diff options
Diffstat (limited to 'client/src/com/vaadin/terminal/gwt')
305 files changed, 6 insertions, 62860 deletions
diff --git a/client/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml b/client/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml index 278d92f38f..8af257fe3c 100644 --- a/client/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml +++ b/client/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml @@ -1,13 +1,9 @@ <module> - <!-- This GWT module defines the Vaadin DefaultWidgetSet. This is the module - you want to extend when creating an extended widget set, or when creating - a specialized widget set with a subset of the components. --> - - <!-- Hint for WidgetSetBuilder not to automatically update the file --> - <!-- WS Compiler: manually edited --> - - <inherits name="com.vaadin.Vaadin" /> - - <entry-point class="com.vaadin.terminal.gwt.client.ApplicationConfiguration" /> + <!-- This GWT module is provided for backwards compatibility only. You + should inherit com.vaadin.DefaultWidgetSet instead. --> + <!-- Hint for WidgetSetBuilder not to automatically update the file --> + <!-- WS Compiler: manually edited --> + <inherits name="com.vaadin.DefaultWidgetSet" /> + </module> diff --git a/client/src/com/vaadin/terminal/gwt/VaadinBrowserSpecificOverrides.gwt.xml b/client/src/com/vaadin/terminal/gwt/VaadinBrowserSpecificOverrides.gwt.xml deleted file mode 100644 index 04d2c18060..0000000000 --- a/client/src/com/vaadin/terminal/gwt/VaadinBrowserSpecificOverrides.gwt.xml +++ /dev/null @@ -1,47 +0,0 @@ -<module> - <!-- This GWT module defines the browser specific overrides used by Vaadin --> - - <!-- Hint for WidgetSetBuilder not to automatically update the file --> - <!-- WS Compiler: manually edited --> - - <!-- Fall through to this rule for everything but IE --> - <replace-with - class="com.vaadin.terminal.gwt.client.ui.upload.UploadIFrameOnloadStrategy"> - <when-type-is - class="com.vaadin.terminal.gwt.client.ui.upload.UploadIFrameOnloadStrategy" /> - </replace-with> - - <replace-with - class="com.vaadin.terminal.gwt.client.ui.upload.UploadIFrameOnloadStrategyIE"> - <when-type-is - class="com.vaadin.terminal.gwt.client.ui.upload.UploadIFrameOnloadStrategy" /> - <any> - <when-property-is name="user.agent" value="ie8" /> - </any> - </replace-with> - - <!-- Fall through to this rule for everything but IE --> - <replace-with class="com.vaadin.terminal.gwt.client.ui.draganddropwrapper.VDragAndDropWrapper"> - <when-type-is class="com.vaadin.terminal.gwt.client.ui.draganddropwrapper.VDragAndDropWrapper" /> - </replace-with> - - <replace-with class="com.vaadin.terminal.gwt.client.ui.draganddropwrapper.VDragAndDropWrapperIE"> - <when-type-is class="com.vaadin.terminal.gwt.client.ui.draganddropwrapper.VDragAndDropWrapper" /> - <any> - <when-property-is name="user.agent" value="ie8" /> - </any> - </replace-with> - - <!-- Fall through to this rule for everything but IE --> - <replace-with class="com.vaadin.terminal.gwt.client.LayoutManager"> - <when-type-is class="com.vaadin.terminal.gwt.client.LayoutManager" /> - </replace-with> - - <replace-with class="com.vaadin.terminal.gwt.client.LayoutManagerIE8"> - <when-type-is class="com.vaadin.terminal.gwt.client.LayoutManager" /> - <any> - <when-property-is name="user.agent" value="ie8" /> - </any> - </replace-with> - -</module> diff --git a/client/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java b/client/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java deleted file mode 100644 index 1150f122b2..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java +++ /dev/null @@ -1,634 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import com.google.gwt.core.client.EntryPoint; -import com.google.gwt.core.client.GWT; -import com.google.gwt.core.client.GWT.UncaughtExceptionHandler; -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.JsArrayString; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.Window; -import com.vaadin.shared.ApplicationConstants; -import com.vaadin.shared.ui.ui.UIConstants; -import com.vaadin.terminal.gwt.client.metadata.BundleLoadCallback; -import com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader; -import com.vaadin.terminal.gwt.client.metadata.NoDataException; -import com.vaadin.terminal.gwt.client.metadata.TypeData; -import com.vaadin.terminal.gwt.client.ui.UnknownComponentConnector; - -public class ApplicationConfiguration implements EntryPoint { - - /** - * Helper class for reading configuration options from the bootstap - * javascript - * - * @since 7.0 - */ - private static class JsoConfiguration extends JavaScriptObject { - protected JsoConfiguration() { - // JSO Constructor - } - - /** - * Reads a configuration parameter as a string. Please note that the - * javascript value of the parameter should also be a string, or else an - * undefined exception may be thrown. - * - * @param name - * name of the configuration parameter - * @return value of the configuration parameter, or <code>null</code> if - * not defined - */ - private native String getConfigString(String name) - /*-{ - var value = this.getConfig(name); - if (value === null || value === undefined) { - return null; - } else { - return value +""; - } - }-*/; - - /** - * Reads a configuration parameter as a boolean object. Please note that - * the javascript value of the parameter should also be a boolean, or - * else an undefined exception may be thrown. - * - * @param name - * name of the configuration parameter - * @return boolean value of the configuration paramter, or - * <code>null</code> if no value is defined - */ - private native Boolean getConfigBoolean(String name) - /*-{ - var value = this.getConfig(name); - if (value === null || value === undefined) { - return null; - } else { - // $entry not needed as function is not exported - return @java.lang.Boolean::valueOf(Z)(value); - } - }-*/; - - /** - * Reads a configuration parameter as an integer object. Please note - * that the javascript value of the parameter should also be an integer, - * or else an undefined exception may be thrown. - * - * @param name - * name of the configuration parameter - * @return integer value of the configuration paramter, or - * <code>null</code> if no value is defined - */ - private native Integer getConfigInteger(String name) - /*-{ - var value = this.getConfig(name); - if (value === null || value === undefined) { - return null; - } else { - // $entry not needed as function is not exported - return @java.lang.Integer::valueOf(I)(value); - } - }-*/; - - /** - * Reads a configuration parameter as an {@link ErrorMessage} object. - * Please note that the javascript value of the parameter should also be - * an object with appropriate fields, or else an undefined exception may - * be thrown when calling this method or when calling methods on the - * returned object. - * - * @param name - * name of the configuration parameter - * @return error message with the given name, or <code>null</code> if no - * value is defined - */ - private native ErrorMessage getConfigError(String name) - /*-{ - return this.getConfig(name); - }-*/; - - /** - * Returns a native javascript object containing version information - * from the server. - * - * @return a javascript object with the version information - */ - private native JavaScriptObject getVersionInfoJSObject() - /*-{ - return this.getConfig("versionInfo"); - }-*/; - - /** - * Gets the version of the Vaadin framework used on the server. - * - * @return a string with the version - * - * @see com.vaadin.terminal.gwt.server.AbstractApplicationServlet#VERSION - */ - private native String getVaadinVersion() - /*-{ - return this.getConfig("versionInfo").vaadinVersion; - }-*/; - - /** - * Gets the version of the application running on the server. - * - * @return a string with the application version - * - * @see com.vaadin.Application#getVersion() - */ - private native String getApplicationVersion() - /*-{ - return this.getConfig("versionInfo").applicationVersion; - }-*/; - - private native String getUIDL() - /*-{ - return this.getConfig("uidl"); - }-*/; - } - - /** - * Wraps a native javascript object containing fields for an error message - * - * @since 7.0 - */ - public static final class ErrorMessage extends JavaScriptObject { - - protected ErrorMessage() { - // JSO constructor - } - - public final native String getCaption() - /*-{ - return this.caption; - }-*/; - - public final native String getMessage() - /*-{ - return this.message; - }-*/; - - public final native String getUrl() - /*-{ - return this.url; - }-*/; - } - - private static WidgetSet widgetSet = GWT.create(WidgetSet.class); - - private String id; - private String themeUri; - private String appUri; - private int uiId; - private boolean standalone; - private ErrorMessage communicationError; - private ErrorMessage authorizationError; - private int heartbeatInterval; - - private HashMap<Integer, String> unknownComponents; - - private Map<Integer, Class<? extends ServerConnector>> classes = new HashMap<Integer, Class<? extends ServerConnector>>(); - - private boolean browserDetailsSent = false; - private boolean widgetsetVersionSent = false; - - static// TODO consider to make this hashmap per application - LinkedList<Command> callbacks = new LinkedList<Command>(); - - private static int dependenciesLoading; - - private static ArrayList<ApplicationConnection> runningApplications = new ArrayList<ApplicationConnection>(); - - private Map<Integer, Integer> componentInheritanceMap = new HashMap<Integer, Integer>(); - private Map<Integer, String> tagToServerSideClassName = new HashMap<Integer, String>(); - - public boolean usePortletURLs() { - return getPortletResourceUrl() != null; - } - - public String getPortletResourceUrl() { - return getJsoConfiguration(id).getConfigString( - ApplicationConstants.PORTLET_RESOUCE_URL_BASE); - } - - public String getRootPanelId() { - return id; - } - - /** - * Gets the application base URI. Using this other than as the download - * action URI can cause problems in Portlet 2.0 deployments. - * - * @return application base URI - */ - public String getApplicationUri() { - return appUri; - } - - public String getThemeName() { - String uri = getThemeUri(); - String themeName = uri.substring(uri.lastIndexOf('/')); - themeName = themeName.replaceAll("[^a-zA-Z0-9]", ""); - return themeName; - } - - public String getThemeUri() { - return themeUri; - } - - public void setAppId(String appId) { - id = appId; - } - - /** - * Gets the initial UIDL from the DOM, if it was provided during the init - * process. - * - * @return - */ - public String getUIDL() { - return getJsoConfiguration(id).getUIDL(); - } - - /** - * @return true if the application is served by std. Vaadin servlet and is - * considered to be the only or main content of the host page. - */ - public boolean isStandalone() { - return standalone; - } - - /** - * Gets the root if of this application instance. The root id should be - * included in every request originating from this instance in order to - * associate it with the right UI instance on the server. - * - * @return the root id - */ - public int getUIId() { - return uiId; - } - - /** - * @return The interval in seconds between heartbeat requests, or a - * non-positive number if heartbeat is disabled. - */ - public int getHeartbeatInterval() { - return heartbeatInterval; - } - - public JavaScriptObject getVersionInfoJSObject() { - return getJsoConfiguration(id).getVersionInfoJSObject(); - } - - public ErrorMessage getCommunicationError() { - return communicationError; - } - - public ErrorMessage getAuthorizationError() { - return authorizationError; - } - - /** - * Reads the configuration values defined by the bootstrap javascript. - */ - private void loadFromDOM() { - JsoConfiguration jsoConfiguration = getJsoConfiguration(id); - appUri = jsoConfiguration.getConfigString("appUri"); - if (appUri != null && !appUri.endsWith("/")) { - appUri += '/'; - } - themeUri = jsoConfiguration.getConfigString("themeUri"); - uiId = jsoConfiguration.getConfigInteger(UIConstants.UI_ID_PARAMETER) - .intValue(); - - // null -> false - standalone = jsoConfiguration.getConfigBoolean("standalone") == Boolean.TRUE; - - heartbeatInterval = jsoConfiguration - .getConfigInteger("heartbeatInterval"); - - communicationError = jsoConfiguration.getConfigError("comErrMsg"); - authorizationError = jsoConfiguration.getConfigError("authErrMsg"); - - // boostrap sets initPending to false if it has sent the browser details - if (jsoConfiguration.getConfigBoolean("initPending") == Boolean.FALSE) { - setBrowserDetailsSent(); - } - - } - - /** - * Starts the application with a given id by reading the configuration - * options stored by the bootstrap javascript. - * - * @param applicationId - * id of the application to load, this is also the id of the html - * element into which the application should be rendered. - */ - public static void startApplication(final String applicationId) { - Scheduler.get().scheduleDeferred(new ScheduledCommand() { - - @Override - public void execute() { - ApplicationConfiguration appConf = getConfigFromDOM(applicationId); - ApplicationConnection a = GWT - .create(ApplicationConnection.class); - a.init(widgetSet, appConf); - a.start(); - runningApplications.add(a); - } - }); - } - - public static List<ApplicationConnection> getRunningApplications() { - return runningApplications; - } - - /** - * Gets the configuration object for a specific application from the - * bootstrap javascript. - * - * @param appId - * the id of the application to get configuration data for - * @return a native javascript object containing the configuration data - */ - private native static JsoConfiguration getJsoConfiguration(String appId) - /*-{ - return $wnd.vaadin.getApp(appId); - }-*/; - - public static ApplicationConfiguration getConfigFromDOM(String appId) { - ApplicationConfiguration conf = new ApplicationConfiguration(); - conf.setAppId(appId); - conf.loadFromDOM(); - return conf; - } - - public String getServletVersion() { - return getJsoConfiguration(id).getVaadinVersion(); - } - - public String getApplicationVersion() { - return getJsoConfiguration(id).getApplicationVersion(); - } - - public Class<? extends ServerConnector> getConnectorClassByEncodedTag( - int tag) { - Class<? extends ServerConnector> type = classes.get(tag); - if (type == null && !classes.containsKey(tag)) { - // Initialize if not already loaded - Integer currentTag = Integer.valueOf(tag); - while (type == null && currentTag != null) { - String serverSideClassNameForTag = getServerSideClassNameForTag(currentTag); - if (TypeData.hasIdentifier(serverSideClassNameForTag)) { - try { - type = (Class<? extends ServerConnector>) TypeData - .getClass(serverSideClassNameForTag); - } catch (NoDataException e) { - throw new RuntimeException(e); - } - } - currentTag = getParentTag(currentTag.intValue()); - } - if (type == null) { - type = UnknownComponentConnector.class; - if (unknownComponents == null) { - unknownComponents = new HashMap<Integer, String>(); - } - unknownComponents.put(tag, getServerSideClassNameForTag(tag)); - } - classes.put(tag, type); - } - return type; - } - - public void addComponentInheritanceInfo(ValueMap valueMap) { - JsArrayString keyArray = valueMap.getKeyArray(); - for (int i = 0; i < keyArray.length(); i++) { - String key = keyArray.get(i); - int value = valueMap.getInt(key); - componentInheritanceMap.put(Integer.parseInt(key), value); - } - } - - public void addComponentMappings(ValueMap valueMap, WidgetSet widgetSet) { - JsArrayString keyArray = valueMap.getKeyArray(); - for (int i = 0; i < keyArray.length(); i++) { - String key = keyArray.get(i).intern(); - int value = valueMap.getInt(key); - tagToServerSideClassName.put(value, key); - } - - for (int i = 0; i < keyArray.length(); i++) { - String key = keyArray.get(i).intern(); - int value = valueMap.getInt(key); - widgetSet.ensureConnectorLoaded(value, this); - } - } - - public Integer getParentTag(int tag) { - return componentInheritanceMap.get(tag); - } - - public String getServerSideClassNameForTag(Integer tag) { - return tagToServerSideClassName.get(tag); - } - - String getUnknownServerClassNameByTag(int tag) { - if (unknownComponents != null) { - return unknownComponents.get(tag); - } - return null; - } - - /** - * - * @param c - */ - static void runWhenDependenciesLoaded(Command c) { - if (dependenciesLoading == 0) { - c.execute(); - } else { - callbacks.add(c); - } - } - - static void startDependencyLoading() { - dependenciesLoading++; - } - - static void endDependencyLoading() { - dependenciesLoading--; - if (dependenciesLoading == 0 && !callbacks.isEmpty()) { - for (Command cmd : callbacks) { - cmd.execute(); - } - callbacks.clear(); - } else if (dependenciesLoading == 0 - && !ConnectorBundleLoader.get().isBundleLoaded( - ConnectorBundleLoader.DEFERRED_BUNDLE_NAME)) { - ConnectorBundleLoader.get().loadBundle( - ConnectorBundleLoader.DEFERRED_BUNDLE_NAME, - new BundleLoadCallback() { - @Override - public void loaded() { - // Nothing to do - } - - @Override - public void failed(Throwable reason) { - VConsole.error(reason); - } - }); - } - } - - @Override - public void onModuleLoad() { - - // Prepare VConsole for debugging - if (isDebugMode()) { - Console console = GWT.create(Console.class); - console.setQuietMode(isQuietDebugMode()); - console.init(); - VConsole.setImplementation(console); - } else { - VConsole.setImplementation((Console) GWT.create(NullConsole.class)); - } - /* - * Display some sort of error of exceptions in web mode to debug - * console. After this, exceptions are reported to VConsole and possible - * GWT hosted mode. - */ - GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { - - @Override - public void onUncaughtException(Throwable e) { - /* - * Note in case of null console (without ?debug) we eat - * exceptions. "a1 is not an object" style errors helps nobody, - * especially end user. It does not work tells just as much. - */ - VConsole.getImplementation().error(e); - } - }); - - if (SuperDevMode.enableBasedOnParameter()) { - // Do not start any application as super dev mode will refresh the - // page once done compiling - return; - } - registerCallback(GWT.getModuleName()); - } - - /** - * Registers that callback that the bootstrap javascript uses to start - * applications once the widgetset is loaded and all required information is - * available - * - * @param widgetsetName - * the name of this widgetset - */ - public native static void registerCallback(String widgetsetName) - /*-{ - var callbackHandler = $entry(@com.vaadin.terminal.gwt.client.ApplicationConfiguration::startApplication(Ljava/lang/String;)); - $wnd.vaadin.registerWidgetset(widgetsetName, callbackHandler); - }-*/; - - /** - * Checks if client side is in debug mode. Practically this is invoked by - * adding ?debug parameter to URI. - * - * @return true if client side is currently been debugged - */ - public static boolean isDebugMode() { - return isDebugAvailable() - && Window.Location.getParameter("debug") != null; - } - - private native static boolean isDebugAvailable() - /*-{ - if($wnd.vaadin.debug) { - return true; - } else { - return false; - } - }-*/; - - /** - * Checks whether debug logging should be quiet - * - * @return <code>true</code> if debug logging should be quiet - */ - public static boolean isQuietDebugMode() { - String debugParameter = Window.Location.getParameter("debug"); - return isDebugAvailable() && debugParameter != null - && debugParameter.startsWith("q"); - } - - /** - * Checks whether information from the web browser (e.g. uri fragment and - * screen size) has been sent to the server. - * - * @return <code>true</code> if browser information has already been sent - * - * @see ApplicationConnection#getNativeBrowserDetailsParameters(String) - */ - public boolean isBrowserDetailsSent() { - return browserDetailsSent; - } - - /** - * Registers that the browser details have been sent. - * {@link #isBrowserDetailsSent()} will return - * <code> after this method has been invoked. - */ - public void setBrowserDetailsSent() { - browserDetailsSent = true; - } - - /** - * Checks whether the widget set version has been sent to the server. It is - * sent in the first UIDL request. - * - * @return <code>true</code> if browser information has already been sent - * - * @see ApplicationConnection#getNativeBrowserDetailsParameters(String) - */ - public boolean isWidgetsetVersionSent() { - return widgetsetVersionSent; - } - - /** - * Registers that the widget set version has been sent to the server. - */ - public void setWidgetsetVersionSent() { - widgetsetVersionSent = true; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java deleted file mode 100644 index da41df5303..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ /dev/null @@ -1,2857 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.google.gwt.core.client.Duration; -import com.google.gwt.core.client.GWT; -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.JsArray; -import com.google.gwt.core.client.JsArrayString; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.http.client.Request; -import com.google.gwt.http.client.RequestBuilder; -import com.google.gwt.http.client.RequestCallback; -import com.google.gwt.http.client.RequestException; -import com.google.gwt.http.client.Response; -import com.google.gwt.http.client.URL; -import com.google.gwt.json.client.JSONArray; -import com.google.gwt.json.client.JSONObject; -import com.google.gwt.json.client.JSONString; -import com.google.gwt.regexp.shared.MatchResult; -import com.google.gwt.regexp.shared.RegExp; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.ui.HasWidgets; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ApplicationConstants; -import com.vaadin.shared.ComponentState; -import com.vaadin.shared.Version; -import com.vaadin.shared.communication.LegacyChangeVariablesInvocation; -import com.vaadin.shared.communication.MethodInvocation; -import com.vaadin.shared.communication.SharedState; -import com.vaadin.shared.ui.ui.UIConstants; -import com.vaadin.terminal.gwt.client.ApplicationConfiguration.ErrorMessage; -import com.vaadin.terminal.gwt.client.ResourceLoader.ResourceLoadEvent; -import com.vaadin.terminal.gwt.client.ResourceLoader.ResourceLoadListener; -import com.vaadin.terminal.gwt.client.communication.HasJavaScriptConnectorHelper; -import com.vaadin.terminal.gwt.client.communication.JsonDecoder; -import com.vaadin.terminal.gwt.client.communication.JsonEncoder; -import com.vaadin.terminal.gwt.client.communication.RpcManager; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.extensions.AbstractExtensionConnector; -import com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader; -import com.vaadin.terminal.gwt.client.metadata.NoDataException; -import com.vaadin.terminal.gwt.client.metadata.Property; -import com.vaadin.terminal.gwt.client.metadata.Type; -import com.vaadin.terminal.gwt.client.metadata.TypeData; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; -import com.vaadin.terminal.gwt.client.ui.AbstractConnector; -import com.vaadin.terminal.gwt.client.ui.VContextMenu; -import com.vaadin.terminal.gwt.client.ui.UI.UIConnector; -import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager; -import com.vaadin.terminal.gwt.client.ui.notification.VNotification; -import com.vaadin.terminal.gwt.client.ui.notification.VNotification.HideEvent; -import com.vaadin.terminal.gwt.client.ui.window.WindowConnector; - -/** - * This is the client side communication "engine", managing client-server - * communication with its server side counterpart - * com.vaadin.terminal.gwt.server.AbstractCommunicationManager. - * - * Client-side connectors receive updates from the corresponding server-side - * connector (typically component) as state updates or RPC calls. The connector - * has the possibility to communicate back with its server side counter part - * through RPC calls. - * - * TODO document better - * - * Entry point classes (widgetsets) define <code>onModuleLoad()</code>. - */ -public class ApplicationConnection { - - public static final String MODIFIED_CLASSNAME = "v-modified"; - - public static final String DISABLED_CLASSNAME = "v-disabled"; - - public static final String REQUIRED_CLASSNAME_EXT = "-required"; - - public static final String ERROR_CLASSNAME_EXT = "-error"; - - public static final char VAR_BURST_SEPARATOR = '\u001d'; - - public static final char VAR_ESCAPE_CHARACTER = '\u001b'; - - /** - * A string that, if found in a non-JSON response to a UIDL request, will - * cause the browser to refresh the page. If followed by a colon, optional - * whitespace, and a URI, causes the browser to synchronously load the URI. - * - * <p> - * This allows, for instance, a servlet filter to redirect the application - * to a custom login page when the session expires. For example: - * </p> - * - * <pre> - * if (sessionExpired) { - * response.setHeader("Content-Type", "text/html"); - * response.getWriter().write( - * myLoginPageHtml + "<!-- Vaadin-Refresh: " - * + request.getContextPath() + " -->"); - * } - * </pre> - */ - public static final String UIDL_REFRESH_TOKEN = "Vaadin-Refresh"; - - // will hold the UIDL security key (for XSS protection) once received - private String uidlSecurityKey = "init"; - - private final HashMap<String, String> resourcesMap = new HashMap<String, String>(); - - /** - * The pending method invocations that will be send to the server by - * {@link #sendPendingCommand}. The key is defined differently based on - * whether the method invocation is enqueued with lastonly. With lastonly - * enabled, the method signature ( {@link MethodInvocation#getLastonlyTag()} - * ) is used as the key to make enable removing a previously enqueued - * invocation. Without lastonly, an incremental id based on - * {@link #lastInvocationTag} is used to get unique values. - */ - private LinkedHashMap<String, MethodInvocation> pendingInvocations = new LinkedHashMap<String, MethodInvocation>(); - - private int lastInvocationTag = 0; - - private WidgetSet widgetSet; - - private VContextMenu contextMenu = null; - - private Timer loadTimer; - private Timer loadTimer2; - private Timer loadTimer3; - private Element loadElement; - - private final UIConnector uIConnector; - - protected boolean applicationRunning = false; - - private boolean hasActiveRequest = false; - - protected boolean cssLoaded = false; - - /** Parameters for this application connection loaded from the web-page */ - private ApplicationConfiguration configuration; - - /** List of pending variable change bursts that must be submitted in order */ - private final ArrayList<LinkedHashMap<String, MethodInvocation>> pendingBursts = new ArrayList<LinkedHashMap<String, MethodInvocation>>(); - - /** Timer for automatic refirect to SessionExpiredURL */ - private Timer redirectTimer; - - /** redirectTimer scheduling interval in seconds */ - private int sessionExpirationInterval; - - private ArrayList<Widget> componentCaptionSizeChanges = new ArrayList<Widget>(); - - private Date requestStartTime; - - private boolean validatingLayouts = false; - - private Set<ComponentConnector> zeroWidthComponents = null; - - private Set<ComponentConnector> zeroHeightComponents = null; - - private final LayoutManager layoutManager; - - private final RpcManager rpcManager; - - /** - * If renderingLocks contains any objects, rendering is to be suspended - * until the collection is empty or a timeout has occurred. - */ - private Set<Object> renderingLocks = new HashSet<Object>(); - - /** - * Data structure holding information about pending UIDL messages. - */ - private class PendingUIDLMessage { - private Date start; - private String jsonText; - private ValueMap json; - - public PendingUIDLMessage(Date start, String jsonText, ValueMap json) { - this.start = start; - this.jsonText = jsonText; - this.json = json; - } - - public Date getStart() { - return start; - } - - public String getJsonText() { - return jsonText; - } - - public ValueMap getJson() { - return json; - } - } - - /** Contains all UIDL messages received while the rendering is suspended */ - private List<PendingUIDLMessage> pendingUIDLMessages = new ArrayList<PendingUIDLMessage>(); - - /** The max timeout the rendering phase may be suspended */ - private static final int MAX_SUSPENDED_TIMEOUT = 5000; - - public static class MultiStepDuration extends Duration { - private int previousStep = elapsedMillis(); - - public void logDuration(String message) { - logDuration(message, 0); - } - - public void logDuration(String message, int minDuration) { - int currentTime = elapsedMillis(); - int stepDuration = currentTime - previousStep; - if (stepDuration >= minDuration) { - VConsole.log(message + ": " + stepDuration + " ms"); - } - previousStep = currentTime; - } - } - - public ApplicationConnection() { - // Assuming UI data is eagerly loaded - ConnectorBundleLoader.get().loadBundle( - ConnectorBundleLoader.EAGER_BUNDLE_NAME, null); - uIConnector = GWT.create(UIConnector.class); - rpcManager = GWT.create(RpcManager.class); - layoutManager = GWT.create(LayoutManager.class); - layoutManager.setConnection(this); - } - - public void init(WidgetSet widgetSet, ApplicationConfiguration cnf) { - VConsole.log("Starting application " + cnf.getRootPanelId()); - - VConsole.log("Vaadin application servlet version: " - + cnf.getServletVersion()); - VConsole.log("Application version: " + cnf.getApplicationVersion()); - - if (!cnf.getServletVersion().equals(Version.getFullVersion())) { - VConsole.error("Warning: your widget set seems to be built with a different " - + "version than the one used on server. Unexpected " - + "behavior may occur."); - } - - this.widgetSet = widgetSet; - configuration = cnf; - - ComponentLocator componentLocator = new ComponentLocator(this); - - String appRootPanelName = cnf.getRootPanelId(); - // remove the end (window name) of autogenerated rootpanel id - appRootPanelName = appRootPanelName.replaceFirst("-\\d+$", ""); - - initializeTestbenchHooks(componentLocator, appRootPanelName); - - initializeClientHooks(); - - uIConnector.init(cnf.getRootPanelId(), this); - showLoadingIndicator(); - - scheduleHeartbeat(); - } - - /** - * Starts this application. Don't call this method directly - it's called by - * {@link ApplicationConfiguration#startNextApplication()}, which should be - * called once this application has started (first response received) or - * failed to start. This ensures that the applications are started in order, - * to avoid session-id problems. - * - */ - public void start() { - String jsonText = configuration.getUIDL(); - if (jsonText == null) { - // inital UIDL not in DOM, request later - repaintAll(); - } else { - // Update counter so TestBench knows something is still going on - hasActiveRequest = true; - - // initial UIDL provided in DOM, continue as if returned by request - handleJSONText(jsonText, -1); - } - } - - private native void initializeTestbenchHooks( - ComponentLocator componentLocator, String TTAppId) - /*-{ - var ap = this; - var client = {}; - client.isActive = $entry(function() { - return ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::hasActiveRequest()() - || ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::isExecutingDeferredCommands()(); - }); - var vi = ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::getVersionInfo()(); - if (vi) { - client.getVersionInfo = function() { - return vi; - } - } - - client.getProfilingData = $entry(function() { - var pd = [ - ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::lastProcessingTime, - ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::totalProcessingTime - ]; - pd = pd.concat(ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::serverTimingInfo); - return pd; - }); - - client.getElementByPath = $entry(function(id) { - return componentLocator.@com.vaadin.terminal.gwt.client.ComponentLocator::getElementByPath(Ljava/lang/String;)(id); - }); - client.getPathForElement = $entry(function(element) { - return componentLocator.@com.vaadin.terminal.gwt.client.ComponentLocator::getPathForElement(Lcom/google/gwt/user/client/Element;)(element); - }); - - $wnd.vaadin.clients[TTAppId] = client; - }-*/; - - /** - * Helper for tt initialization - */ - private JavaScriptObject getVersionInfo() { - return configuration.getVersionInfoJSObject(); - } - - /** - * Publishes a JavaScript API for mash-up applications. - * <ul> - * <li><code>vaadin.forceSync()</code> sends pending variable changes, in - * effect synchronizing the server and client state. This is done for all - * applications on host page.</li> - * <li><code>vaadin.postRequestHooks</code> is a map of functions which gets - * called after each XHR made by vaadin application. Note, that it is - * attaching js functions responsibility to create the variable like this: - * - * <code><pre> - * if(!vaadin.postRequestHooks) {vaadin.postRequestHooks = new Object();} - * postRequestHooks.myHook = function(appId) { - * if(appId == "MyAppOfInterest") { - * // do the staff you need on xhr activity - * } - * } - * </pre></code> First parameter passed to these functions is the identifier - * of Vaadin application that made the request. - * </ul> - * - * TODO make this multi-app aware - */ - private native void initializeClientHooks() - /*-{ - var app = this; - var oldSync; - if ($wnd.vaadin.forceSync) { - oldSync = $wnd.vaadin.forceSync; - } - $wnd.vaadin.forceSync = $entry(function() { - if (oldSync) { - oldSync(); - } - app.@com.vaadin.terminal.gwt.client.ApplicationConnection::sendPendingVariableChanges()(); - }); - var oldForceLayout; - if ($wnd.vaadin.forceLayout) { - oldForceLayout = $wnd.vaadin.forceLayout; - } - $wnd.vaadin.forceLayout = $entry(function() { - if (oldForceLayout) { - oldForceLayout(); - } - app.@com.vaadin.terminal.gwt.client.ApplicationConnection::forceLayout()(); - }); - }-*/; - - /** - * Runs possibly registered client side post request hooks. This is expected - * to be run after each uidl request made by Vaadin application. - * - * @param appId - */ - private static native void runPostRequestHooks(String appId) - /*-{ - if ($wnd.vaadin.postRequestHooks) { - for ( var hook in $wnd.vaadin.postRequestHooks) { - if (typeof ($wnd.vaadin.postRequestHooks[hook]) == "function") { - try { - $wnd.vaadin.postRequestHooks[hook](appId); - } catch (e) { - } - } - } - } - }-*/; - - /** - * If on Liferay and logged in, ask the client side session management - * JavaScript to extend the session duration. - * - * Otherwise, Liferay client side JavaScript will explicitly expire the - * session even though the server side considers the session to be active. - * See ticket #8305 for more information. - */ - protected native void extendLiferaySession() - /*-{ - if ($wnd.Liferay && $wnd.Liferay.Session) { - $wnd.Liferay.Session.extend(); - // if the extend banner is visible, hide it - if ($wnd.Liferay.Session.banner) { - $wnd.Liferay.Session.banner.remove(); - } - } - }-*/; - - /** - * Gets the application base URI. Using this other than as the download - * action URI can cause problems in Portlet 2.0 deployments. - * - * @return application base URI - */ - public String getAppUri() { - return configuration.getApplicationUri(); - }; - - /** - * Indicates whether or not there are currently active UIDL requests. Used - * internally to sequence requests properly, seldom needed in Widgets. - * - * @return true if there are active requests - */ - public boolean hasActiveRequest() { - return hasActiveRequest; - } - - private String getRepaintAllParameters() { - // collect some client side data that will be sent to server on - // initial uidl request - String nativeBootstrapParameters = getNativeBrowserDetailsParameters(getConfiguration() - .getRootPanelId()); - // TODO figure out how client and view size could be used better on - // server. screen size can be accessed via Browser object, but other - // values currently only via transaction listener. - String parameters = "repaintAll=1&" + nativeBootstrapParameters; - return parameters; - } - - /** - * Gets the browser detail parameters that are sent by the bootstrap - * javascript for two-request initialization. - * - * @param parentElementId - * @return - */ - private static native String getNativeBrowserDetailsParameters( - String parentElementId) - /*-{ - return $wnd.vaadin.getBrowserDetailsParameters(parentElementId); - }-*/; - - protected void repaintAll() { - String repainAllParameters = getRepaintAllParameters(); - makeUidlRequest("", repainAllParameters, false); - } - - /** - * Requests an analyze of layouts, to find inconsistencies. Exclusively used - * for debugging during development. - */ - public void analyzeLayouts() { - String params = getRepaintAllParameters() + "&analyzeLayouts=1"; - makeUidlRequest("", params, false); - } - - /** - * Sends a request to the server to print details to console that will help - * developer to locate component in the source code. - * - * @param componentConnector - */ - void highlightComponent(ComponentConnector componentConnector) { - String params = getRepaintAllParameters() + "&highlightComponent=" - + componentConnector.getConnectorId(); - makeUidlRequest("", params, false); - } - - /** - * Makes an UIDL request to the server. - * - * @param requestData - * Data that is passed to the server. - * @param extraParams - * Parameters that are added as GET parameters to the url. - * Contains key=value pairs joined by & characters or is empty if - * no parameters should be added. Should not start with any - * special character. - * @param forceSync - * true if the request should be synchronous, false otherwise - */ - protected void makeUidlRequest(final String requestData, - final String extraParams, final boolean forceSync) { - startRequest(); - // Security: double cookie submission pattern - final String payload = uidlSecurityKey + VAR_BURST_SEPARATOR - + requestData; - VConsole.log("Making UIDL Request with params: " + payload); - String uri = translateVaadinUri(ApplicationConstants.APP_PROTOCOL_PREFIX - + ApplicationConstants.UIDL_REQUEST_PATH); - - if (extraParams != null && extraParams.length() > 0) { - uri = addGetParameters(uri, extraParams); - } - uri = addGetParameters(uri, UIConstants.UI_ID_PARAMETER + "=" - + configuration.getUIId()); - - doUidlRequest(uri, payload, forceSync); - - } - - /** - * Sends an asynchronous or synchronous UIDL request to the server using the - * given URI. - * - * @param uri - * The URI to use for the request. May includes GET parameters - * @param payload - * The contents of the request to send - * @param synchronous - * true if the request should be synchronous, false otherwise - */ - protected void doUidlRequest(final String uri, final String payload, - final boolean synchronous) { - if (!synchronous) { - RequestCallback requestCallback = new RequestCallback() { - @Override - public void onError(Request request, Throwable exception) { - showCommunicationError(exception.getMessage(), -1); - endRequest(); - } - - @Override - public void onResponseReceived(Request request, - Response response) { - VConsole.log("Server visit took " - + String.valueOf((new Date()).getTime() - - requestStartTime.getTime()) + "ms"); - - int statusCode = response.getStatusCode(); - - switch (statusCode) { - case 0: - showCommunicationError( - "Invalid status code 0 (server down?)", - statusCode); - endRequest(); - return; - - case 401: - /* - * Authorization has failed. Could be that the session - * has timed out and the container is redirecting to a - * login page. - */ - showAuthenticationError(""); - endRequest(); - return; - - case 503: - /* - * We'll assume msec instead of the usual seconds. If - * there's no Retry-After header, handle the error like - * a 500, as per RFC 2616 section 10.5.4. - */ - String delay = response.getHeader("Retry-After"); - if (delay != null) { - VConsole.log("503, retrying in " + delay + "msec"); - (new Timer() { - @Override - public void run() { - doUidlRequest(uri, payload, synchronous); - } - }).schedule(Integer.parseInt(delay)); - return; - } - } - - if ((statusCode / 100) == 4) { - // Handle all 4xx errors the same way as (they are - // all permanent errors) - showCommunicationError( - "UIDL could not be read from server. Check servlets mappings. Error code: " - + statusCode, statusCode); - endRequest(); - return; - } else if ((statusCode / 100) == 5) { - // Something's wrong on the server, there's nothing the - // client can do except maybe try again. - showCommunicationError("Server error. Error code: " - + statusCode, statusCode); - endRequest(); - return; - } - - String contentType = response.getHeader("Content-Type"); - if (contentType == null - || !contentType.startsWith("application/json")) { - /* - * A servlet filter or equivalent may have intercepted - * the request and served non-UIDL content (for - * instance, a login page if the session has expired.) - * If the response contains a magic substring, do a - * synchronous refresh. See #8241. - */ - MatchResult refreshToken = RegExp.compile( - UIDL_REFRESH_TOKEN + "(:\\s*(.*?))?(\\s|$)") - .exec(response.getText()); - if (refreshToken != null) { - redirect(refreshToken.getGroup(2)); - return; - } - } - - // for(;;);[realjson] - final String jsonText = response.getText().substring(9, - response.getText().length() - 1); - handleJSONText(jsonText, statusCode); - } - - }; - try { - doAsyncUIDLRequest(uri, payload, requestCallback); - } catch (RequestException e) { - VConsole.error(e); - endRequest(); - } - } else { - // Synchronized call, discarded response (leaving the page) - SynchronousXHR syncXHR = (SynchronousXHR) SynchronousXHR.create(); - syncXHR.synchronousPost(uri + "&" - + ApplicationConstants.PARAM_UNLOADBURST + "=1", payload); - /* - * Although we are in theory leaving the page, the page may still - * stay open. End request properly here too. See #3289 - */ - endRequest(); - } - - } - - /** - * Handles received UIDL JSON text, parsing it, and passing it on to the - * appropriate handlers, while logging timiing information. - * - * @param jsonText - * @param statusCode - */ - private void handleJSONText(String jsonText, int statusCode) { - final Date start = new Date(); - final ValueMap json; - try { - json = parseJSONResponse(jsonText); - } catch (final Exception e) { - endRequest(); - showCommunicationError(e.getMessage() + " - Original JSON-text:" - + jsonText, statusCode); - return; - } - - VConsole.log("JSON parsing took " - + (new Date().getTime() - start.getTime()) + "ms"); - if (applicationRunning) { - handleReceivedJSONMessage(start, jsonText, json); - } else { - applicationRunning = true; - handleWhenCSSLoaded(jsonText, json); - } - } - - /** - * Sends an asynchronous UIDL request to the server using the given URI. - * - * @param uri - * The URI to use for the request. May includes GET parameters - * @param payload - * The contents of the request to send - * @param requestCallback - * The handler for the response - * @throws RequestException - * if the request could not be sent - */ - protected void doAsyncUIDLRequest(String uri, String payload, - RequestCallback requestCallback) throws RequestException { - RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, uri); - // TODO enable timeout - // rb.setTimeoutMillis(timeoutMillis); - rb.setHeader("Content-Type", "text/plain;charset=utf-8"); - rb.setRequestData(payload); - rb.setCallback(requestCallback); - - rb.send(); - } - - int cssWaits = 0; - - /** - * Holds the time spent rendering the last request - */ - protected int lastProcessingTime; - - /** - * Holds the total time spent rendering requests during the lifetime of the - * session. - */ - protected int totalProcessingTime; - - /** - * Holds the timing information from the server-side. How much time was - * spent servicing the last request and how much time has been spent - * servicing the session so far. These values are always one request behind, - * since they cannot be measured before the request is finished. - */ - private ValueMap serverTimingInfo; - - static final int MAX_CSS_WAITS = 100; - - protected void handleWhenCSSLoaded(final String jsonText, - final ValueMap json) { - if (!isCSSLoaded() && cssWaits < MAX_CSS_WAITS) { - (new Timer() { - @Override - public void run() { - handleWhenCSSLoaded(jsonText, json); - } - }).schedule(50); - VConsole.log("Assuming CSS loading is not complete, " - + "postponing render phase. " - + "(.v-loading-indicator height == 0)"); - cssWaits++; - } else { - cssLoaded = true; - handleReceivedJSONMessage(new Date(), jsonText, json); - if (cssWaits >= MAX_CSS_WAITS) { - VConsole.error("CSS files may have not loaded properly."); - } - } - } - - /** - * Checks whether or not the CSS is loaded. By default checks the size of - * the loading indicator element. - * - * @return - */ - protected boolean isCSSLoaded() { - return cssLoaded - || DOM.getElementPropertyInt(loadElement, "offsetHeight") != 0; - } - - /** - * Shows the communication error notification. - * - * @param details - * Optional details for debugging. - * @param statusCode - * The status code returned for the request - * - */ - protected void showCommunicationError(String details, int statusCode) { - VConsole.error("Communication error: " + details); - ErrorMessage communicationError = configuration.getCommunicationError(); - showError(details, communicationError.getCaption(), - communicationError.getMessage(), communicationError.getUrl()); - } - - /** - * Shows the authentication error notification. - * - * @param details - * Optional details for debugging. - */ - protected void showAuthenticationError(String details) { - VConsole.error("Authentication error: " + details); - ErrorMessage authorizationError = configuration.getAuthorizationError(); - showError(details, authorizationError.getCaption(), - authorizationError.getMessage(), authorizationError.getUrl()); - } - - /** - * Shows the error notification. - * - * @param details - * Optional details for debugging. - */ - private void showError(String details, String caption, String message, - String url) { - - StringBuilder html = new StringBuilder(); - if (caption != null) { - html.append("<h1>"); - html.append(caption); - html.append("</h1>"); - } - if (message != null) { - html.append("<p>"); - html.append(message); - html.append("</p>"); - } - - if (html.length() > 0) { - - // Add error description - html.append("<br/><p><I style=\"font-size:0.7em\">"); - html.append(details); - html.append("</I></p>"); - - VNotification n = VNotification.createNotification(1000 * 60 * 45); - n.addEventListener(new NotificationRedirect(url)); - n.show(html.toString(), VNotification.CENTERED_TOP, - VNotification.STYLE_SYSTEM); - } else { - redirect(url); - } - } - - protected void startRequest() { - if (hasActiveRequest) { - VConsole.error("Trying to start a new request while another is active"); - } - hasActiveRequest = true; - requestStartTime = new Date(); - // show initial throbber - if (loadTimer == null) { - loadTimer = new Timer() { - @Override - public void run() { - /* - * IE7 does not properly cancel the event with - * loadTimer.cancel() so we have to check that we really - * should make it visible - */ - if (loadTimer != null) { - showLoadingIndicator(); - } - - } - }; - // First one kicks in at 300ms - } - loadTimer.schedule(300); - } - - protected void endRequest() { - if (!hasActiveRequest) { - VConsole.error("No active request"); - } - // After checkForPendingVariableBursts() there may be a new active - // request, so we must set hasActiveRequest to false before, not after, - // the call. Active requests used to be tracked with an integer counter, - // so setting it after used to work but not with the #8505 changes. - hasActiveRequest = false; - if (applicationRunning) { - checkForPendingVariableBursts(); - runPostRequestHooks(configuration.getRootPanelId()); - } - // deferring to avoid flickering - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - if (!hasActiveRequest()) { - hideLoadingIndicator(); - - // If on Liferay and session expiration management is in - // use, extend session duration on each request. - // Doing it here rather than before the request to improve - // responsiveness. - // Postponed until the end of the next request if other - // requests still pending. - extendLiferaySession(); - } - } - }); - } - - /** - * This method is called after applying uidl change set to application. - * - * It will clean current and queued variable change sets. And send next - * change set if it exists. - */ - private void checkForPendingVariableBursts() { - cleanVariableBurst(pendingInvocations); - if (pendingBursts.size() > 0) { - for (LinkedHashMap<String, MethodInvocation> pendingBurst : pendingBursts) { - cleanVariableBurst(pendingBurst); - } - LinkedHashMap<String, MethodInvocation> nextBurst = pendingBursts - .remove(0); - buildAndSendVariableBurst(nextBurst, false); - } - } - - /** - * Cleans given queue of variable changes of such changes that came from - * components that do not exist anymore. - * - * @param variableBurst - */ - private void cleanVariableBurst( - LinkedHashMap<String, MethodInvocation> variableBurst) { - Iterator<MethodInvocation> iterator = variableBurst.values().iterator(); - while (iterator.hasNext()) { - String id = iterator.next().getConnectorId(); - if (!getConnectorMap().hasConnector(id) - && !getConnectorMap().isDragAndDropPaintable(id)) { - // variable owner does not exist anymore - iterator.remove(); - VConsole.log("Removed variable from removed component: " + id); - } - } - } - - private void showLoadingIndicator() { - // show initial throbber - if (loadElement == null) { - loadElement = DOM.createDiv(); - DOM.setStyleAttribute(loadElement, "position", "absolute"); - DOM.appendChild(uIConnector.getWidget().getElement(), loadElement); - VConsole.log("inserting load indicator"); - } - DOM.setElementProperty(loadElement, "className", "v-loading-indicator"); - DOM.setStyleAttribute(loadElement, "display", "block"); - // Initialize other timers - loadTimer2 = new Timer() { - @Override - public void run() { - DOM.setElementProperty(loadElement, "className", - "v-loading-indicator-delay"); - } - }; - // Second one kicks in at 1500ms from request start - loadTimer2.schedule(1200); - - loadTimer3 = new Timer() { - @Override - public void run() { - DOM.setElementProperty(loadElement, "className", - "v-loading-indicator-wait"); - } - }; - // Third one kicks in at 5000ms from request start - loadTimer3.schedule(4700); - } - - private void hideLoadingIndicator() { - if (loadTimer != null) { - loadTimer.cancel(); - loadTimer = null; - } - if (loadTimer2 != null) { - loadTimer2.cancel(); - loadTimer3.cancel(); - loadTimer2 = null; - loadTimer3 = null; - } - if (loadElement != null) { - DOM.setStyleAttribute(loadElement, "display", "none"); - } - } - - /** - * Checks if deferred commands are (potentially) still being executed as a - * result of an update from the server. Returns true if a deferred command - * might still be executing, false otherwise. This will not work correctly - * if a deferred command is added in another deferred command. - * <p> - * Used by the native "client.isActive" function. - * </p> - * - * @return true if deferred commands are (potentially) being executed, false - * otherwise - */ - private boolean isExecutingDeferredCommands() { - Scheduler s = Scheduler.get(); - if (s instanceof VSchedulerImpl) { - return ((VSchedulerImpl) s).hasWorkQueued(); - } else { - return false; - } - } - - /** - * Determines whether or not the loading indicator is showing. - * - * @return true if the loading indicator is visible - */ - public boolean isLoadingIndicatorVisible() { - if (loadElement == null) { - return false; - } - if (loadElement.getStyle().getProperty("display").equals("none")) { - return false; - } - - return true; - } - - private static native ValueMap parseJSONResponse(String jsonText) - /*-{ - try { - return JSON.parse(jsonText); - } catch (ignored) { - return eval('(' + jsonText + ')'); - } - }-*/; - - private void handleReceivedJSONMessage(Date start, String jsonText, - ValueMap json) { - handleUIDLMessage(start, jsonText, json); - } - - protected void handleUIDLMessage(final Date start, final String jsonText, - final ValueMap json) { - if (!renderingLocks.isEmpty()) { - // Some component is doing something that can't be interrupted - // (e.g. animation that should be smooth). Enqueue the UIDL - // message for later processing. - VConsole.log("Postponing UIDL handling due to lock..."); - pendingUIDLMessages.add(new PendingUIDLMessage(start, jsonText, - json)); - forceHandleMessage.schedule(MAX_SUSPENDED_TIMEOUT); - return; - } - - VConsole.log("Handling message from server"); - // Handle redirect - if (json.containsKey("redirect")) { - String url = json.getValueMap("redirect").getString("url"); - VConsole.log("redirecting to " + url); - redirect(url); - return; - } - - final MultiStepDuration handleUIDLDuration = new MultiStepDuration(); - - // Get security key - if (json.containsKey(ApplicationConstants.UIDL_SECURITY_TOKEN_ID)) { - uidlSecurityKey = json - .getString(ApplicationConstants.UIDL_SECURITY_TOKEN_ID); - } - VConsole.log(" * Handling resources from server"); - - if (json.containsKey("resources")) { - ValueMap resources = json.getValueMap("resources"); - JsArrayString keyArray = resources.getKeyArray(); - int l = keyArray.length(); - for (int i = 0; i < l; i++) { - String key = keyArray.get(i); - resourcesMap.put(key, resources.getAsString(key)); - } - } - handleUIDLDuration.logDuration( - " * Handling resources from server completed", 10); - - VConsole.log(" * Handling type inheritance map from server"); - - if (json.containsKey("typeInheritanceMap")) { - configuration.addComponentInheritanceInfo(json - .getValueMap("typeInheritanceMap")); - } - handleUIDLDuration.logDuration( - " * Handling type inheritance map from server completed", 10); - - VConsole.log("Handling type mappings from server"); - - if (json.containsKey("typeMappings")) { - configuration.addComponentMappings( - json.getValueMap("typeMappings"), widgetSet); - } - - VConsole.log("Handling resource dependencies"); - if (json.containsKey("scriptDependencies")) { - loadScriptDependencies(json.getJSStringArray("scriptDependencies")); - } - if (json.containsKey("styleDependencies")) { - loadStyleDependencies(json.getJSStringArray("styleDependencies")); - } - - handleUIDLDuration.logDuration( - " * Handling type mappings from server completed", 10); - /* - * Hook for e.g. TestBench to get details about server peformance - */ - if (json.containsKey("timings")) { - serverTimingInfo = json.getValueMap("timings"); - } - - Command c = new Command() { - @Override - public void execute() { - handleUIDLDuration.logDuration(" * Loading widgets completed", - 10); - - MultiStepDuration updateDuration = new MultiStepDuration(); - - if (json.containsKey("locales")) { - VConsole.log(" * Handling locales"); - // Store locale data - JsArray<ValueMap> valueMapArray = json - .getJSValueMapArray("locales"); - LocaleService.addLocales(valueMapArray); - } - - updateDuration.logDuration(" * Handling locales completed", 10); - - boolean repaintAll = false; - ValueMap meta = null; - if (json.containsKey("meta")) { - VConsole.log(" * Handling meta information"); - meta = json.getValueMap("meta"); - if (meta.containsKey("repaintAll")) { - repaintAll = true; - uIConnector.getWidget().clear(); - getConnectorMap().clear(); - if (meta.containsKey("invalidLayouts")) { - validatingLayouts = true; - zeroWidthComponents = new HashSet<ComponentConnector>(); - zeroHeightComponents = new HashSet<ComponentConnector>(); - } - } - if (meta.containsKey("timedRedirect")) { - final ValueMap timedRedirect = meta - .getValueMap("timedRedirect"); - redirectTimer = new Timer() { - @Override - public void run() { - redirect(timedRedirect.getString("url")); - } - }; - sessionExpirationInterval = timedRedirect - .getInt("interval"); - } - } - - updateDuration.logDuration( - " * Handling meta information completed", 10); - - if (redirectTimer != null) { - redirectTimer.schedule(1000 * sessionExpirationInterval); - } - - componentCaptionSizeChanges.clear(); - - int startProcessing = updateDuration.elapsedMillis(); - - // Ensure that all connectors that we are about to update exist - Set<ServerConnector> createdConnectors = createConnectorsIfNeeded(json); - - updateDuration.logDuration(" * Creating connectors completed", - 10); - - // Update states, do not fire events - Collection<StateChangeEvent> pendingStateChangeEvents = updateConnectorState( - json, createdConnectors); - - updateDuration.logDuration( - " * Update of connector states completed", 10); - - // Update hierarchy, do not fire events - Collection<ConnectorHierarchyChangeEvent> pendingHierarchyChangeEvents = updateConnectorHierarchy(json); - - updateDuration.logDuration( - " * Update of connector hierarchy completed", 10); - - // Fire hierarchy change events - sendHierarchyChangeEvents(pendingHierarchyChangeEvents); - - updateDuration.logDuration( - " * Hierarchy state change event processing completed", - 10); - - delegateToWidget(pendingStateChangeEvents); - - // Fire state change events. - sendStateChangeEvents(pendingStateChangeEvents); - - updateDuration.logDuration( - " * State change event processing completed", 10); - - // Update of legacy (UIDL) style connectors - updateVaadin6StyleConnectors(json); - - updateDuration - .logDuration( - " * Vaadin 6 style connector updates (updateFromUidl) completed", - 10); - - // Handle any RPC invocations done on the server side - handleRpcInvocations(json); - - updateDuration.logDuration( - " * Processing of RPC invocations completed", 10); - - if (json.containsKey("dd")) { - // response contains data for drag and drop service - VDragAndDropManager.get().handleServerResponse( - json.getValueMap("dd")); - } - - updateDuration - .logDuration( - " * Processing of drag and drop server response completed", - 10); - - unregisterRemovedConnectors(); - - updateDuration.logDuration( - " * Unregistering of removed components completed", 10); - - VConsole.log("handleUIDLMessage: " - + (updateDuration.elapsedMillis() - startProcessing) - + " ms"); - - LayoutManager layoutManager = getLayoutManager(); - layoutManager.setEverythingNeedsMeasure(); - layoutManager.layoutNow(); - - updateDuration - .logDuration(" * Layout processing completed", 10); - - if (ApplicationConfiguration.isDebugMode()) { - VConsole.log(" * Dumping state changes to the console"); - VConsole.dirUIDL(json, ApplicationConnection.this); - - updateDuration - .logDuration( - " * Dumping state changes to the console completed", - 10); - } - - if (meta != null) { - if (meta.containsKey("appError")) { - ValueMap error = meta.getValueMap("appError"); - String html = ""; - if (error.containsKey("caption") - && error.getString("caption") != null) { - html += "<h1>" + error.getAsString("caption") - + "</h1>"; - } - if (error.containsKey("message") - && error.getString("message") != null) { - html += "<p>" + error.getAsString("message") - + "</p>"; - } - String url = null; - if (error.containsKey("url")) { - url = error.getString("url"); - } - - if (html.length() != 0) { - /* 45 min */ - VNotification n = VNotification - .createNotification(1000 * 60 * 45); - n.addEventListener(new NotificationRedirect(url)); - n.show(html, VNotification.CENTERED_TOP, - VNotification.STYLE_SYSTEM); - } else { - redirect(url); - } - applicationRunning = false; - } - if (validatingLayouts) { - VConsole.printLayoutProblems(meta, - ApplicationConnection.this, - zeroHeightComponents, zeroWidthComponents); - zeroHeightComponents = null; - zeroWidthComponents = null; - validatingLayouts = false; - - } - } - - updateDuration.logDuration(" * Error handling completed", 10); - - // TODO build profiling for widget impl loading time - - lastProcessingTime = (int) ((new Date().getTime()) - start - .getTime()); - totalProcessingTime += lastProcessingTime; - - VConsole.log(" Processing time was " - + String.valueOf(lastProcessingTime) + "ms for " - + jsonText.length() + " characters of JSON"); - VConsole.log("Referenced paintables: " + connectorMap.size()); - - endRequest(); - - } - - private void delegateToWidget( - Collection<StateChangeEvent> pendingStateChangeEvents) { - VConsole.log(" * Running @DelegateToWidget"); - - for (StateChangeEvent sce : pendingStateChangeEvents) { - ServerConnector connector = sce.getConnector(); - if (connector instanceof ComponentConnector) { - ComponentConnector component = (ComponentConnector) connector; - - Type stateType = AbstractConnector - .getStateType(component); - - Set<String> changedProperties = sce - .getChangedProperties(); - for (String propertyName : changedProperties) { - Property property = stateType - .getProperty(propertyName); - String method = property - .getDelegateToWidgetMethodName(); - if (method != null) { - doDelegateToWidget(component, property, method); - } - } - - } - } - } - - private void doDelegateToWidget(ComponentConnector component, - Property property, String methodName) { - Type type = TypeData.getType(component.getClass()); - try { - Type widgetType = type.getMethod("getWidget") - .getReturnType(); - Widget widget = component.getWidget(); - - Object propertyValue = property.getValue(component - .getState()); - - widgetType.getMethod(methodName).invoke(widget, - propertyValue); - } catch (NoDataException e) { - throw new RuntimeException( - "Missing data needed to invoke @DelegateToWidget for " - + Util.getSimpleName(component), e); - } - } - - /** - * Sends the state change events created while updating the state - * information. - * - * This must be called after hierarchy change listeners have been - * called. At least caption updates for the parent are strange if - * fired from state change listeners and thus calls the parent - * BEFORE the parent is aware of the child (through a - * ConnectorHierarchyChangedEvent) - * - * @param pendingStateChangeEvents - * The events to send - */ - private void sendStateChangeEvents( - Collection<StateChangeEvent> pendingStateChangeEvents) { - VConsole.log(" * Sending state change events"); - - for (StateChangeEvent sce : pendingStateChangeEvents) { - try { - sce.getConnector().fireEvent(sce); - } catch (final Throwable e) { - VConsole.error(e); - } - } - - } - - private void unregisterRemovedConnectors() { - int unregistered = 0; - List<ServerConnector> currentConnectors = new ArrayList<ServerConnector>( - connectorMap.getConnectors()); - for (ServerConnector c : currentConnectors) { - if (c.getParent() != null) { - if (!c.getParent().getChildren().contains(c)) { - VConsole.error("ERROR: Connector is connected to a parent but the parent does not contain the connector"); - } - } else if ((c instanceof UIConnector && c == getRootConnector())) { - // UIConnector for this connection, leave as-is - } else if (c instanceof WindowConnector - && getRootConnector().hasSubWindow( - (WindowConnector) c)) { - // Sub window attached to this UIConnector, leave - // as-is - } else { - // The connector has been detached from the - // hierarchy, unregister it and any possible - // children. The UIConnector should never be - // unregistered even though it has no parent. - connectorMap.unregisterConnector(c); - unregistered++; - } - - } - - VConsole.log("* Unregistered " + unregistered + " connectors"); - } - - private Set<ServerConnector> createConnectorsIfNeeded(ValueMap json) { - VConsole.log(" * Creating connectors (if needed)"); - - if (!json.containsKey("types")) { - return Collections.emptySet(); - } - - Set<ServerConnector> createdConnectors = new HashSet<ServerConnector>(); - - ValueMap types = json.getValueMap("types"); - JsArrayString keyArray = types.getKeyArray(); - for (int i = 0; i < keyArray.length(); i++) { - try { - String connectorId = keyArray.get(i); - int connectorType = Integer.parseInt(types - .getString((connectorId))); - ServerConnector connector = connectorMap - .getConnector(connectorId); - if (connector != null) { - continue; - } - - Class<? extends ServerConnector> connectorClass = configuration - .getConnectorClassByEncodedTag(connectorType); - - // Connector does not exist so we must create it - if (connectorClass != UIConnector.class) { - // create, initialize and register the paintable - connector = getConnector(connectorId, connectorType); - createdConnectors.add(connector); - } else { - // First UIConnector update. Before this the - // UIConnector has been created but not - // initialized as the connector id has not been - // known - connectorMap.registerConnector(connectorId, - uIConnector); - uIConnector.doInit(connectorId, - ApplicationConnection.this); - createdConnectors.add(uIConnector); - } - } catch (final Throwable e) { - VConsole.error(e); - } - } - return createdConnectors; - } - - private void updateVaadin6StyleConnectors(ValueMap json) { - JsArray<ValueMap> changes = json.getJSValueMapArray("changes"); - int length = changes.length(); - - VConsole.log(" * Passing UIDL to Vaadin 6 style connectors"); - // update paintables - for (int i = 0; i < length; i++) { - try { - final UIDL change = changes.get(i).cast(); - final UIDL uidl = change.getChildUIDL(0); - String connectorId = uidl.getId(); - - final ComponentConnector legacyConnector = (ComponentConnector) connectorMap - .getConnector(connectorId); - if (legacyConnector instanceof Paintable) { - ((Paintable) legacyConnector).updateFromUIDL(uidl, - ApplicationConnection.this); - } else if (legacyConnector == null) { - VConsole.error("Received update for " - + uidl.getTag() - + ", but there is no such paintable (" - + connectorId + ") rendered."); - } else { - VConsole.error("Server sent Vaadin 6 style updates for " - + Util.getConnectorString(legacyConnector) - + " but this is not a Vaadin 6 Paintable"); - } - - } catch (final Throwable e) { - VConsole.error(e); - } - } - } - - private void sendHierarchyChangeEvents( - Collection<ConnectorHierarchyChangeEvent> pendingHierarchyChangeEvents) { - if (pendingHierarchyChangeEvents.isEmpty()) { - return; - } - - VConsole.log(" * Sending hierarchy change events"); - for (ConnectorHierarchyChangeEvent event : pendingHierarchyChangeEvents) { - try { - event.getConnector().fireEvent(event); - } catch (final Throwable e) { - VConsole.error(e); - } - } - - } - - private Collection<StateChangeEvent> updateConnectorState( - ValueMap json, Set<ServerConnector> newConnectors) { - ArrayList<StateChangeEvent> events = new ArrayList<StateChangeEvent>(); - VConsole.log(" * Updating connector states"); - if (!json.containsKey("state")) { - return events; - } - HashSet<ServerConnector> remainingNewConnectors = new HashSet<ServerConnector>( - newConnectors); - - // set states for all paintables mentioned in "state" - ValueMap states = json.getValueMap("state"); - JsArrayString keyArray = states.getKeyArray(); - for (int i = 0; i < keyArray.length(); i++) { - try { - String connectorId = keyArray.get(i); - ServerConnector connector = connectorMap - .getConnector(connectorId); - if (null != connector) { - - JSONObject stateJson = new JSONObject( - states.getJavaScriptObject(connectorId)); - - if (connector instanceof HasJavaScriptConnectorHelper) { - ((HasJavaScriptConnectorHelper) connector) - .getJavascriptConnectorHelper() - .setNativeState( - stateJson.getJavaScriptObject()); - } - - SharedState state = connector.getState(); - JsonDecoder.decodeValue(new Type(state.getClass() - .getName(), null), stateJson, state, - ApplicationConnection.this); - - Set<String> changedProperties = new HashSet<String>(); - addJsonFields(stateJson, changedProperties, ""); - - if (newConnectors.contains(connector)) { - remainingNewConnectors.remove(connector); - // Fire events for properties using the default - // value for newly created connectors - addAllStateFields( - AbstractConnector - .getStateType(connector), - changedProperties, ""); - } - - StateChangeEvent event = new StateChangeEvent( - connector, changedProperties); - - events.add(event); - } - } catch (final Throwable e) { - VConsole.error(e); - } - } - - // Fire events for properties using the default value for newly - // created connectors even if there were no state changes - for (ServerConnector connector : remainingNewConnectors) { - Set<String> changedProperties = new HashSet<String>(); - addAllStateFields( - AbstractConnector.getStateType(connector), - changedProperties, ""); - - StateChangeEvent event = new StateChangeEvent(connector, - changedProperties); - - events.add(event); - - } - - return events; - } - - /** - * Recursively adds the names of all properties in the provided - * state type. - * - * @param type - * the type to process - * @param foundProperties - * a set of all currently added properties - * @param context - * the base name of the current object - */ - private void addAllStateFields(Type type, - Set<String> foundProperties, String context) { - try { - Collection<Property> properties = type.getProperties(); - for (Property property : properties) { - String propertyName = context + property.getName(); - foundProperties.add(propertyName); - - Type propertyType = property.getType(); - if (propertyType.hasProperties()) { - addAllStateFields(propertyType, foundProperties, - propertyName + "."); - } - } - } catch (NoDataException e) { - throw new IllegalStateException( - "No property info for " - + type - + ". Did you remember to compile the right widgetset?", - e); - } - } - - /** - * Recursively adds the names of all fields in all objects in the - * provided json object. - * - * @param json - * the json object to process - * @param fields - * a set of all currently added fields - * @param context - * the base name of the current object - */ - private void addJsonFields(JSONObject json, Set<String> fields, - String context) { - for (String key : json.keySet()) { - String fieldName = context + key; - fields.add(fieldName); - - JSONObject object = json.get(key).isObject(); - if (object != null) { - addJsonFields(object, fields, fieldName + "."); - } - } - } - - /** - * Updates the connector hierarchy and returns a list of events that - * should be fired after update of the hierarchy and the state is - * done. - * - * @param json - * The JSON containing the hierarchy information - * @return A collection of events that should be fired when update - * of hierarchy and state is complete - */ - private Collection<ConnectorHierarchyChangeEvent> updateConnectorHierarchy( - ValueMap json) { - List<ConnectorHierarchyChangeEvent> events = new LinkedList<ConnectorHierarchyChangeEvent>(); - - VConsole.log(" * Updating connector hierarchy"); - if (!json.containsKey("hierarchy")) { - return events; - } - - ValueMap hierarchies = json.getValueMap("hierarchy"); - JsArrayString hierarchyKeys = hierarchies.getKeyArray(); - for (int i = 0; i < hierarchyKeys.length(); i++) { - try { - String connectorId = hierarchyKeys.get(i); - ServerConnector parentConnector = connectorMap - .getConnector(connectorId); - JsArrayString childConnectorIds = hierarchies - .getJSStringArray(connectorId); - int childConnectorSize = childConnectorIds.length(); - - List<ServerConnector> newChildren = new ArrayList<ServerConnector>(); - List<ComponentConnector> newComponents = new ArrayList<ComponentConnector>(); - for (int connectorIndex = 0; connectorIndex < childConnectorSize; connectorIndex++) { - String childConnectorId = childConnectorIds - .get(connectorIndex); - ServerConnector childConnector = connectorMap - .getConnector(childConnectorId); - if (childConnector == null) { - VConsole.error("Hierarchy claims that " - + childConnectorId + " is a child for " - + connectorId + " (" - + parentConnector.getClass().getName() - + ") but no connector with id " - + childConnectorId - + " has been registered"); - continue; - } - newChildren.add(childConnector); - if (childConnector instanceof ComponentConnector) { - newComponents - .add((ComponentConnector) childConnector); - } else if (!(childConnector instanceof AbstractExtensionConnector)) { - throw new IllegalStateException( - Util.getConnectorString(childConnector) - + " is not a ComponentConnector nor an AbstractExtensionConnector"); - } - if (childConnector.getParent() != parentConnector) { - // Avoid extra calls to setParent - childConnector.setParent(parentConnector); - } - } - - // TODO This check should be done on the server side in - // the future so the hierarchy update is only sent when - // something actually has changed - List<ServerConnector> oldChildren = parentConnector - .getChildren(); - boolean actuallyChanged = !Util.collectionsEquals( - oldChildren, newChildren); - - if (!actuallyChanged) { - continue; - } - - if (parentConnector instanceof ComponentContainerConnector) { - ComponentContainerConnector ccc = (ComponentContainerConnector) parentConnector; - List<ComponentConnector> oldComponents = ccc - .getChildComponents(); - if (!Util.collectionsEquals(oldComponents, - newComponents)) { - // Fire change event if the hierarchy has - // changed - ConnectorHierarchyChangeEvent event = GWT - .create(ConnectorHierarchyChangeEvent.class); - event.setOldChildren(oldComponents); - event.setConnector(parentConnector); - ccc.setChildComponents(newComponents); - events.add(event); - } - } else if (!newComponents.isEmpty()) { - VConsole.error("Hierachy claims " - + Util.getConnectorString(parentConnector) - + " has component children even though it isn't a ComponentContainerConnector"); - } - - parentConnector.setChildren(newChildren); - - // Remove parent for children that are no longer - // attached to this (avoid updating children if they - // have already been assigned to a new parent) - for (ServerConnector oldChild : oldChildren) { - if (oldChild.getParent() != parentConnector) { - continue; - } - - // TODO This could probably be optimized - if (!newChildren.contains(oldChild)) { - oldChild.setParent(null); - } - } - } catch (final Throwable e) { - VConsole.error(e); - } - } - return events; - - } - - private void handleRpcInvocations(ValueMap json) { - if (json.containsKey("rpc")) { - VConsole.log(" * Performing server to client RPC calls"); - - JSONArray rpcCalls = new JSONArray( - json.getJavaScriptObject("rpc")); - - int rpcLength = rpcCalls.size(); - for (int i = 0; i < rpcLength; i++) { - try { - JSONArray rpcCall = (JSONArray) rpcCalls.get(i); - rpcManager.parseAndApplyInvocation(rpcCall, - ApplicationConnection.this); - } catch (final Throwable e) { - VConsole.error(e); - } - } - } - - } - - }; - ApplicationConfiguration.runWhenDependenciesLoaded(c); - } - - private void loadStyleDependencies(JsArrayString dependencies) { - // Assuming no reason to interpret in a defined order - ResourceLoadListener resourceLoadListener = new ResourceLoadListener() { - @Override - public void onLoad(ResourceLoadEvent event) { - ApplicationConfiguration.endDependencyLoading(); - } - - @Override - public void onError(ResourceLoadEvent event) { - VConsole.error(event.getResourceUrl() - + " could not be loaded, or the load detection failed because the stylesheet is empty."); - // The show must go on - onLoad(event); - } - }; - ResourceLoader loader = ResourceLoader.get(); - for (int i = 0; i < dependencies.length(); i++) { - String url = translateVaadinUri(dependencies.get(i)); - ApplicationConfiguration.startDependencyLoading(); - loader.loadStylesheet(url, resourceLoadListener); - } - } - - private void loadScriptDependencies(final JsArrayString dependencies) { - if (dependencies.length() == 0) { - return; - } - - // Listener that loads the next when one is completed - ResourceLoadListener resourceLoadListener = new ResourceLoadListener() { - @Override - public void onLoad(ResourceLoadEvent event) { - if (dependencies.length() != 0) { - String url = translateVaadinUri(dependencies.shift()); - ApplicationConfiguration.startDependencyLoading(); - // Load next in chain (hopefully already preloaded) - event.getResourceLoader().loadScript(url, this); - } - // Call start for next before calling end for current - ApplicationConfiguration.endDependencyLoading(); - } - - @Override - public void onError(ResourceLoadEvent event) { - VConsole.error(event.getResourceUrl() + " could not be loaded."); - // The show must go on - onLoad(event); - } - }; - - ResourceLoader loader = ResourceLoader.get(); - - // Start chain by loading first - String url = translateVaadinUri(dependencies.shift()); - ApplicationConfiguration.startDependencyLoading(); - loader.loadScript(url, resourceLoadListener); - - // Preload all remaining - for (int i = 0; i < dependencies.length(); i++) { - String preloadUrl = translateVaadinUri(dependencies.get(i)); - loader.preloadResource(preloadUrl, null); - } - } - - // Redirect browser, null reloads current page - private static native void redirect(String url) - /*-{ - if (url) { - $wnd.location = url; - } else { - $wnd.location.reload(false); - } - }-*/; - - private void addVariableToQueue(String connectorId, String variableName, - Object value, boolean immediate) { - boolean lastOnly = !immediate; - // note that type is now deduced from value - addMethodInvocationToQueue(new LegacyChangeVariablesInvocation( - connectorId, variableName, value), lastOnly, lastOnly); - } - - /** - * Adds an explicit RPC method invocation to the send queue. - * - * @since 7.0 - * - * @param invocation - * RPC method invocation - * @param delayed - * <code>false</code> to trigger sending within a short time - * window (possibly combining subsequent calls to a single - * request), <code>true</code> to let the framework delay sending - * of RPC calls and variable changes until the next non-delayed - * change - * @param lastonly - * <code>true</code> to remove all previously delayed invocations - * of the same method that were also enqueued with lastonly set - * to <code>true</code>. <code>false</code> to add invocation to - * the end of the queue without touching previously enqueued - * invocations. - */ - public void addMethodInvocationToQueue(MethodInvocation invocation, - boolean delayed, boolean lastonly) { - String tag; - if (lastonly) { - tag = invocation.getLastonlyTag(); - assert !tag.matches("\\d+") : "getLastonlyTag value must have at least one non-digit character"; - pendingInvocations.remove(tag); - } else { - tag = Integer.toString(lastInvocationTag++); - } - pendingInvocations.put(tag, invocation); - if (!delayed) { - sendPendingVariableChanges(); - } - } - - /** - * This method sends currently queued variable changes to server. It is - * called when immediate variable update must happen. - * - * To ensure correct order for variable changes (due servers multithreading - * or network), we always wait for active request to be handler before - * sending a new one. If there is an active request, we will put varible - * "burst" to queue that will be purged after current request is handled. - * - */ - public void sendPendingVariableChanges() { - if (!deferedSendPending) { - deferedSendPending = true; - Scheduler.get().scheduleDeferred(sendPendingCommand); - } - } - - private final ScheduledCommand sendPendingCommand = new ScheduledCommand() { - @Override - public void execute() { - deferedSendPending = false; - doSendPendingVariableChanges(); - } - }; - private boolean deferedSendPending = false; - - private void doSendPendingVariableChanges() { - if (applicationRunning) { - if (hasActiveRequest()) { - // skip empty queues if there are pending bursts to be sent - if (pendingInvocations.size() > 0 || pendingBursts.size() == 0) { - pendingBursts.add(pendingInvocations); - pendingInvocations = new LinkedHashMap<String, MethodInvocation>(); - // Keep tag string short - lastInvocationTag = 0; - } - } else { - buildAndSendVariableBurst(pendingInvocations, false); - } - } - } - - /** - * Build the variable burst and send it to server. - * - * When sync is forced, we also force sending of all pending variable-bursts - * at the same time. This is ok as we can assume that DOM will never be - * updated after this. - * - * @param pendingInvocations - * List of RPC method invocations to send - * @param forceSync - * Should we use synchronous request? - */ - private void buildAndSendVariableBurst( - LinkedHashMap<String, MethodInvocation> pendingInvocations, - boolean forceSync) { - final StringBuffer req = new StringBuffer(); - - while (!pendingInvocations.isEmpty()) { - if (ApplicationConfiguration.isDebugMode()) { - Util.logVariableBurst(this, pendingInvocations.values()); - } - - JSONArray reqJson = new JSONArray(); - - for (MethodInvocation invocation : pendingInvocations.values()) { - JSONArray invocationJson = new JSONArray(); - invocationJson.set(0, - new JSONString(invocation.getConnectorId())); - invocationJson.set(1, - new JSONString(invocation.getInterfaceName())); - invocationJson.set(2, - new JSONString(invocation.getMethodName())); - JSONArray paramJson = new JSONArray(); - boolean restrictToInternalTypes = isLegacyVariableChange(invocation); - for (int i = 0; i < invocation.getParameters().length; ++i) { - // TODO non-static encoder? type registration? - paramJson.set(i, JsonEncoder.encode( - invocation.getParameters()[i], - restrictToInternalTypes, this)); - } - invocationJson.set(3, paramJson); - reqJson.set(reqJson.size(), invocationJson); - } - - // escape burst separators (if any) - req.append(escapeBurstContents(reqJson.toString())); - - pendingInvocations.clear(); - // Keep tag string short - lastInvocationTag = 0; - // Append all the bursts to this synchronous request - if (forceSync && !pendingBursts.isEmpty()) { - pendingInvocations = pendingBursts.get(0); - pendingBursts.remove(0); - req.append(VAR_BURST_SEPARATOR); - } - } - - // Include the browser detail parameters if they aren't already sent - String extraParams; - if (!getConfiguration().isBrowserDetailsSent()) { - extraParams = getNativeBrowserDetailsParameters(getConfiguration() - .getRootPanelId()); - getConfiguration().setBrowserDetailsSent(); - } else { - extraParams = ""; - } - if (!getConfiguration().isWidgetsetVersionSent()) { - if (!extraParams.isEmpty()) { - extraParams += "&"; - } - String widgetsetVersion = Version.getFullVersion(); - extraParams += "wsver=" + widgetsetVersion; - - getConfiguration().setWidgetsetVersionSent(); - } - makeUidlRequest(req.toString(), extraParams, forceSync); - } - - private boolean isLegacyVariableChange(MethodInvocation invocation) { - return ApplicationConstants.UPDATE_VARIABLE_METHOD.equals(invocation - .getInterfaceName()) - && ApplicationConstants.UPDATE_VARIABLE_METHOD - .equals(invocation.getMethodName()); - } - - /** - * Sends a new value for the given paintables given variable to the server. - * <p> - * The update is actually queued to be sent at a suitable time. If immediate - * is true, the update is sent as soon as possible. If immediate is false, - * the update will be sent along with the next immediate update. - * </p> - * - * @param paintableId - * the id of the paintable that owns the variable - * @param variableName - * the name of the variable - * @param newValue - * the new value to be sent - * @param immediate - * true if the update is to be sent as soon as possible - */ - public void updateVariable(String paintableId, String variableName, - ServerConnector newValue, boolean immediate) { - addVariableToQueue(paintableId, variableName, newValue, immediate); - } - - /** - * Sends a new value for the given paintables given variable to the server. - * <p> - * The update is actually queued to be sent at a suitable time. If immediate - * is true, the update is sent as soon as possible. If immediate is false, - * the update will be sent along with the next immediate update. - * </p> - * - * @param paintableId - * the id of the paintable that owns the variable - * @param variableName - * the name of the variable - * @param newValue - * the new value to be sent - * @param immediate - * true if the update is to be sent as soon as possible - */ - - public void updateVariable(String paintableId, String variableName, - String newValue, boolean immediate) { - addVariableToQueue(paintableId, variableName, newValue, immediate); - } - - /** - * Sends a new value for the given paintables given variable to the server. - * <p> - * The update is actually queued to be sent at a suitable time. If immediate - * is true, the update is sent as soon as possible. If immediate is false, - * the update will be sent along with the next immediate update. - * </p> - * - * @param paintableId - * the id of the paintable that owns the variable - * @param variableName - * the name of the variable - * @param newValue - * the new value to be sent - * @param immediate - * true if the update is to be sent as soon as possible - */ - - public void updateVariable(String paintableId, String variableName, - int newValue, boolean immediate) { - addVariableToQueue(paintableId, variableName, newValue, immediate); - } - - /** - * Sends a new value for the given paintables given variable to the server. - * <p> - * The update is actually queued to be sent at a suitable time. If immediate - * is true, the update is sent as soon as possible. If immediate is false, - * the update will be sent along with the next immediate update. - * </p> - * - * @param paintableId - * the id of the paintable that owns the variable - * @param variableName - * the name of the variable - * @param newValue - * the new value to be sent - * @param immediate - * true if the update is to be sent as soon as possible - */ - - public void updateVariable(String paintableId, String variableName, - long newValue, boolean immediate) { - addVariableToQueue(paintableId, variableName, newValue, immediate); - } - - /** - * Sends a new value for the given paintables given variable to the server. - * <p> - * The update is actually queued to be sent at a suitable time. If immediate - * is true, the update is sent as soon as possible. If immediate is false, - * the update will be sent along with the next immediate update. - * </p> - * - * @param paintableId - * the id of the paintable that owns the variable - * @param variableName - * the name of the variable - * @param newValue - * the new value to be sent - * @param immediate - * true if the update is to be sent as soon as possible - */ - - public void updateVariable(String paintableId, String variableName, - float newValue, boolean immediate) { - addVariableToQueue(paintableId, variableName, newValue, immediate); - } - - /** - * Sends a new value for the given paintables given variable to the server. - * <p> - * The update is actually queued to be sent at a suitable time. If immediate - * is true, the update is sent as soon as possible. If immediate is false, - * the update will be sent along with the next immediate update. - * </p> - * - * @param paintableId - * the id of the paintable that owns the variable - * @param variableName - * the name of the variable - * @param newValue - * the new value to be sent - * @param immediate - * true if the update is to be sent as soon as possible - */ - - public void updateVariable(String paintableId, String variableName, - double newValue, boolean immediate) { - addVariableToQueue(paintableId, variableName, newValue, immediate); - } - - /** - * Sends a new value for the given paintables given variable to the server. - * <p> - * The update is actually queued to be sent at a suitable time. If immediate - * is true, the update is sent as soon as possible. If immediate is false, - * the update will be sent along with the next immediate update. - * </p> - * - * @param paintableId - * the id of the paintable that owns the variable - * @param variableName - * the name of the variable - * @param newValue - * the new value to be sent - * @param immediate - * true if the update is to be sent as soon as possible - */ - - public void updateVariable(String paintableId, String variableName, - boolean newValue, boolean immediate) { - addVariableToQueue(paintableId, variableName, newValue, immediate); - } - - /** - * Sends a new value for the given paintables given variable to the server. - * <p> - * The update is actually queued to be sent at a suitable time. If immediate - * is true, the update is sent as soon as possible. If immediate is false, - * the update will be sent along with the next immediate update. - * </p> - * - * @param paintableId - * the id of the paintable that owns the variable - * @param variableName - * the name of the variable - * @param map - * the new values to be sent - * @param immediate - * true if the update is to be sent as soon as possible - */ - public void updateVariable(String paintableId, String variableName, - Map<String, Object> map, boolean immediate) { - addVariableToQueue(paintableId, variableName, map, immediate); - } - - /** - * Sends a new value for the given paintables given variable to the server. - * - * The update is actually queued to be sent at a suitable time. If immediate - * is true, the update is sent as soon as possible. If immediate is false, - * the update will be sent along with the next immediate update. - * - * A null array is sent as an empty array. - * - * @param paintableId - * the id of the paintable that owns the variable - * @param variableName - * the name of the variable - * @param values - * the new value to be sent - * @param immediate - * true if the update is to be sent as soon as possible - */ - public void updateVariable(String paintableId, String variableName, - String[] values, boolean immediate) { - addVariableToQueue(paintableId, variableName, values, immediate); - } - - /** - * Sends a new value for the given paintables given variable to the server. - * - * The update is actually queued to be sent at a suitable time. If immediate - * is true, the update is sent as soon as possible. If immediate is false, - * the update will be sent along with the next immediate update. </p> - * - * A null array is sent as an empty array. - * - * - * @param paintableId - * the id of the paintable that owns the variable - * @param variableName - * the name of the variable - * @param values - * the new value to be sent - * @param immediate - * true if the update is to be sent as soon as possible - */ - public void updateVariable(String paintableId, String variableName, - Object[] values, boolean immediate) { - addVariableToQueue(paintableId, variableName, values, immediate); - } - - /** - * Encode burst separator characters in a String for transport over the - * network. This protects from separator injection attacks. - * - * @param value - * to encode - * @return encoded value - */ - protected String escapeBurstContents(String value) { - final StringBuilder result = new StringBuilder(); - for (int i = 0; i < value.length(); ++i) { - char character = value.charAt(i); - switch (character) { - case VAR_ESCAPE_CHARACTER: - // fall-through - escape character is duplicated - case VAR_BURST_SEPARATOR: - result.append(VAR_ESCAPE_CHARACTER); - // encode as letters for easier reading - result.append(((char) (character + 0x30))); - break; - default: - // the char is not a special one - add it to the result as is - result.append(character); - break; - } - } - return result.toString(); - } - - private boolean runningLayout = false; - - /** - * Causes a re-calculation/re-layout of all paintables in a container. - * - * @param container - */ - public void runDescendentsLayout(HasWidgets container) { - if (runningLayout) { - return; - } - runningLayout = true; - internalRunDescendentsLayout(container); - runningLayout = false; - } - - /** - * This will cause re-layouting of all components. Mainly used for - * development. Published to JavaScript. - */ - public void forceLayout() { - Duration duration = new Duration(); - - layoutManager.forceLayout(); - - VConsole.log("forceLayout in " + duration.elapsedMillis() + " ms"); - } - - private void internalRunDescendentsLayout(HasWidgets container) { - // getConsole().log( - // "runDescendentsLayout(" + Util.getSimpleName(container) + ")"); - final Iterator<Widget> childWidgets = container.iterator(); - while (childWidgets.hasNext()) { - final Widget child = childWidgets.next(); - - if (getConnectorMap().isConnector(child)) { - - if (handleComponentRelativeSize(child)) { - /* - * Only need to propagate event if "child" has a relative - * size - */ - - if (child instanceof ContainerResizedListener) { - ((ContainerResizedListener) child).iLayout(); - } - - if (child instanceof HasWidgets) { - final HasWidgets childContainer = (HasWidgets) child; - internalRunDescendentsLayout(childContainer); - } - } - } else if (child instanceof HasWidgets) { - // propagate over non Paintable HasWidgets - internalRunDescendentsLayout((HasWidgets) child); - } - - } - } - - /** - * Converts relative sizes into pixel sizes. - * - * @param child - * @return true if the child has a relative size - */ - private boolean handleComponentRelativeSize(ComponentConnector paintable) { - return false; - } - - /** - * Converts relative sizes into pixel sizes. - * - * @param child - * @return true if the child has a relative size - */ - public boolean handleComponentRelativeSize(Widget widget) { - return handleComponentRelativeSize(connectorMap.getConnector(widget)); - - } - - @Deprecated - public ComponentConnector getPaintable(UIDL uidl) { - // Non-component connectors shouldn't be painted from legacy connectors - return (ComponentConnector) getConnector(uidl.getId(), - Integer.parseInt(uidl.getTag())); - } - - /** - * Get either an existing ComponentConnector or create a new - * ComponentConnector with the given type and id. - * - * If a ComponentConnector with the given id already exists, returns it. - * Otherwise creates and registers a new ComponentConnector of the given - * type. - * - * @param connectorId - * Id of the paintable - * @param connectorType - * Type of the connector, as passed from the server side - * - * @return Either an existing ComponentConnector or a new ComponentConnector - * of the given type - */ - public ServerConnector getConnector(String connectorId, int connectorType) { - if (!connectorMap.hasConnector(connectorId)) { - return createAndRegisterConnector(connectorId, connectorType); - } - return connectorMap.getConnector(connectorId); - } - - /** - * Creates a new ServerConnector with the given type and id. - * - * Creates and registers a new ServerConnector of the given type. Should - * never be called with the connector id of an existing connector. - * - * @param connectorId - * Id of the new connector - * @param connectorType - * Type of the connector, as passed from the server side - * - * @return A new ServerConnector of the given type - */ - private ServerConnector createAndRegisterConnector(String connectorId, - int connectorType) { - // Create and register a new connector with the given type - ServerConnector p = widgetSet.createConnector(connectorType, - configuration); - connectorMap.registerConnector(connectorId, p); - p.doInit(connectorId, this); - - return p; - } - - /** - * Gets a recource that has been pre-loaded via UIDL, such as custom - * layouts. - * - * @param name - * identifier of the resource to get - * @return the resource - */ - public String getResource(String name) { - return resourcesMap.get(name); - } - - /** - * Singleton method to get instance of app's context menu. - * - * @return VContextMenu object - */ - public VContextMenu getContextMenu() { - if (contextMenu == null) { - contextMenu = new VContextMenu(); - DOM.setElementProperty(contextMenu.getElement(), "id", - "PID_VAADIN_CM"); - } - return contextMenu; - } - - /** - * Translates custom protocols in UIDL URI's to be recognizable by browser. - * All uri's from UIDL should be routed via this method before giving them - * to browser due URI's in UIDL may contain custom protocols like theme://. - * - * @param uidlUri - * Vaadin URI from uidl - * @return translated URI ready for browser - */ - public String translateVaadinUri(String uidlUri) { - if (uidlUri == null) { - return null; - } - if (uidlUri.startsWith("theme://")) { - final String themeUri = configuration.getThemeUri(); - if (themeUri == null) { - VConsole.error("Theme not set: ThemeResource will not be found. (" - + uidlUri + ")"); - } - uidlUri = themeUri + uidlUri.substring(7); - } - - if (uidlUri.startsWith(ApplicationConstants.CONNECTOR_PROTOCOL_PREFIX)) { - // getAppUri *should* always end with / - // substring *should* always start with / (connector:///foo.bar - // without connector://) - uidlUri = ApplicationConstants.APP_PROTOCOL_PREFIX - + ApplicationConstants.CONNECTOR_RESOURCE_PREFIX - + uidlUri - .substring(ApplicationConstants.CONNECTOR_PROTOCOL_PREFIX - .length()); - // Let translation of app:// urls take care of the rest - } - if (uidlUri.startsWith(ApplicationConstants.APP_PROTOCOL_PREFIX)) { - String relativeUrl = uidlUri - .substring(ApplicationConstants.APP_PROTOCOL_PREFIX - .length()); - if (getConfiguration().usePortletURLs()) { - // Should put path in v-resourcePath parameter and append query - // params to base portlet url - String[] parts = relativeUrl.split("\\?", 2); - String path = parts[0]; - - String url = getConfiguration().getPortletResourceUrl(); - - // If there's a "?" followed by something, append it as a query - // string to the base URL - if (parts.length > 1) { - String appUrlParams = parts[1]; - url = addGetParameters(url, appUrlParams); - } - if (!path.startsWith("/")) { - path = '/' + path; - } - String pathParam = ApplicationConstants.V_RESOURCE_PATH + "=" - + URL.encodeQueryString(path); - url = addGetParameters(url, pathParam); - uidlUri = url; - } else { - uidlUri = getAppUri() + relativeUrl; - } - } - return uidlUri; - } - - /** - * Gets the URI for the current theme. Can be used to reference theme - * resources. - * - * @return URI to the current theme - */ - public String getThemeUri() { - return configuration.getThemeUri(); - } - - /** - * Listens for Notification hide event, and redirects. Used for system - * messages, such as session expired. - * - */ - private class NotificationRedirect implements VNotification.EventListener { - String url; - - NotificationRedirect(String url) { - this.url = url; - } - - @Override - public void notificationHidden(HideEvent event) { - redirect(url); - } - - } - - /* Extended title handling */ - - private final VTooltip tooltip = new VTooltip(this); - - private ConnectorMap connectorMap = GWT.create(ConnectorMap.class); - - protected String getUidlSecurityKey() { - return uidlSecurityKey; - } - - /** - * Use to notify that the given component's caption has changed; layouts may - * have to be recalculated. - * - * @param component - * the Paintable whose caption has changed - */ - public void captionSizeUpdated(Widget widget) { - componentCaptionSizeChanges.add(widget); - } - - /** - * Gets the main view - * - * @return the main view - */ - public UIConnector getRootConnector() { - return uIConnector; - } - - /** - * Gets the {@link ApplicationConfiguration} for the current application. - * - * @see ApplicationConfiguration - * @return the configuration for this application - */ - public ApplicationConfiguration getConfiguration() { - return configuration; - } - - /** - * Checks if there is a registered server side listener for the event. The - * list of events which has server side listeners is updated automatically - * before the component is updated so the value is correct if called from - * updatedFromUIDL. - * - * @param paintable - * The connector to register event listeners for - * @param eventIdentifier - * The identifier for the event - * @return true if at least one listener has been registered on server side - * for the event identified by eventIdentifier. - * @deprecated as of Vaadin 7. Use - * {@link ComponentState#hasEventListener(String)} instead - */ - @Deprecated - public boolean hasEventListeners(ComponentConnector paintable, - String eventIdentifier) { - return paintable.hasEventListener(eventIdentifier); - } - - /** - * Adds the get parameters to the uri and returns the new uri that contains - * the parameters. - * - * @param uri - * The uri to which the parameters should be added. - * @param extraParams - * One or more parameters in the format "a=b" or "c=d&e=f". An - * empty string is allowed but will not modify the url. - * @return The modified URI with the get parameters in extraParams added. - */ - public static String addGetParameters(String uri, String extraParams) { - if (extraParams == null || extraParams.length() == 0) { - return uri; - } - // RFC 3986: The query component is indicated by the first question - // mark ("?") character and terminated by a number sign ("#") character - // or by the end of the URI. - String fragment = null; - int hashPosition = uri.indexOf('#'); - if (hashPosition != -1) { - // Fragment including "#" - fragment = uri.substring(hashPosition); - // The full uri before the fragment - uri = uri.substring(0, hashPosition); - } - - if (uri.contains("?")) { - uri += "&"; - } else { - uri += "?"; - } - uri += extraParams; - - if (fragment != null) { - uri += fragment; - } - - return uri; - } - - ConnectorMap getConnectorMap() { - return connectorMap; - } - - /** - * @deprecated No longer needed in Vaadin 7 - */ - @Deprecated - public void unregisterPaintable(ServerConnector p) { - VConsole.log("unregisterPaintable (unnecessarily) called for " - + Util.getConnectorString(p)); - } - - /** - * Get VTooltip instance related to application connection - * - * @return VTooltip instance - */ - public VTooltip getVTooltip() { - return tooltip; - } - - /** - * Method provided for backwards compatibility. Duties previously done by - * this method is now handled by the state change event handler in - * AbstractComponentConnector. The only function this method has is to - * return true if the UIDL is a "cached" update. - * - * @param component - * @param uidl - * @param manageCaption - * @return - */ - @Deprecated - public boolean updateComponent(Widget component, UIDL uidl, - boolean manageCaption) { - ComponentConnector connector = getConnectorMap() - .getConnector(component); - if (!AbstractComponentConnector.isRealUpdate(uidl)) { - return true; - } - - if (!manageCaption) { - VConsole.error(Util.getConnectorString(connector) - + " called updateComponent with manageCaption=false. The parameter was ignored - override delegateCaption() to return false instead. It is however not recommended to use caption this way at all."); - } - return false; - } - - /** - * @deprecated as of Vaadin 7. Use - * {@link ComponentState#hasEventListener(String)} instead - */ - @Deprecated - public boolean hasEventListeners(Widget widget, String eventIdentifier) { - return hasEventListeners(getConnectorMap().getConnector(widget), - eventIdentifier); - } - - LayoutManager getLayoutManager() { - return layoutManager; - } - - /** - * Schedules a heartbeat request to occur after the configured heartbeat - * interval elapses if the interval is a positive number. Otherwise, does - * nothing. - * - * @see #sendHeartbeat() - * @see ApplicationConfiguration#getHeartbeatInterval() - */ - protected void scheduleHeartbeat() { - final int interval = getConfiguration().getHeartbeatInterval(); - if (interval > 0) { - VConsole.log("Scheduling heartbeat in " + interval + " seconds"); - new Timer() { - @Override - public void run() { - sendHeartbeat(); - } - }.schedule(interval * 1000); - } - } - - /** - * Sends a heartbeat request to the server. - * <p> - * Heartbeat requests are used to inform the server that the client-side is - * still alive. If the client page is closed or the connection lost, the - * server will eventually close the inactive Root. - * <p> - * <b>TODO</b>: Improved error handling, like in doUidlRequest(). - * - * @see #scheduleHeartbeat() - */ - protected void sendHeartbeat() { - final String uri = addGetParameters( - translateVaadinUri(ApplicationConstants.APP_PROTOCOL_PREFIX - + ApplicationConstants.HEARTBEAT_REQUEST_PATH), - UIConstants.UI_ID_PARAMETER + "=" - + getConfiguration().getUIId()); - - final RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, uri); - - final RequestCallback callback = new RequestCallback() { - - @Override - public void onResponseReceived(Request request, Response response) { - int status = response.getStatusCode(); - if (status == Response.SC_OK) { - // TODO Permit retry in some error situations - VConsole.log("Heartbeat response OK"); - scheduleHeartbeat(); - } else { - VConsole.error("Heartbeat request failed with status code " - + status); - } - } - - @Override - public void onError(Request request, Throwable exception) { - VConsole.error("Heartbeat request resulted in exception"); - VConsole.error(exception); - } - }; - - rb.setCallback(callback); - - try { - VConsole.log("Sending heartbeat request..."); - rb.send(); - } catch (RequestException re) { - callback.onError(null, re); - } - } - - /** - * Timer used to make sure that no misbehaving components can lock the - * rendering phase forever. - */ - Timer forceHandleMessage = new Timer() { - @Override - public void run() { - VConsole.log("WARNING: rendering was never resumed, forcing reload..."); - renderingLocks.clear(); - handlePendingMessages(); - } - }; - - /** - * This method can be used to postpone rendering of a response for a short - * period of time (e.g. to avoid the rendering process during animation). - * - * @param lock - */ - public void suspendRendering(Object lock) { - renderingLocks.add(lock); - } - - /** - * Resumes the rendering process once all locks have been removed. - * - * @param lock - */ - public void resumeRendering(Object lock) { - VConsole.log("...resuming UIDL handling."); - renderingLocks.remove(lock); - if (renderingLocks.isEmpty()) { - VConsole.log("No more rendering locks, rendering pending requests."); - forceHandleMessage.cancel(); - handlePendingMessages(); - } - } - - /** - * Handles all pending UIDL messages queued while the rendering was - * suspended. - */ - private void handlePendingMessages() { - for (PendingUIDLMessage pending : pendingUIDLMessages) { - handleUIDLMessage(pending.getStart(), pending.getJsonText(), - pending.getJson()); - } - pendingUIDLMessages.clear(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/BrowserInfo.java b/client/src/com/vaadin/terminal/gwt/client/BrowserInfo.java deleted file mode 100644 index 680131c70c..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/BrowserInfo.java +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.user.client.ui.RootPanel; -import com.vaadin.shared.VBrowserDetails; - -/** - * Class used to query information about web browser. - * - * Browser details are detected only once and those are stored in this singleton - * class. - * - */ -public class BrowserInfo { - - private static final String BROWSER_OPERA = "op"; - private static final String BROWSER_IE = "ie"; - private static final String BROWSER_FIREFOX = "ff"; - private static final String BROWSER_SAFARI = "sa"; - - public static final String ENGINE_GECKO = "gecko"; - public static final String ENGINE_WEBKIT = "webkit"; - public static final String ENGINE_PRESTO = "presto"; - public static final String ENGINE_TRIDENT = "trident"; - - private static final String OS_WINDOWS = "win"; - private static final String OS_LINUX = "lin"; - private static final String OS_MACOSX = "mac"; - private static final String OS_ANDROID = "android"; - private static final String OS_IOS = "ios"; - - // Common CSS class for all touch devices - private static final String UI_TOUCH = "touch"; - - private static BrowserInfo instance; - - private static String cssClass = null; - - static { - // Add browser dependent v-* classnames to body to help css hacks - String browserClassnames = get().getCSSClass(); - RootPanel.get().addStyleName(browserClassnames); - } - - /** - * Singleton method to get BrowserInfo object. - * - * @return instance of BrowserInfo object - */ - public static BrowserInfo get() { - if (instance == null) { - instance = new BrowserInfo(); - } - return instance; - } - - private VBrowserDetails browserDetails; - private boolean touchDevice; - - private BrowserInfo() { - browserDetails = new VBrowserDetails(getBrowserString()); - if (browserDetails.isIE()) { - // Use document mode instead user agent to accurately detect how we - // are rendering - int documentMode = getIEDocumentMode(); - if (documentMode != -1) { - browserDetails.setIEMode(documentMode); - } - } - - if (browserDetails.isChrome()) { - touchDevice = detectChromeTouchDevice(); - } else { - touchDevice = detectTouchDevice(); - } - } - - private native boolean detectTouchDevice() - /*-{ - try { document.createEvent("TouchEvent");return true;} catch(e){return false;}; - }-*/; - - private native boolean detectChromeTouchDevice() - /*-{ - return ("ontouchstart" in window); - }-*/; - - private native int getIEDocumentMode() - /*-{ - var mode = $wnd.document.documentMode; - if (!mode) - return -1; - return mode; - }-*/; - - /** - * Returns a string representing the browser in use, for use in CSS - * classnames. The classnames will be space separated abbreviations, - * optionally with a version appended. - * - * Abbreviations: Firefox: ff Internet Explorer: ie Safari: sa Opera: op - * - * Browsers that CSS-wise behave like each other will get the same - * abbreviation (this usually depends on the rendering engine). - * - * This is quite simple at the moment, more heuristics will be added when - * needed. - * - * Examples: Internet Explorer 6: ".v-ie .v-ie6 .v-ie60", Firefox 3.0.4: - * ".v-ff .v-ff3 .v-ff30", Opera 9.60: ".v-op .v-op9 .v-op960", Opera 10.10: - * ".v-op .v-op10 .v-op1010" - * - * @return - */ - public String getCSSClass() { - String prefix = "v-"; - - if (cssClass == null) { - String browserIdentifier = ""; - String majorVersionClass = ""; - String minorVersionClass = ""; - String browserEngineClass = ""; - - if (browserDetails.isFirefox()) { - browserIdentifier = BROWSER_FIREFOX; - majorVersionClass = browserIdentifier - + getBrowserMajorVersion(); - minorVersionClass = majorVersionClass - + browserDetails.getBrowserMinorVersion(); - browserEngineClass = ENGINE_GECKO; - } else if (browserDetails.isChrome()) { - // TODO update when Chrome is more stable - browserIdentifier = BROWSER_SAFARI; - majorVersionClass = "ch"; - browserEngineClass = ENGINE_WEBKIT; - } else if (browserDetails.isSafari()) { - browserIdentifier = BROWSER_SAFARI; - majorVersionClass = browserIdentifier - + getBrowserMajorVersion(); - minorVersionClass = majorVersionClass - + browserDetails.getBrowserMinorVersion(); - browserEngineClass = ENGINE_WEBKIT; - } else if (browserDetails.isIE()) { - browserIdentifier = BROWSER_IE; - majorVersionClass = browserIdentifier - + getBrowserMajorVersion(); - minorVersionClass = majorVersionClass - + browserDetails.getBrowserMinorVersion(); - browserEngineClass = ENGINE_TRIDENT; - } else if (browserDetails.isOpera()) { - browserIdentifier = BROWSER_OPERA; - majorVersionClass = browserIdentifier - + getBrowserMajorVersion(); - minorVersionClass = majorVersionClass - + browserDetails.getBrowserMinorVersion(); - browserEngineClass = ENGINE_PRESTO; - } - - cssClass = prefix + browserIdentifier; - if (!"".equals(majorVersionClass)) { - cssClass = cssClass + " " + prefix + majorVersionClass; - } - if (!"".equals(minorVersionClass)) { - cssClass = cssClass + " " + prefix + minorVersionClass; - } - if (!"".equals(browserEngineClass)) { - cssClass = cssClass + " " + prefix + browserEngineClass; - } - String osClass = getOperatingSystemClass(); - if (osClass != null) { - cssClass = cssClass + " " + prefix + osClass; - } - if (isTouchDevice()) { - cssClass = cssClass + " " + prefix + UI_TOUCH; - } - } - - return cssClass; - } - - private String getOperatingSystemClass() { - if (browserDetails.isAndroid()) { - return OS_ANDROID; - } else if (browserDetails.isIOS()) { - return OS_IOS; - } else if (browserDetails.isWindows()) { - return OS_WINDOWS; - } else if (browserDetails.isLinux()) { - return OS_LINUX; - } else if (browserDetails.isMacOSX()) { - return OS_MACOSX; - } - // Unknown OS - return null; - } - - public boolean isIE() { - return browserDetails.isIE(); - } - - public boolean isFirefox() { - return browserDetails.isFirefox(); - } - - public boolean isSafari() { - return browserDetails.isSafari(); - } - - public boolean isIE8() { - return isIE() && getBrowserMajorVersion() == 8; - } - - public boolean isIE9() { - return isIE() && getBrowserMajorVersion() == 9; - } - - public boolean isChrome() { - return browserDetails.isChrome(); - } - - public boolean isGecko() { - return browserDetails.isGecko(); - } - - public boolean isWebkit() { - return browserDetails.isWebKit(); - } - - /** - * Returns the Gecko version if the browser is Gecko based. The Gecko - * version for Firefox 2 is 1.8 and 1.9 for Firefox 3. - * - * @return The Gecko version or -1 if the browser is not Gecko based - */ - public float getGeckoVersion() { - if (!browserDetails.isGecko()) { - return -1; - } - - return browserDetails.getBrowserEngineVersion(); - } - - /** - * Returns the WebKit version if the browser is WebKit based. The WebKit - * version returned is the major version e.g., 523. - * - * @return The WebKit version or -1 if the browser is not WebKit based - */ - public float getWebkitVersion() { - if (!browserDetails.isWebKit()) { - return -1; - } - - return browserDetails.getBrowserEngineVersion(); - } - - public float getIEVersion() { - if (!browserDetails.isIE()) { - return -1; - } - - return getBrowserMajorVersion(); - } - - public float getOperaVersion() { - if (!browserDetails.isOpera()) { - return -1; - } - - return getBrowserMajorVersion(); - } - - public boolean isOpera() { - return browserDetails.isOpera(); - } - - public boolean isOpera10() { - return browserDetails.isOpera() && getBrowserMajorVersion() == 10; - } - - public boolean isOpera11() { - return browserDetails.isOpera() && getBrowserMajorVersion() == 11; - } - - public native static String getBrowserString() - /*-{ - return $wnd.navigator.userAgent; - }-*/; - - public native int getScreenWidth() - /*-{ - return $wnd.screen.width; - }-*/; - - public native int getScreenHeight() - /*-{ - return $wnd.screen.height; - }-*/; - - /** - * @return true if the browser runs on a touch based device. - */ - public boolean isTouchDevice() { - return touchDevice; - } - - /** - * Indicates whether the browser might require juggling to properly update - * sizes inside elements with overflow: auto. - * - * @return <code>true</code> if the browser requires the workaround, - * otherwise <code>false</code> - */ - public boolean requiresOverflowAutoFix() { - return (getWebkitVersion() > 0 || getOperaVersion() >= 11) - && Util.getNativeScrollbarSize() > 0; - } - - /** - * Checks if the browser is run on iOS - * - * @return true if the browser is run on iOS, false otherwise - */ - public boolean isIOS() { - return browserDetails.isIOS(); - } - - /** - * Checks if the browser is run on Android - * - * @return true if the browser is run on Android, false otherwise - */ - public boolean isAndroid() { - return browserDetails.isAndroid(); - } - - /** - * Checks if the browser is capable of handling scrolling natively or if a - * touch scroll helper is needed for scrolling. - * - * @return true if browser needs a touch scroll helper, false if the browser - * can handle scrolling natively - */ - public boolean requiresTouchScrollDelegate() { - if (!isTouchDevice()) { - return false; - } - if (isAndroid() && isWebkit() && getWebkitVersion() >= 534) { - return false; - } - // Cannot enable native touch scrolling on iOS 5 until #8792 is resolved - // if (isIOS() && isWebkit() && getWebkitVersion() >= 534) { - // return false; - // } - return true; - } - - /** - * Tests if this is an Android devices with a broken scrollTop - * implementation - * - * @return true if scrollTop cannot be trusted on this device, false - * otherwise - */ - public boolean isAndroidWithBrokenScrollTop() { - return isAndroid() - && (getOperatingSystemMajorVersion() == 3 || getOperatingSystemMajorVersion() == 4); - } - - private int getOperatingSystemMajorVersion() { - return browserDetails.getOperatingSystemMajorVersion(); - } - - /** - * Returns the browser major version e.g., 3 for Firefox 3.5, 4 for Chrome - * 4, 8 for Internet Explorer 8. - * <p> - * Note that Internet Explorer 8 and newer will return the document mode so - * IE8 rendering as IE7 will return 7. - * </p> - * - * @return The major version of the browser. - */ - public int getBrowserMajorVersion() { - return browserDetails.getBrowserMajorVersion(); - } - - /** - * Returns the browser minor version e.g., 5 for Firefox 3.5. - * - * @see #getBrowserMajorVersion() - * - * @return The minor version of the browser, or -1 if not known/parsed. - */ - public int getBrowserMinorVersion() { - return browserDetails.getBrowserMinorVersion(); - } - - /** - * Checks if the browser version is newer or equal to the given major+minor - * version. - * - * @param majorVersion - * The major version to check for - * @param minorVersion - * The minor version to check for - * @return true if the browser version is newer or equal to the given - * version - */ - public boolean isBrowserVersionNewerOrEqual(int majorVersion, - int minorVersion) { - if (getBrowserMajorVersion() == majorVersion) { - // Same major - return (getBrowserMinorVersion() >= minorVersion); - } - - // Older or newer major - return (getBrowserMajorVersion() > majorVersion); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/CSSRule.java b/client/src/com/vaadin/terminal/gwt/client/CSSRule.java deleted file mode 100644 index 1571e9bdf0..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/CSSRule.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.core.client.JavaScriptObject; - -/** - * Utility class for fetching CSS properties from DOM StyleSheets JS object. - */ -public class CSSRule { - - private final String selector; - private JavaScriptObject rules = null; - - /** - * - * @param selector - * the CSS selector to search for in the stylesheets - * @param deep - * should the search follow any @import statements? - */ - public CSSRule(final String selector, final boolean deep) { - this.selector = selector; - fetchRule(selector, deep); - } - - // TODO how to find the right LINK-element? We should probably give the - // stylesheet a name. - private native void fetchRule(final String selector, final boolean deep) - /*-{ - var sheets = $doc.styleSheets; - for(var i = 0; i < sheets.length; i++) { - var sheet = sheets[i]; - if(sheet.href && sheet.href.indexOf("VAADIN/themes")>-1) { - // $entry not needed as function is not exported - this.@com.vaadin.terminal.gwt.client.CSSRule::rules = @com.vaadin.terminal.gwt.client.CSSRule::searchForRule(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Z)(sheet, selector, deep); - return; - } - } - this.@com.vaadin.terminal.gwt.client.CSSRule::rules = []; - }-*/; - - /* - * Loops through all current style rules and collects all matching to - * 'rules' array. The array is reverse ordered (last one found is first). - */ - private static native JavaScriptObject searchForRule( - final JavaScriptObject sheet, final String selector, - final boolean deep) - /*-{ - if(!$doc.styleSheets) - return null; - - selector = selector.toLowerCase(); - - var allMatches = []; - - // IE handles imported sheet differently - if(deep && sheet.imports && sheet.imports.length > 0) { - for(var i=0; i < sheet.imports.length; i++) { - // $entry not needed as function is not exported - var imports = @com.vaadin.terminal.gwt.client.CSSRule::searchForRule(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Z)(sheet.imports[i], selector, deep); - allMatches.concat(imports); - } - } - - var theRules = new Array(); - if (sheet.cssRules) - theRules = sheet.cssRules - else if (sheet.rules) - theRules = sheet.rules - - var j = theRules.length; - for(var i=0; i<j; i++) { - var r = theRules[i]; - if(r.type == 1 || sheet.imports) { - var selectors = r.selectorText.toLowerCase().split(","); - var n = selectors.length; - for(var m=0; m<n; m++) { - if(selectors[m].replace(/^\s+|\s+$/g, "") == selector) { - allMatches.unshift(r); - break; // No need to loop other selectors for this rule - } - } - } else if(deep && r.type == 3) { - // Search @import stylesheet - // $entry not needed as function is not exported - var imports = @com.vaadin.terminal.gwt.client.CSSRule::searchForRule(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Z)(r.styleSheet, selector, deep); - allMatches = allMatches.concat(imports); - } - } - - return allMatches; - }-*/; - - /** - * Returns a specific property value from this CSS rule. - * - * @param propertyName - * camelCase CSS property name - * @return the value of the property as a String - */ - public native String getPropertyValue(final String propertyName) - /*-{ - var j = this.@com.vaadin.terminal.gwt.client.CSSRule::rules.length; - for(var i=0; i<j; i++) { - // $entry not needed as function is not exported - var value = this.@com.vaadin.terminal.gwt.client.CSSRule::rules[i].style[propertyName]; - if(value) - return value; - } - return null; - }-*/; - - public String getSelector() { - return selector; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ComponentConnector.java b/client/src/com/vaadin/terminal/gwt/client/ComponentConnector.java deleted file mode 100644 index 066e609d2c..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ComponentConnector.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.dom.client.Element; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ComponentState; - -/** - * An interface used by client-side widgets or paintable parts to receive - * updates from the corresponding server-side components in the form of - * {@link UIDL}. - * - * Updates can be sent back to the server using the - * {@link ApplicationConnection#updateVariable()} methods. - */ -public interface ComponentConnector extends ServerConnector { - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.VPaintable#getState() - */ - @Override - public ComponentState getState(); - - /** - * Returns the widget for this {@link ComponentConnector} - */ - public Widget getWidget(); - - public LayoutManager getLayoutManager(); - - /** - * Returns <code>true</code> if the width of this paintable is currently - * undefined. If the width is undefined, the actual width of the paintable - * is defined by its contents. - * - * @return <code>true</code> if the width is undefined, else - * <code>false</code> - */ - public boolean isUndefinedWidth(); - - /** - * Returns <code>true</code> if the height of this paintable is currently - * undefined. If the height is undefined, the actual height of the paintable - * is defined by its contents. - * - * @return <code>true</code> if the height is undefined, else - * <code>false</code> - */ - public boolean isUndefinedHeight(); - - /** - * Returns <code>true</code> if the width of this paintable is currently - * relative. If the width is relative, the actual width of the paintable is - * a percentage of the size allocated to it by its parent. - * - * @return <code>true</code> if the width is undefined, else - * <code>false</code> - */ - public boolean isRelativeWidth(); - - /** - * Returns <code>true</code> if the height of this paintable is currently - * relative. If the height is relative, the actual height of the paintable - * is a percentage of the size allocated to it by its parent. - * - * @return <code>true</code> if the width is undefined, else - * <code>false</code> - */ - public boolean isRelativeHeight(); - - /** - * Checks if the connector is read only. - * - * @deprecated This belongs in AbstractFieldConnector, see #8514 - * @return true - */ - @Deprecated - public boolean isReadOnly(); - - public boolean hasEventListener(String eventIdentifier); - - /** - * Return true if parent handles caption, false if the paintable handles the - * caption itself. - * - * <p> - * This should always return true and all components should let the parent - * handle the caption and use other attributes for internal texts in the - * component - * </p> - * - * @return true if caption handling is delegated to the parent, false if - * parent should not be allowed to render caption - */ - public boolean delegateCaptionHandling(); - - /** - * Sets the enabled state of the widget associated to this connector. - * - * @param widgetEnabled - * true if the widget should be enabled, false otherwise - */ - public void setWidgetEnabled(boolean widgetEnabled); - - /** - * Gets the tooltip info for the given element. - * - * @param element - * The element to lookup a tooltip for - * @return The tooltip for the element or null if no tooltip is defined for - * this element. - */ - public TooltipInfo getTooltipInfo(Element element); - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ComponentContainerConnector.java b/client/src/com/vaadin/terminal/gwt/client/ComponentContainerConnector.java deleted file mode 100644 index b74e77d01f..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ComponentContainerConnector.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import java.util.List; - -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.ui.HasWidgets; -import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent.ConnectorHierarchyChangeHandler; - -/** - * An interface used by client-side connectors whose widget is a component - * container (implements {@link HasWidgets}). - */ -public interface ComponentContainerConnector extends ServerConnector { - - /** - * Update child components caption, description and error message. - * - * <p> - * Each component is responsible for maintaining its caption, description - * and error message. In most cases components doesn't want to do that and - * those elements reside outside of the component. Because of this layouts - * must provide service for it's childen to show those elements for them. - * </p> - * - * @param connector - * Child component for which service is requested. - */ - void updateCaption(ComponentConnector connector); - - /** - * Returns the children for this connector. - * <p> - * The children for this connector are defined as all - * {@link ComponentConnector}s whose parent is this - * {@link ComponentContainerConnector}. - * </p> - * - * @return A collection of children for this connector. An empty collection - * if there are no children. Never returns null. - */ - public List<ComponentConnector> getChildComponents(); - - /** - * Sets the children for this connector. This method should only be called - * by the framework to ensure that the connector hierarchy on the client - * side and the server side are in sync. - * <p> - * Note that calling this method does not call - * {@link ConnectorHierarchyChangeHandler#onConnectorHierarchyChange(ConnectorHierarchyChangeEvent)} - * . The event method is called only when the hierarchy has been updated for - * all connectors. - * - * @param children - * The new child connectors - */ - public void setChildComponents(List<ComponentConnector> children); - - /** - * Adds a handler that is called whenever the child hierarchy of this - * connector has been updated by the server. - * - * @param handler - * The handler that should be added. - * @return A handler registration reference that can be used to unregister - * the handler - */ - public HandlerRegistration addConnectorHierarchyChangeHandler( - ConnectorHierarchyChangeHandler handler); - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ComponentDetail.java b/client/src/com/vaadin/terminal/gwt/client/ComponentDetail.java deleted file mode 100644 index cd7ad0178f..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ComponentDetail.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import java.util.HashMap; - -class ComponentDetail { - - private TooltipInfo tooltipInfo = new TooltipInfo(); - - public ComponentDetail() { - - } - - /** - * Returns a TooltipInfo assosiated with Component. If element is given, - * returns an additional TooltipInfo. - * - * @param key - * @return the tooltipInfo - */ - public TooltipInfo getTooltipInfo(Object key) { - if (key == null) { - return tooltipInfo; - } else { - if (additionalTooltips != null) { - return additionalTooltips.get(key); - } else { - return null; - } - } - } - - /** - * @param tooltipInfo - * the tooltipInfo to set - */ - public void setTooltipInfo(TooltipInfo tooltipInfo) { - this.tooltipInfo = tooltipInfo; - } - - private HashMap<Object, TooltipInfo> additionalTooltips; - - public void putAdditionalTooltip(Object key, TooltipInfo tooltip) { - if (tooltip == null && additionalTooltips != null) { - additionalTooltips.remove(key); - } else { - if (additionalTooltips == null) { - additionalTooltips = new HashMap<Object, TooltipInfo>(); - } - additionalTooltips.put(key, tooltip); - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ComponentDetailMap.java b/client/src/com/vaadin/terminal/gwt/client/ComponentDetailMap.java deleted file mode 100644 index 3566d4e86f..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ComponentDetailMap.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import java.util.ArrayList; -import java.util.Collection; - -import com.google.gwt.core.client.JavaScriptObject; - -final class ComponentDetailMap extends JavaScriptObject { - - protected ComponentDetailMap() { - } - - static ComponentDetailMap create() { - return (ComponentDetailMap) JavaScriptObject.createObject(); - } - - boolean isEmpty() { - return size() == 0; - } - - final native boolean containsKey(String key) - /*-{ - return this.hasOwnProperty(key); - }-*/; - - final native ComponentDetail get(String key) - /*-{ - return this[key]; - }-*/; - - final native void put(String id, ComponentDetail value) - /*-{ - this[id] = value; - }-*/; - - final native void remove(String id) - /*-{ - delete this[id]; - }-*/; - - final native int size() - /*-{ - var count = 0; - for(var key in this) { - count++; - } - return count; - }-*/; - - final native void clear() - /*-{ - for(var key in this) { - if(this.hasOwnProperty(key)) { - delete this[key]; - } - } - }-*/; - - private final native void fillWithValues(Collection<ComponentDetail> list) - /*-{ - for(var key in this) { - // $entry not needed as function is not exported - list.@java.util.Collection::add(Ljava/lang/Object;)(this[key]); - } - }-*/; - - final Collection<ComponentDetail> values() { - ArrayList<ComponentDetail> list = new ArrayList<ComponentDetail>(); - fillWithValues(list); - return list; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ComponentLocator.java b/client/src/com/vaadin/terminal/gwt/client/ComponentLocator.java deleted file mode 100644 index 22a28d14bf..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ComponentLocator.java +++ /dev/null @@ -1,622 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.HasWidgets; -import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ComponentState; -import com.vaadin.shared.Connector; -import com.vaadin.shared.communication.SharedState; -import com.vaadin.terminal.gwt.client.ui.SubPartAware; -import com.vaadin.terminal.gwt.client.ui.UI.VUI; -import com.vaadin.terminal.gwt.client.ui.gridlayout.VGridLayout; -import com.vaadin.terminal.gwt.client.ui.orderedlayout.VMeasuringOrderedLayout; -import com.vaadin.terminal.gwt.client.ui.tabsheet.VTabsheetPanel; -import com.vaadin.terminal.gwt.client.ui.window.VWindow; -import com.vaadin.terminal.gwt.client.ui.window.WindowConnector; - -/** - * ComponentLocator provides methods for generating a String locator for a given - * DOM element and for locating a DOM element using a String locator. - */ -public class ComponentLocator { - - /** - * Separator used in the String locator between a parent and a child widget. - */ - private static final String PARENTCHILD_SEPARATOR = "/"; - - /** - * Separator used in the String locator between the part identifying the - * containing widget and the part identifying the target element within the - * widget. - */ - private static final String SUBPART_SEPARATOR = "#"; - - /** - * String that identifies the root panel when appearing first in the String - * locator. - */ - private static final String ROOT_ID = "Root"; - - /** - * Reference to ApplicationConnection instance. - */ - private ApplicationConnection client; - - /** - * Construct a ComponentLocator for the given ApplicationConnection. - * - * @param client - * ApplicationConnection instance for the application. - */ - public ComponentLocator(ApplicationConnection client) { - this.client = client; - } - - /** - * Generates a String locator which uniquely identifies the target element. - * The {@link #getElementByPath(String)} method can be used for the inverse - * operation, i.e. locating an element based on the return value from this - * method. - * <p> - * Note that getElementByPath(getPathForElement(element)) == element is not - * always true as {@link #getPathForElement(Element)} can return a path to - * another element if the widget determines an action on the other element - * will give the same result as the action on the target element. - * </p> - * - * @since 5.4 - * @param targetElement - * The element to generate a path for. - * @return A String locator that identifies the target element or null if a - * String locator could not be created. - */ - public String getPathForElement(Element targetElement) { - String pid = null; - - Element e = targetElement; - - while (true) { - pid = ConnectorMap.get(client).getConnectorId(e); - if (pid != null) { - break; - } - - e = DOM.getParent(e); - if (e == null) { - break; - } - } - - Widget w = null; - if (pid != null) { - // If we found a Paintable then we use that as reference. We should - // find the Paintable for all but very special cases (like - // overlays). - w = ((ComponentConnector) ConnectorMap.get(client) - .getConnector(pid)).getWidget(); - - /* - * Still if the Paintable contains a widget that implements - * SubPartAware, we want to use that as a reference - */ - Widget targetParent = findParentWidget(targetElement, w); - while (targetParent != w && targetParent != null) { - if (targetParent instanceof SubPartAware) { - /* - * The targetParent widget is a child of the Paintable and - * the first parent (of the targetElement) that implements - * SubPartAware - */ - w = targetParent; - break; - } - targetParent = targetParent.getParent(); - } - } - if (w == null) { - // Check if the element is part of a widget that is attached - // directly to the root panel - RootPanel rootPanel = RootPanel.get(); - int rootWidgetCount = rootPanel.getWidgetCount(); - for (int i = 0; i < rootWidgetCount; i++) { - Widget rootWidget = rootPanel.getWidget(i); - if (rootWidget.getElement().isOrHasChild(targetElement)) { - // The target element is contained by this root widget - w = findParentWidget(targetElement, rootWidget); - break; - } - } - if (w != null) { - // We found a widget but we should still see if we find a - // SubPartAware implementor (we cannot find the Paintable as - // there is no link from VOverlay to its paintable/owner). - Widget subPartAwareWidget = findSubPartAwareParentWidget(w); - if (subPartAwareWidget != null) { - w = subPartAwareWidget; - } - } - } - - if (w == null) { - // Containing widget not found - return null; - } - - // Determine the path for the target widget - String path = getPathForWidget(w); - if (path == null) { - /* - * No path could be determined for the target widget. Cannot create - * a locator string. - */ - return null; - } - - if (w.getElement() == targetElement) { - /* - * We are done if the target element is the root of the target - * widget. - */ - return path; - } else if (w instanceof SubPartAware) { - /* - * If the widget can provide an identifier for the targetElement we - * let it do that - */ - String elementLocator = ((SubPartAware) w) - .getSubPartName(targetElement); - if (elementLocator != null) { - return path + SUBPART_SEPARATOR + elementLocator; - } - } - /* - * If everything else fails we use the DOM path to identify the target - * element - */ - return path + getDOMPathForElement(targetElement, w.getElement()); - } - - /** - * Finds the first widget in the hierarchy (moving upwards) that implements - * SubPartAware. Returns the SubPartAware implementor or null if none is - * found. - * - * @param w - * The widget to start from. This is returned if it implements - * SubPartAware. - * @return The first widget (upwards in hierarchy) that implements - * SubPartAware or null - */ - private Widget findSubPartAwareParentWidget(Widget w) { - - while (w != null) { - if (w instanceof SubPartAware) { - return w; - } - w = w.getParent(); - } - return null; - } - - /** - * Returns the first widget found when going from {@code targetElement} - * upwards in the DOM hierarchy, assuming that {@code ancestorWidget} is a - * parent of {@code targetElement}. - * - * @param targetElement - * @param ancestorWidget - * @return The widget whose root element is a parent of - * {@code targetElement}. - */ - private Widget findParentWidget(Element targetElement, Widget ancestorWidget) { - /* - * As we cannot resolve Widgets from the element we start from the - * widget and move downwards to the correct child widget, as long as we - * find one. - */ - if (ancestorWidget instanceof HasWidgets) { - for (Widget w : ((HasWidgets) ancestorWidget)) { - if (w.getElement().isOrHasChild(targetElement)) { - return findParentWidget(targetElement, w); - } - } - } - - // No children found, this is it - return ancestorWidget; - } - - /** - * Locates an element based on a DOM path and a base element. - * - * @param baseElement - * The base element which the path is relative to - * @param path - * String locator (consisting of domChild[x] parts) that - * identifies the element - * @return The element identified by path, relative to baseElement or null - * if the element could not be found. - */ - private Element getElementByDOMPath(Element baseElement, String path) { - String parts[] = path.split(PARENTCHILD_SEPARATOR); - Element element = baseElement; - - for (String part : parts) { - if (part.startsWith("domChild[")) { - String childIndexString = part.substring("domChild[".length(), - part.length() - 1); - try { - int childIndex = Integer.parseInt(childIndexString); - element = DOM.getChild(element, childIndex); - } catch (Exception e) { - return null; - } - } - } - - return element; - } - - /** - * Generates a String locator using domChild[x] parts for the element - * relative to the baseElement. - * - * @param element - * The target element - * @param baseElement - * The starting point for the locator. The generated path is - * relative to this element. - * @return A String locator that can be used to locate the target element - * using {@link #getElementByDOMPath(Element, String)} or null if - * the locator String cannot be created. - */ - private String getDOMPathForElement(Element element, Element baseElement) { - Element e = element; - String path = ""; - while (true) { - Element parent = DOM.getParent(e); - if (parent == null) { - return null; - } - - int childIndex = -1; - - int childCount = DOM.getChildCount(parent); - for (int i = 0; i < childCount; i++) { - if (e == DOM.getChild(parent, i)) { - childIndex = i; - break; - } - } - if (childIndex == -1) { - return null; - } - - path = PARENTCHILD_SEPARATOR + "domChild[" + childIndex + "]" - + path; - - if (parent == baseElement) { - break; - } - - e = parent; - } - - return path; - } - - /** - * Locates an element using a String locator (path) which identifies a DOM - * element. The {@link #getPathForElement(Element)} method can be used for - * the inverse operation, i.e. generating a string expression for a DOM - * element. - * - * @since 5.4 - * @param path - * The String locater which identifies the target element. - * @return The DOM element identified by {@code path} or null if the element - * could not be located. - */ - public Element getElementByPath(String path) { - /* - * Path is of type "targetWidgetPath#componentPart" or - * "targetWidgetPath". - */ - String parts[] = path.split(SUBPART_SEPARATOR, 2); - String widgetPath = parts[0]; - Widget w = getWidgetFromPath(widgetPath); - if (w == null || !Util.isAttachedAndDisplayed(w)) { - return null; - } - - if (parts.length == 1) { - int pos = widgetPath.indexOf("domChild"); - if (pos == -1) { - return w.getElement(); - } - - // Contains dom reference to a sub element of the widget - String subPath = widgetPath.substring(pos); - return getElementByDOMPath(w.getElement(), subPath); - } else if (parts.length == 2) { - if (w instanceof SubPartAware) { - return ((SubPartAware) w).getSubPartElement(parts[1]); - } - } - - return null; - } - - /** - * Creates a locator String for the given widget. The path can be used to - * locate the widget using {@link #getWidgetFromPath(String)}. - * - * Returns null if no path can be determined for the widget or if the widget - * is null. - * - * @param w - * The target widget - * @return A String locator for the widget - */ - private String getPathForWidget(Widget w) { - if (w == null) { - return null; - } - - if (w instanceof VUI) { - return ""; - } else if (w instanceof VWindow) { - Connector windowConnector = ConnectorMap.get(client) - .getConnector(w); - List<WindowConnector> subWindowList = client.getRootConnector() - .getSubWindows(); - int indexOfSubWindow = subWindowList.indexOf(windowConnector); - return PARENTCHILD_SEPARATOR + "VWindow[" + indexOfSubWindow + "]"; - } else if (w instanceof RootPanel) { - return ROOT_ID; - } - - Widget parent = w.getParent(); - - String basePath = getPathForWidget(parent); - if (basePath == null) { - return null; - } - String simpleName = Util.getSimpleName(w); - - /* - * Check if the parent implements Iterable. At least VPopupView does not - * implement HasWdgets so we cannot check for that. - */ - if (!(parent instanceof Iterable<?>)) { - // Parent does not implement Iterable so we cannot find out which - // child this is - return null; - } - - Iterator<?> i = ((Iterable<?>) parent).iterator(); - int pos = 0; - while (i.hasNext()) { - Object child = i.next(); - if (child == w) { - return basePath + PARENTCHILD_SEPARATOR + simpleName + "[" - + pos + "]"; - } - String simpleName2 = Util.getSimpleName(child); - if (simpleName.equals(simpleName2)) { - pos++; - } - } - - return null; - } - - /** - * Locates the widget based on a String locator. - * - * @param path - * The String locator that identifies the widget. - * @return The Widget identified by the String locator or null if the widget - * could not be identified. - */ - private Widget getWidgetFromPath(String path) { - Widget w = null; - String parts[] = path.split(PARENTCHILD_SEPARATOR); - - for (int i = 0; i < parts.length; i++) { - String part = parts[i]; - - if (part.equals(ROOT_ID)) { - w = RootPanel.get(); - } else if (part.equals("")) { - w = client.getRootConnector().getWidget(); - } else if (w == null) { - String id = part; - // Must be old static pid (PID_S*) - ServerConnector connector = ConnectorMap.get(client) - .getConnector(id); - if (connector == null) { - // Lookup by component id - // TODO Optimize this - connector = findConnectorById(client.getRootConnector(), - id.substring(5)); - } - - if (connector instanceof ComponentConnector) { - w = ((ComponentConnector) connector).getWidget(); - } else { - // Not found - return null; - } - } else if (part.startsWith("domChild[")) { - // The target widget has been found and the rest identifies the - // element - break; - } else if (w instanceof Iterable) { - // W identifies a widget that contains other widgets, as it - // should. Try to locate the child - Iterable<?> parent = (Iterable<?>) w; - - // Part is of type "VVerticalLayout[0]", split this into - // VVerticalLayout and 0 - String[] split = part.split("\\[", 2); - String widgetClassName = split[0]; - String indexString = split[1]; - int widgetPosition = Integer.parseInt(indexString.substring(0, - indexString.length() - 1)); - - // AbsolutePanel in GridLayout has been removed -> skip it - if (w instanceof VGridLayout - && "AbsolutePanel".equals(widgetClassName)) { - continue; - } - - if (w instanceof VTabsheetPanel && widgetPosition != 0) { - // TabSheetPanel now only contains 1 connector => the index - // is always 0 which indicates the widget in the active tab - widgetPosition = 0; - } - - /* - * The new grid and ordered layotus do not contain - * ChildComponentContainer widgets. This is instead simulated by - * constructing a path step that would find the desired widget - * from the layout and injecting it as the next search step - * (which would originally have found the widget inside the - * ChildComponentContainer) - */ - if ((w instanceof VMeasuringOrderedLayout || w instanceof VGridLayout) - && "ChildComponentContainer".equals(widgetClassName) - && i + 1 < parts.length) { - - HasWidgets layout = (HasWidgets) w; - - String nextPart = parts[i + 1]; - String[] nextSplit = nextPart.split("\\[", 2); - String nextWidgetClassName = nextSplit[0]; - - // Find the n:th child and count the number of children with - // the same type before it - int nextIndex = 0; - for (Widget child : layout) { - boolean matchingType = nextWidgetClassName.equals(Util - .getSimpleName(child)); - if (matchingType && widgetPosition == 0) { - // This is the n:th child that we looked for - break; - } else if (widgetPosition < 0) { - // Error if we're past the desired position without - // a match - return null; - } else if (matchingType) { - // If this was another child of the expected type, - // increase the count for the next step - nextIndex++; - } - - // Don't count captions - if (!(child instanceof VCaption)) { - widgetPosition--; - } - } - - // Advance to the next step, this time checking for the - // actual child widget - parts[i + 1] = nextWidgetClassName + '[' + nextIndex + ']'; - continue; - } - - // Locate the child - Iterator<? extends Widget> iterator; - - /* - * VWindow and VContextMenu workarounds for backwards - * compatibility - */ - if (widgetClassName.equals("VWindow")) { - List<WindowConnector> windows = client.getRootConnector() - .getSubWindows(); - List<VWindow> windowWidgets = new ArrayList<VWindow>( - windows.size()); - for (WindowConnector wc : windows) { - windowWidgets.add(wc.getWidget()); - } - iterator = windowWidgets.iterator(); - } else if (widgetClassName.equals("VContextMenu")) { - return client.getContextMenu(); - } else { - iterator = (Iterator<? extends Widget>) parent.iterator(); - } - - boolean ok = false; - - // Find the widgetPosition:th child of type "widgetClassName" - while (iterator.hasNext()) { - - Widget child = iterator.next(); - String simpleName2 = Util.getSimpleName(child); - - if (widgetClassName.equals(simpleName2)) { - if (widgetPosition == 0) { - w = child; - ok = true; - break; - } - widgetPosition--; - } - } - - if (!ok) { - // Did not find the child - return null; - } - } else { - // W identifies something that is not a "HasWidgets". This - // should not happen as all widget containers should implement - // HasWidgets. - return null; - } - } - - return w; - } - - private ServerConnector findConnectorById(ServerConnector root, String id) { - SharedState state = root.getState(); - if (state instanceof ComponentState - && id.equals(((ComponentState) state).getId())) { - return root; - } - for (ServerConnector child : root.getChildren()) { - ServerConnector found = findConnectorById(child, id); - if (found != null) { - return found; - } - } - - return null; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ComputedStyle.java b/client/src/com/vaadin/terminal/gwt/client/ComputedStyle.java deleted file mode 100644 index 7662ba634b..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ComputedStyle.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.dom.client.Element; - -public class ComputedStyle { - - protected final JavaScriptObject computedStyle; - private final Element elem; - - /** - * Gets this element's computed style object which can be used to gather - * information about the current state of the rendered node. - * <p> - * Note that this method is expensive. Wherever possible, reuse the returned - * object. - * - * @param elem - * the element - * @return the computed style - */ - public ComputedStyle(Element elem) { - computedStyle = getComputedStyle(elem); - this.elem = elem; - } - - private static native JavaScriptObject getComputedStyle(Element elem) - /*-{ - if(elem.nodeType != 1) { - return {}; - } - - if($wnd.document.defaultView && $wnd.document.defaultView.getComputedStyle) { - return $wnd.document.defaultView.getComputedStyle(elem, null); - } - - if(elem.currentStyle) { - return elem.currentStyle; - } - }-*/; - - /** - * - * @param name - * name of the CSS property in camelCase - * @return the value of the property, normalized for across browsers (each - * browser returns pixel values whenever possible). - */ - public final native String getProperty(String name) - /*-{ - var cs = this.@com.vaadin.terminal.gwt.client.ComputedStyle::computedStyle; - var elem = this.@com.vaadin.terminal.gwt.client.ComputedStyle::elem; - - // Border values need to be checked separately. The width might have a - // meaningful value even if the border style is "none". In that case the - // value should be 0. - if(name.indexOf("border") > -1 && name.indexOf("Width") > -1) { - var borderStyleProp = name.substring(0,name.length-5) + "Style"; - if(cs.getPropertyValue) - var borderStyle = cs.getPropertyValue(borderStyleProp); - else // IE - var borderStyle = cs[borderStyleProp]; - if(borderStyle == "none") - return "0px"; - } - - if(cs.getPropertyValue) { - - // Convert name to dashed format - name = name.replace(/([A-Z])/g, "-$1").toLowerCase(); - var ret = cs.getPropertyValue(name); - - } else { - - var ret = cs[name]; - var style = elem.style; - - // From the awesome hack by Dean Edwards - // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 - - // If we're not dealing with a regular pixel number - // but a number that has a weird ending, we need to convert it to pixels - if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { - // Remember the original values - var left = style.left, rsLeft = elem.runtimeStyle.left; - - // Put in the new values to get a computed value out - elem.runtimeStyle.left = cs.left; - style.left = ret || 0; - ret = style.pixelLeft + "px"; - - // Revert the changed values - style.left = left; - elem.runtimeStyle.left = rsLeft; - } - - } - - // Normalize margin values. This is not totally valid, but in most cases - // it is what the user wants to know. - if(name.indexOf("margin") > -1 && ret == "auto") { - return "0px"; - } - - // Some browsers return undefined width and height values as "auto", so - // we need to retrieve those ourselves. - if (name == "width" && ret == "auto") { - ret = elem.clientWidth + "px"; - } else if (name == "height" && ret == "auto") { - ret = elem.clientHeight + "px"; - } - - return ret; - - }-*/; - - public final int getIntProperty(String name) { - Integer parsed = parseInt(getProperty(name)); - if (parsed != null) { - return parsed.intValue(); - } - return 0; - } - - /** - * Get current margin values from the DOM. The array order is the default - * CSS order: top, right, bottom, left. - */ - public final int[] getMargin() { - int[] margin = { 0, 0, 0, 0 }; - margin[0] = getIntProperty("marginTop"); - margin[1] = getIntProperty("marginRight"); - margin[2] = getIntProperty("marginBottom"); - margin[3] = getIntProperty("marginLeft"); - return margin; - } - - /** - * Get current padding values from the DOM. The array order is the default - * CSS order: top, right, bottom, left. - */ - public final int[] getPadding() { - int[] padding = { 0, 0, 0, 0 }; - padding[0] = getIntProperty("paddingTop"); - padding[1] = getIntProperty("paddingRight"); - padding[2] = getIntProperty("paddingBottom"); - padding[3] = getIntProperty("paddingLeft"); - return padding; - } - - /** - * Get current border values from the DOM. The array order is the default - * CSS order: top, right, bottom, left. - */ - public final int[] getBorder() { - int[] border = { 0, 0, 0, 0 }; - border[0] = getIntProperty("borderTopWidth"); - border[1] = getIntProperty("borderRightWidth"); - border[2] = getIntProperty("borderBottomWidth"); - border[3] = getIntProperty("borderLeftWidth"); - return border; - } - - /** - * Takes a String value e.g. "12px" and parses that to int 12. - * - * @param String - * a value starting with a number - * @return int the value from the string before any non-numeric characters. - * If the value cannot be parsed to a number, returns - * <code>null</code>. - */ - public static native Integer parseInt(final String value) - /*-{ - var number = parseInt(value, 10); - if (isNaN(number)) - return null; - else - // $entry not needed as function is not exported - return @java.lang.Integer::valueOf(I)(number); - }-*/; - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ConnectorHierarchyChangeEvent.java b/client/src/com/vaadin/terminal/gwt/client/ConnectorHierarchyChangeEvent.java deleted file mode 100644 index 6abaa89891..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ConnectorHierarchyChangeEvent.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import java.io.Serializable; -import java.util.List; - -import com.google.gwt.event.shared.EventHandler; -import com.google.gwt.event.shared.GwtEvent; -import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent.ConnectorHierarchyChangeHandler; -import com.vaadin.terminal.gwt.client.communication.AbstractServerConnectorEvent; - -/** - * Event for containing data related to a change in the {@link ServerConnector} - * hierarchy. A {@link ConnectorHierarchyChangedEvent} is fired when an update - * from the server has been fully processed and all hierarchy updates have been - * completed. - * - * @author Vaadin Ltd - * @since 7.0.0 - * - */ -public class ConnectorHierarchyChangeEvent extends - AbstractServerConnectorEvent<ConnectorHierarchyChangeHandler> { - /** - * Type of this event, used by the event bus. - */ - public static final Type<ConnectorHierarchyChangeHandler> TYPE = new Type<ConnectorHierarchyChangeHandler>(); - - List<ComponentConnector> oldChildren; - private ComponentContainerConnector parent; - - public ConnectorHierarchyChangeEvent() { - } - - /** - * Returns a collection of the old children for the connector. This was the - * state before the update was received from the server. - * - * @return A collection of old child connectors. Never returns null. - */ - public List<ComponentConnector> getOldChildren() { - return oldChildren; - } - - /** - * Sets the collection of the old children for the connector. - * - * @param oldChildren - * The old child connectors. Must not be null. - */ - public void setOldChildren(List<ComponentConnector> oldChildren) { - this.oldChildren = oldChildren; - } - - /** - * Returns the {@link ComponentContainerConnector} for which this event - * occurred. - * - * @return The {@link ComponentContainerConnector} whose child collection - * has changed. Never returns null. - */ - public ComponentContainerConnector getParent() { - return parent; - } - - /** - * Sets the {@link ComponentContainerConnector} for which this event - * occurred. - * - * @param The - * {@link ComponentContainerConnector} whose child collection has - * changed. - */ - public void setParent(ComponentContainerConnector parent) { - this.parent = parent; - } - - public interface ConnectorHierarchyChangeHandler extends Serializable, - EventHandler { - public void onConnectorHierarchyChange( - ConnectorHierarchyChangeEvent connectorHierarchyChangeEvent); - } - - @Override - public void dispatch(ConnectorHierarchyChangeHandler handler) { - handler.onConnectorHierarchyChange(this); - } - - @Override - public GwtEvent.Type<ConnectorHierarchyChangeHandler> getAssociatedType() { - return TYPE; - } - -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ConnectorMap.java b/client/src/com/vaadin/terminal/gwt/client/ConnectorMap.java deleted file mode 100644 index 8202ef7d17..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ConnectorMap.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.dom.client.Element; -import com.google.gwt.user.client.ui.Widget; - -public class ConnectorMap { - - private Map<String, ServerConnector> idToConnector = new HashMap<String, ServerConnector>(); - - public static ConnectorMap get(ApplicationConnection applicationConnection) { - return applicationConnection.getConnectorMap(); - } - - @Deprecated - private final ComponentDetailMap idToComponentDetail = ComponentDetailMap - .create(); - - /** - * Returns a {@link ServerConnector} by its id - * - * @param id - * The connector id - * @return A connector or null if a connector with the given id has not been - * registered - */ - public ServerConnector getConnector(String connectorId) { - return idToConnector.get(connectorId); - } - - /** - * Returns a {@link ComponentConnector} element by its root element - * - * @param element - * Root element of the {@link ComponentConnector} - * @return A connector or null if a connector with the given id has not been - * registered - */ - public ComponentConnector getConnector(Element element) { - return (ComponentConnector) getConnector(getConnectorId(element)); - } - - /** - * FIXME: What does this even do and why? - * - * @param pid - * @return - */ - public boolean isDragAndDropPaintable(String pid) { - return (pid.startsWith("DD")); - } - - /** - * Checks if a connector with the given id has been registered. - * - * @param connectorId - * The id to check for - * @return true if a connector has been registered with the given id, false - * otherwise - */ - public boolean hasConnector(String connectorId) { - return idToConnector.containsKey(connectorId); - } - - /** - * Removes all registered connectors - */ - public void clear() { - idToConnector.clear(); - idToComponentDetail.clear(); - } - - /** - * Retrieves the connector whose widget matches the parameter. - * - * @param widget - * The widget - * @return A connector with {@literal widget} as its root widget or null if - * no connector was found - */ - public ComponentConnector getConnector(Widget widget) { - return getConnector(widget.getElement()); - } - - public void registerConnector(String id, ServerConnector connector) { - ComponentDetail componentDetail = GWT.create(ComponentDetail.class); - idToComponentDetail.put(id, componentDetail); - idToConnector.put(id, connector); - if (connector instanceof ComponentConnector) { - ComponentConnector pw = (ComponentConnector) connector; - setConnectorId(pw.getWidget().getElement(), id); - } - } - - private native void setConnectorId(Element el, String id) - /*-{ - el.tkPid = id; - }-*/; - - /** - * Gets the connector id using a DOM element - the element should be the - * root element for a connector, otherwise no id will be found. Use - * {@link #getConnectorId(ServerConnector)} instead whenever possible. - * - * @see #getConnectorId(ServerConnector) - * @param el - * element of the connector whose id is desired - * @return the id of the element's connector, if it's a connector - */ - native String getConnectorId(Element el) - /*-{ - return el.tkPid; - }-*/; - - /** - * Gets the main element for the connector with the given id. The reverse of - * {@link #getConnectorId(Element)}. - * - * @param connectorId - * the id of the widget whose element is desired - * @return the element for the connector corresponding to the id - */ - public Element getElement(String connectorId) { - ServerConnector p = getConnector(connectorId); - if (p instanceof ComponentConnector) { - return ((ComponentConnector) p).getWidget().getElement(); - } - - return null; - } - - /** - * Unregisters the given connector; always use after removing a connector. - * This method does not remove the connector from the DOM, but marks the - * connector so that ApplicationConnection may clean up its references to - * it. Removing the widget from DOM is component containers responsibility. - * - * @param connector - * the connector to remove - */ - public void unregisterConnector(ServerConnector connector) { - if (connector == null) { - VConsole.error("Trying to unregister null connector"); - return; - } - - String connectorId = connector.getConnectorId(); - - idToComponentDetail.remove(connectorId); - idToConnector.remove(connectorId); - connector.onUnregister(); - - for (ServerConnector child : connector.getChildren()) { - if (child.getParent() == connector) { - /* - * Only unregister children that are actually connected to this - * parent. For instance when moving connectors from one layout - * to another and removing the first layout it will still - * contain references to its old children, which are now - * attached to another connector. - */ - unregisterConnector(child); - } - } - } - - /** - * Gets all registered {@link ComponentConnector} instances - * - * @return An array of all registered {@link ComponentConnector} instances - */ - public ComponentConnector[] getComponentConnectors() { - ArrayList<ComponentConnector> result = new ArrayList<ComponentConnector>(); - - for (ServerConnector connector : getConnectors()) { - if (connector instanceof ComponentConnector) { - result.add((ComponentConnector) connector); - } - } - - return result.toArray(new ComponentConnector[result.size()]); - } - - @Deprecated - private ComponentDetail getComponentDetail( - ComponentConnector componentConnector) { - return idToComponentDetail.get(componentConnector.getConnectorId()); - } - - public int size() { - return idToConnector.size(); - } - - public Collection<? extends ServerConnector> getConnectors() { - return Collections.unmodifiableCollection(idToConnector.values()); - } - - /** - * Tests if the widget is the root widget of a {@link ComponentConnector}. - * - * @param widget - * The widget to test - * @return true if the widget is the root widget of a - * {@link ComponentConnector}, false otherwise - */ - public boolean isConnector(Widget w) { - return getConnectorId(w.getElement()) != null; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/Console.java b/client/src/com/vaadin/terminal/gwt/client/Console.java deleted file mode 100644 index 4f292e4e28..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/Console.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import java.util.Set; - -public interface Console { - - public abstract void log(String msg); - - public abstract void log(Throwable e); - - public abstract void error(Throwable e); - - public abstract void error(String msg); - - public abstract void printObject(Object msg); - - public abstract void dirUIDL(ValueMap u, ApplicationConnection client); - - public abstract void printLayoutProblems(ValueMap meta, - ApplicationConnection applicationConnection, - Set<ComponentConnector> zeroHeightComponents, - Set<ComponentConnector> zeroWidthComponents); - - public abstract void setQuietMode(boolean quietDebugMode); - - public abstract void init(); - -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ContainerResizedListener.java b/client/src/com/vaadin/terminal/gwt/client/ContainerResizedListener.java deleted file mode 100644 index 01ece2ed80..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ContainerResizedListener.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -/** - * ContainerResizedListener interface is useful for Widgets that support - * relative sizes and who need some additional sizing logic. - */ -public interface ContainerResizedListener { - /** - * This function is run when container box has been resized. Object - * implementing ContainerResizedListener is responsible to call the same - * function on its ancestors that implement NeedsLayout in case their - * container has resized. runAnchestorsLayout(HasWidgets parent) function - * from Util class may be a good helper for this. - * - */ - public void iLayout(); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/DateTimeService.java b/client/src/com/vaadin/terminal/gwt/client/DateTimeService.java deleted file mode 100644 index 8cce0846ac..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/DateTimeService.java +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import java.util.Date; - -import com.google.gwt.i18n.client.DateTimeFormat; -import com.google.gwt.i18n.client.LocaleInfo; -import com.vaadin.terminal.gwt.client.ui.datefield.VDateField; - -/** - * This class provides date/time parsing services to all components on the - * client side. - * - * @author Vaadin Ltd. - * - */ -@SuppressWarnings("deprecation") -public class DateTimeService { - - private String currentLocale; - - private static int[] maxDaysInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, - 31, 30, 31 }; - - /** - * Creates a new date time service with the application default locale. - */ - public DateTimeService() { - currentLocale = LocaleService.getDefaultLocale(); - } - - /** - * Creates a new date time service with a given locale. - * - * @param locale - * e.g. fi, en etc. - * @throws LocaleNotLoadedException - */ - public DateTimeService(String locale) throws LocaleNotLoadedException { - setLocale(locale); - } - - public void setLocale(String locale) throws LocaleNotLoadedException { - if (LocaleService.getAvailableLocales().contains(locale)) { - currentLocale = locale; - } else { - throw new LocaleNotLoadedException(locale); - } - } - - public String getLocale() { - return currentLocale; - } - - public String getMonth(int month) { - try { - return LocaleService.getMonthNames(currentLocale)[month]; - } catch (final LocaleNotLoadedException e) { - VConsole.error(e); - return null; - } - } - - public String getShortMonth(int month) { - try { - return LocaleService.getShortMonthNames(currentLocale)[month]; - } catch (final LocaleNotLoadedException e) { - VConsole.error(e); - return null; - } - } - - public String getDay(int day) { - try { - return LocaleService.getDayNames(currentLocale)[day]; - } catch (final LocaleNotLoadedException e) { - VConsole.error(e); - return null; - } - } - - public String getShortDay(int day) { - try { - return LocaleService.getShortDayNames(currentLocale)[day]; - } catch (final LocaleNotLoadedException e) { - VConsole.error(e); - return null; - } - } - - public int getFirstDayOfWeek() { - try { - return LocaleService.getFirstDayOfWeek(currentLocale); - } catch (final LocaleNotLoadedException e) { - VConsole.error(e); - return 0; - } - } - - public boolean isTwelveHourClock() { - try { - return LocaleService.isTwelveHourClock(currentLocale); - } catch (final LocaleNotLoadedException e) { - VConsole.error(e); - return false; - } - } - - public String getClockDelimeter() { - try { - return LocaleService.getClockDelimiter(currentLocale); - } catch (final LocaleNotLoadedException e) { - VConsole.error(e); - return ":"; - } - } - - private static final String[] DEFAULT_AMPM_STRINGS = { "AM", "PM" }; - - public String[] getAmPmStrings() { - try { - return LocaleService.getAmPmStrings(currentLocale); - } catch (final LocaleNotLoadedException e) { - // TODO can this practically even happen? Should die instead? - VConsole.error("Locale not loaded, using fallback : AM/PM"); - VConsole.error(e); - return DEFAULT_AMPM_STRINGS; - } - } - - public int getStartWeekDay(Date date) { - final Date dateForFirstOfThisMonth = new Date(date.getYear(), - date.getMonth(), 1); - int firstDay; - try { - firstDay = LocaleService.getFirstDayOfWeek(currentLocale); - } catch (final LocaleNotLoadedException e) { - VConsole.error("Locale not loaded, using fallback 0"); - VConsole.error(e); - firstDay = 0; - } - int start = dateForFirstOfThisMonth.getDay() - firstDay; - if (start < 0) { - start = 6; - } - return start; - } - - public static void setMilliseconds(Date date, int ms) { - date.setTime(date.getTime() / 1000 * 1000 + ms); - } - - public static int getMilliseconds(Date date) { - if (date == null) { - return 0; - } - - return (int) (date.getTime() - date.getTime() / 1000 * 1000); - } - - public static int getNumberOfDaysInMonth(Date date) { - final int month = date.getMonth(); - if (month == 1 && true == isLeapYear(date)) { - return 29; - } - return maxDaysInMonth[month]; - } - - public static boolean isLeapYear(Date date) { - // Instantiate the date for 1st March of that year - final Date firstMarch = new Date(date.getYear(), 2, 1); - - // Go back 1 day - final long firstMarchTime = firstMarch.getTime(); - final long lastDayTimeFeb = firstMarchTime - (24 * 60 * 60 * 1000); // NUM_MILLISECS_A_DAY - - // Instantiate new Date with this time - final Date febLastDay = new Date(lastDayTimeFeb); - - // Check for date in this new instance - return (29 == febLastDay.getDate()) ? true : false; - } - - public static boolean isSameDay(Date d1, Date d2) { - return (getDayInt(d1) == getDayInt(d2)); - } - - public static boolean isInRange(Date date, Date rangeStart, Date rangeEnd, - int resolution) { - Date s; - Date e; - if (rangeStart.after(rangeEnd)) { - s = rangeEnd; - e = rangeStart; - } else { - e = rangeEnd; - s = rangeStart; - } - long start = s.getYear() * 10000000000l; - long end = e.getYear() * 10000000000l; - long target = date.getYear() * 10000000000l; - - if (resolution == VDateField.RESOLUTION_YEAR) { - return (start <= target && end >= target); - } - start += s.getMonth() * 100000000l; - end += e.getMonth() * 100000000l; - target += date.getMonth() * 100000000l; - if (resolution == VDateField.RESOLUTION_MONTH) { - return (start <= target && end >= target); - } - start += s.getDate() * 1000000l; - end += e.getDate() * 1000000l; - target += date.getDate() * 1000000l; - if (resolution == VDateField.RESOLUTION_DAY) { - return (start <= target && end >= target); - } - start += s.getHours() * 10000l; - end += e.getHours() * 10000l; - target += date.getHours() * 10000l; - if (resolution == VDateField.RESOLUTION_HOUR) { - return (start <= target && end >= target); - } - start += s.getMinutes() * 100l; - end += e.getMinutes() * 100l; - target += date.getMinutes() * 100l; - if (resolution == VDateField.RESOLUTION_MIN) { - return (start <= target && end >= target); - } - start += s.getSeconds(); - end += e.getSeconds(); - target += date.getSeconds(); - return (start <= target && end >= target); - - } - - private static int getDayInt(Date date) { - final int y = date.getYear(); - final int m = date.getMonth(); - final int d = date.getDate(); - - return ((y + 1900) * 10000 + m * 100 + d) * 1000000000; - } - - /** - * Returns the ISO-8601 week number of the given date. - * - * @param date - * The date for which the week number should be resolved - * @return The ISO-8601 week number for {@literal date} - */ - public static int getISOWeekNumber(Date date) { - final long MILLISECONDS_PER_DAY = 24 * 3600 * 1000; - int dayOfWeek = date.getDay(); // 0 == sunday - - // ISO 8601 use weeks that start on monday so we use - // mon=1,tue=2,...sun=7; - if (dayOfWeek == 0) { - dayOfWeek = 7; - } - // Find nearest thursday (defines the week in ISO 8601). The week number - // for the nearest thursday is the same as for the target date. - int nearestThursdayDiff = 4 - dayOfWeek; // 4 is thursday - Date nearestThursday = new Date(date.getTime() + nearestThursdayDiff - * MILLISECONDS_PER_DAY); - - Date firstOfJanuary = new Date(nearestThursday.getYear(), 0, 1); - long timeDiff = nearestThursday.getTime() - firstOfJanuary.getTime(); - int daysSinceFirstOfJanuary = (int) (timeDiff / MILLISECONDS_PER_DAY); - - int weekNumber = (daysSinceFirstOfJanuary) / 7 + 1; - - return weekNumber; - } - - /** - * Check if format contains the month name. If it does we manually convert - * it to the month name since DateTimeFormat.format always uses the current - * locale and will replace the month name wrong if current locale is - * different from the locale set for the DateField. - * - * MMMM is converted into long month name, MMM is converted into short month - * name. '' are added around the name to avoid that DateTimeFormat parses - * the month name as a pattern. - * - * @param date - * The date to convert - * @param formatStr - * The format string that might contain MMM or MMMM - * @param dateTimeService - * Reference to the Vaadin DateTimeService - * @return - */ - public String formatDate(Date date, String formatStr) { - /* - * Format month names separately when locale for the DateTimeService is - * not the same as the browser locale - */ - formatStr = formatMonthNames(date, formatStr); - - // Format uses the browser locale - DateTimeFormat format = DateTimeFormat.getFormat(formatStr); - - String result = format.format(date); - - return result; - } - - private String formatMonthNames(Date date, String formatStr) { - if (formatStr.contains("MMMM")) { - String monthName = getMonth(date.getMonth()); - - if (monthName != null) { - /* - * Replace 4 or more M:s with the quoted month name. Also - * concatenate generated string with any other string prepending - * or following the MMMM pattern, i.e. 'MMMM'ta ' becomes - * 'MONTHta ' and not 'MONTH''ta ', 'ab'MMMM becomes 'abMONTH', - * 'x'MMMM'y' becomes 'xMONTHy'. - */ - formatStr = formatStr.replaceAll("'([M]{4,})'", monthName); - formatStr = formatStr.replaceAll("([M]{4,})'", "'" + monthName); - formatStr = formatStr.replaceAll("'([M]{4,})", monthName + "'"); - formatStr = formatStr.replaceAll("[M]{4,}", "'" + monthName - + "'"); - } - } - - if (formatStr.contains("MMM")) { - - String monthName = getShortMonth(date.getMonth()); - - if (monthName != null) { - /* - * Replace 3 or more M:s with the quoted month name. Also - * concatenate generated string with any other string prepending - * or following the MMM pattern, i.e. 'MMM'ta ' becomes 'MONTHta - * ' and not 'MONTH''ta ', 'ab'MMM becomes 'abMONTH', 'x'MMM'y' - * becomes 'xMONTHy'. - */ - formatStr = formatStr.replaceAll("'([M]{3,})'", monthName); - formatStr = formatStr.replaceAll("([M]{3,})'", "'" + monthName); - formatStr = formatStr.replaceAll("'([M]{3,})", monthName + "'"); - formatStr = formatStr.replaceAll("[M]{3,}", "'" + monthName - + "'"); - } - } - - return formatStr; - } - - /** - * Replaces month names in the entered date with the name in the current - * browser locale. - * - * @param enteredDate - * Date string e.g. "5 May 2010" - * @param formatString - * Format string e.g. "d M yyyy" - * @return The date string where the month names have been replaced by the - * browser locale version - */ - private String parseMonthName(String enteredDate, String formatString) { - LocaleInfo browserLocale = LocaleInfo.getCurrentLocale(); - if (browserLocale.getLocaleName().equals(getLocale())) { - // No conversion needs to be done when locales match - return enteredDate; - } - String[] browserMonthNames = browserLocale.getDateTimeConstants() - .months(); - String[] browserShortMonthNames = browserLocale.getDateTimeConstants() - .shortMonths(); - - if (formatString.contains("MMMM")) { - // Full month name - for (int i = 0; i < 12; i++) { - enteredDate = enteredDate.replaceAll(getMonth(i), - browserMonthNames[i]); - } - } - if (formatString.contains("MMM")) { - // Short month name - for (int i = 0; i < 12; i++) { - enteredDate = enteredDate.replaceAll(getShortMonth(i), - browserShortMonthNames[i]); - } - } - - return enteredDate; - } - - /** - * Parses the given date string using the given format string and the locale - * set in this DateTimeService instance. - * - * @param dateString - * Date string e.g. "1 February 2010" - * @param formatString - * Format string e.g. "d MMMM yyyy" - * @param lenient - * true to use lenient parsing, false to use strict parsing - * @return A Date object representing the dateString. Never returns null. - * @throws IllegalArgumentException - * if the parsing fails - * - */ - public Date parseDate(String dateString, String formatString, - boolean lenient) throws IllegalArgumentException { - /* DateTimeFormat uses the browser's locale */ - DateTimeFormat format = DateTimeFormat.getFormat(formatString); - - /* - * Parse month names separately when locale for the DateTimeService is - * not the same as the browser locale - */ - dateString = parseMonthName(dateString, formatString); - - Date date; - - if (lenient) { - date = format.parse(dateString); - } else { - date = format.parseStrict(dateString); - } - - // Some version of Firefox sets the timestamp to 0 if parsing fails. - if (date != null && date.getTime() == 0) { - throw new IllegalArgumentException("Parsing of '" + dateString - + "' failed"); - } - - return date; - - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/DirectionalManagedLayout.java b/client/src/com/vaadin/terminal/gwt/client/DirectionalManagedLayout.java deleted file mode 100644 index 323fc5bdf2..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/DirectionalManagedLayout.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import com.vaadin.terminal.gwt.client.ui.ManagedLayout; - -public interface DirectionalManagedLayout extends ManagedLayout { - public void layoutVertically(); - - public void layoutHorizontally(); -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/EventHelper.java b/client/src/com/vaadin/terminal/gwt/client/EventHelper.java deleted file mode 100644 index 8d09094c1f..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/EventHelper.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import static com.vaadin.shared.EventId.BLUR; -import static com.vaadin.shared.EventId.FOCUS; - -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.DomEvent.Type; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.shared.EventHandler; -import com.google.gwt.event.shared.HandlerRegistration; - -/** - * Helper class for attaching/detaching handlers for Vaadin client side - * components, based on identifiers in UIDL. Helpers expect Paintables to be - * both listeners and sources for events. This helper cannot be used for more - * complex widgets. - * <p> - * Possible current registration is given as parameter. The returned - * registration (possibly the same as given, should be store for next update. - * <p> - * Pseudocode what helpers do: - * - * <pre> - * - * if paintable has event listener in UIDL - * if registration is null - * register paintable as as handler for event - * return the registration - * else - * if registration is not null - * remove the handler from paintable - * return null - * - * - * </pre> - * - */ -public class EventHelper { - - /** - * Adds or removes a focus handler depending on if the connector has focus - * listeners on the server side or not. - * - * @param connector - * The connector to update. Must implement focusHandler. - * @param handlerRegistration - * The old registration reference or null no handler has been - * registered previously - * @return a new registration handler that can be used to unregister the - * handler later - */ - public static <T extends ComponentConnector & FocusHandler> HandlerRegistration updateFocusHandler( - T connector, HandlerRegistration handlerRegistration) { - return updateHandler(connector, FOCUS, handlerRegistration, - FocusEvent.getType()); - } - - /** - * Adds or removes a blur handler depending on if the connector has blur - * listeners on the server side or not. - * - * @param connector - * The connector to update. Must implement BlurHandler. - * @param handlerRegistration - * The old registration reference or null no handler has been - * registered previously - * @return a new registration handler that can be used to unregister the - * handler later - */ - public static <T extends ComponentConnector & BlurHandler> HandlerRegistration updateBlurHandler( - T connector, HandlerRegistration handlerRegistration) { - return updateHandler(connector, BLUR, handlerRegistration, - BlurEvent.getType()); - } - - private static <H extends EventHandler> HandlerRegistration updateHandler( - ComponentConnector connector, String eventIdentifier, - HandlerRegistration handlerRegistration, Type<H> type) { - if (connector.hasEventListener(eventIdentifier)) { - if (handlerRegistration == null) { - handlerRegistration = connector.getWidget().addDomHandler( - (H) connector, type); - } - } else if (handlerRegistration != null) { - handlerRegistration.removeHandler(); - handlerRegistration = null; - } - return handlerRegistration; - - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/FastStringSet.java b/client/src/com/vaadin/terminal/gwt/client/FastStringSet.java deleted file mode 100644 index d88f56ed61..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/FastStringSet.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.JsArrayString; - -public final class FastStringSet extends JavaScriptObject { - protected FastStringSet() { - // JSO constructor - } - - public native boolean contains(String string) - /*-{ - return this.hasOwnProperty(string); - }-*/; - - public native void add(String string) - /*-{ - this[string] = true; - }-*/; - - public native void addAll(JsArrayString array) - /*-{ - for(var i = 0; i < array.length; i++) { - this[array[i]] = true; - } - }-*/; - - public native JsArrayString dump() - /*-{ - var array = []; - for(var string in this) { - if (this.hasOwnProperty(string)) { - array.push(string); - } - } - return array; - }-*/; - - public native void remove(String string) - /*-{ - delete this[string]; - }-*/; - - public native boolean isEmpty() - /*-{ - for(var string in this) { - if (this.hasOwnProperty(string)) { - return false; - } - } - return true; - }-*/; - - public static FastStringSet create() { - return JavaScriptObject.createObject().cast(); - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/Focusable.java b/client/src/com/vaadin/terminal/gwt/client/Focusable.java deleted file mode 100644 index fe468a0548..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/Focusable.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -/** - * GWT's HasFocus is way too overkill for just receiving focus in simple - * components. Vaadin uses this interface in addition to GWT's HasFocus to pass - * focus requests from server to actual ui widgets in browsers. - * - * So in to make your server side focusable component receive focus on client - * side it must either implement this or HasFocus interface. - */ -public interface Focusable { - /** - * Sets focus to this widget. - */ - public void focus(); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java b/client/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java deleted file mode 100644 index 6494ae3480..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.JsArray; -import com.google.gwt.json.client.JSONArray; -import com.google.gwt.user.client.Element; -import com.vaadin.shared.JavaScriptConnectorState; -import com.vaadin.shared.communication.MethodInvocation; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler; - -public class JavaScriptConnectorHelper { - - private final ServerConnector connector; - private final JavaScriptObject nativeState = JavaScriptObject - .createObject(); - private final JavaScriptObject rpcMap = JavaScriptObject.createObject(); - - private final Map<String, JavaScriptObject> rpcObjects = new HashMap<String, JavaScriptObject>(); - private final Map<String, Set<String>> rpcMethods = new HashMap<String, Set<String>>(); - - private JavaScriptObject connectorWrapper; - private int tag; - - private boolean inited = false; - - public JavaScriptConnectorHelper(ServerConnector connector) { - this.connector = connector; - - // Wildcard rpc object - rpcObjects.put("", JavaScriptObject.createObject()); - } - - public void init() { - connector.addStateChangeHandler(new StateChangeHandler() { - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - JavaScriptObject wrapper = getConnectorWrapper(); - JavaScriptConnectorState state = getConnectorState(); - - for (String callback : state.getCallbackNames()) { - ensureCallback(JavaScriptConnectorHelper.this, wrapper, - callback); - } - - for (Entry<String, Set<String>> entry : state - .getRpcInterfaces().entrySet()) { - String rpcName = entry.getKey(); - String jsName = getJsInterfaceName(rpcName); - if (!rpcObjects.containsKey(jsName)) { - Set<String> methods = entry.getValue(); - rpcObjects.put(jsName, - createRpcObject(rpcName, methods)); - - // Init all methods for wildcard rpc - for (String method : methods) { - JavaScriptObject wildcardRpcObject = rpcObjects - .get(""); - Set<String> interfaces = rpcMethods.get(method); - if (interfaces == null) { - interfaces = new HashSet<String>(); - rpcMethods.put(method, interfaces); - attachRpcMethod(wildcardRpcObject, null, method); - } - interfaces.add(rpcName); - } - } - } - - // Init after setting up callbacks & rpc - if (!inited) { - initJavaScript(); - inited = true; - } - - fireNativeStateChange(wrapper); - } - }); - } - - private static String getJsInterfaceName(String rpcName) { - return rpcName.replace('$', '.'); - } - - protected JavaScriptObject createRpcObject(String iface, Set<String> methods) { - JavaScriptObject object = JavaScriptObject.createObject(); - - for (String method : methods) { - attachRpcMethod(object, iface, method); - } - - return object; - } - - private boolean initJavaScript() { - ApplicationConfiguration conf = connector.getConnection() - .getConfiguration(); - ArrayList<String> attemptedNames = new ArrayList<String>(); - Integer tag = Integer.valueOf(this.tag); - while (tag != null) { - String serverSideClassName = conf.getServerSideClassNameForTag(tag); - String initFunctionName = serverSideClassName - .replaceAll("\\.", "_"); - if (tryInitJs(initFunctionName, getConnectorWrapper())) { - VConsole.log("JavaScript connector initialized using " - + initFunctionName); - return true; - } else { - VConsole.log("No JavaScript function " + initFunctionName - + " found"); - attemptedNames.add(initFunctionName); - tag = conf.getParentTag(tag.intValue()); - } - } - VConsole.log("No JavaScript init for connector not found"); - showInitProblem(attemptedNames); - return false; - } - - protected void showInitProblem(ArrayList<String> attemptedNames) { - // Default does nothing - } - - private static native boolean tryInitJs(String initFunctionName, - JavaScriptObject connectorWrapper) - /*-{ - if (typeof $wnd[initFunctionName] == 'function') { - $wnd[initFunctionName].apply(connectorWrapper); - return true; - } else { - return false; - } - }-*/; - - private JavaScriptObject getConnectorWrapper() { - if (connectorWrapper == null) { - connectorWrapper = createConnectorWrapper(this, - connector.getConnection(), nativeState, rpcMap, - connector.getConnectorId(), rpcObjects); - } - - return connectorWrapper; - } - - private static native void fireNativeStateChange( - JavaScriptObject connectorWrapper) - /*-{ - if (typeof connectorWrapper.onStateChange == 'function') { - connectorWrapper.onStateChange(); - } - }-*/; - - private static native JavaScriptObject createConnectorWrapper( - JavaScriptConnectorHelper h, ApplicationConnection c, - JavaScriptObject nativeState, JavaScriptObject registeredRpc, - String connectorId, Map<String, JavaScriptObject> rpcObjects) - /*-{ - return { - 'getConnectorId': function() { - return connectorId; - }, - 'getParentId': $entry(function(connectorId) { - return h.@com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper::getParentId(Ljava/lang/String;)(connectorId); - }), - 'getState': function() { - return nativeState; - }, - 'getRpcProxy': $entry(function(iface) { - if (!iface) { - iface = ''; - } - return rpcObjects.@java.util.Map::get(Ljava/lang/Object;)(iface); - }), - 'getElement': $entry(function(connectorId) { - return h.@com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper::getWidgetElement(Ljava/lang/String;)(connectorId); - }), - 'registerRpc': function(iface, rpcHandler) { - //registerRpc(handler) -> registerRpc('', handler); - if (!rpcHandler) { - rpcHandler = iface; - iface = ''; - } - if (!registeredRpc[iface]) { - registeredRpc[iface] = []; - } - registeredRpc[iface].push(rpcHandler); - }, - 'translateVaadinUri': $entry(function(uri) { - return c.@com.vaadin.terminal.gwt.client.ApplicationConnection::translateVaadinUri(Ljava/lang/String;)(uri); - }), - }; - }-*/; - - private native void attachRpcMethod(JavaScriptObject rpc, String iface, - String method) - /*-{ - var self = this; - rpc[method] = $entry(function() { - self.@com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper::fireRpc(Ljava/lang/String;Ljava/lang/String;Lcom/google/gwt/core/client/JsArray;)(iface, method, arguments); - }); - }-*/; - - private String getParentId(String connectorId) { - ServerConnector target = getConnector(connectorId); - if (target == null) { - return null; - } - ServerConnector parent = target.getParent(); - if (parent == null) { - return null; - } else { - return parent.getConnectorId(); - } - } - - private Element getWidgetElement(String connectorId) { - ServerConnector target = getConnector(connectorId); - if (target instanceof ComponentConnector) { - return ((ComponentConnector) target).getWidget().getElement(); - } else { - return null; - } - } - - private ServerConnector getConnector(String connectorId) { - if (connectorId == null || connectorId.length() == 0) { - return connector; - } - - return ConnectorMap.get(connector.getConnection()).getConnector( - connectorId); - } - - private void fireRpc(String iface, String method, - JsArray<JavaScriptObject> arguments) { - if (iface == null) { - iface = findWildcardInterface(method); - } - - JSONArray argumentsArray = new JSONArray(arguments); - Object[] parameters = new Object[arguments.length()]; - for (int i = 0; i < parameters.length; i++) { - parameters[i] = argumentsArray.get(i); - } - connector.getConnection().addMethodInvocationToQueue( - new MethodInvocation(connector.getConnectorId(), iface, method, - parameters), false, false); - } - - private String findWildcardInterface(String method) { - Set<String> interfaces = rpcMethods.get(method); - if (interfaces.size() == 1) { - return interfaces.iterator().next(); - } else { - // TODO Resolve conflicts using argument count and types - String interfaceList = ""; - for (String iface : interfaces) { - if (interfaceList.length() != 0) { - interfaceList += ", "; - } - interfaceList += getJsInterfaceName(iface); - } - - throw new IllegalStateException( - "Can not call method " - + method - + " for wildcard rpc proxy because the function is defined for multiple rpc interfaces: " - + interfaceList - + ". Retrieve a rpc proxy for a specific interface using getRpcProxy(interfaceName) to use the function."); - } - } - - private void fireCallback(String name, JsArray<JavaScriptObject> arguments) { - MethodInvocation invocation = new MethodInvocation( - connector.getConnectorId(), - "com.vaadin.ui.JavaScript$JavaScriptCallbackRpc", "call", - new Object[] { name, new JSONArray(arguments) }); - connector.getConnection().addMethodInvocationToQueue(invocation, false, - false); - } - - public void setNativeState(JavaScriptObject state) { - updateNativeState(nativeState, state); - } - - private static native void updateNativeState(JavaScriptObject state, - JavaScriptObject input) - /*-{ - // Copy all fields to existing state object - for(var key in state) { - if (state.hasOwnProperty(key)) { - delete state[key]; - } - } - - for(var key in input) { - if (input.hasOwnProperty(key)) { - state[key] = input[key]; - } - } - }-*/; - - public Object[] decodeRpcParameters(JSONArray parametersJson) { - return new Object[] { parametersJson.getJavaScriptObject() }; - } - - public void setTag(int tag) { - this.tag = tag; - } - - public void invokeJsRpc(MethodInvocation invocation, - JSONArray parametersJson) { - String iface = invocation.getInterfaceName(); - String method = invocation.getMethodName(); - if ("com.vaadin.ui.JavaScript$JavaScriptCallbackRpc".equals(iface) - && "call".equals(method)) { - String callbackName = parametersJson.get(0).isString() - .stringValue(); - JavaScriptObject arguments = parametersJson.get(1).isArray() - .getJavaScriptObject(); - invokeCallback(getConnectorWrapper(), callbackName, arguments); - } else { - JavaScriptObject arguments = parametersJson.getJavaScriptObject(); - invokeJsRpc(rpcMap, iface, method, arguments); - // Also invoke wildcard interface - invokeJsRpc(rpcMap, "", method, arguments); - } - } - - private static native void invokeCallback(JavaScriptObject connector, - String name, JavaScriptObject arguments) - /*-{ - connector[name].apply(connector, arguments); - }-*/; - - private static native void invokeJsRpc(JavaScriptObject rpcMap, - String interfaceName, String methodName, JavaScriptObject parameters) - /*-{ - var targets = rpcMap[interfaceName]; - if (!targets) { - return; - } - for(var i = 0; i < targets.length; i++) { - var target = targets[i]; - target[methodName].apply(target, parameters); - } - }-*/; - - private static native void ensureCallback(JavaScriptConnectorHelper h, - JavaScriptObject connector, String name) - /*-{ - connector[name] = $entry(function() { - var args = Array.prototype.slice.call(arguments, 0); - h.@com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper::fireCallback(Ljava/lang/String;Lcom/google/gwt/core/client/JsArray;)(name, args); - }); - }-*/; - - private JavaScriptConnectorState getConnectorState() { - return (JavaScriptConnectorState) connector.getState(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java b/client/src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java deleted file mode 100644 index e94e0a739b..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import com.vaadin.shared.JavaScriptExtensionState; -import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.AbstractJavaScriptExtension; -import com.vaadin.terminal.gwt.client.communication.HasJavaScriptConnectorHelper; -import com.vaadin.terminal.gwt.client.extensions.AbstractExtensionConnector; - -@Connect(AbstractJavaScriptExtension.class) -public final class JavaScriptExtension extends AbstractExtensionConnector - implements HasJavaScriptConnectorHelper { - private final JavaScriptConnectorHelper helper = new JavaScriptConnectorHelper( - this); - - @Override - protected void init() { - super.init(); - helper.init(); - } - - @Override - public JavaScriptConnectorHelper getJavascriptConnectorHelper() { - return helper; - } - - @Override - public JavaScriptExtensionState getState() { - return (JavaScriptExtensionState) super.getState(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/LayoutManager.java b/client/src/com/vaadin/terminal/gwt/client/LayoutManager.java deleted file mode 100644 index c00f9bd865..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/LayoutManager.java +++ /dev/null @@ -1,1227 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import com.google.gwt.core.client.Duration; -import com.google.gwt.core.client.JsArrayString; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Overflow; -import com.google.gwt.user.client.Timer; -import com.vaadin.terminal.gwt.client.MeasuredSize.MeasureResult; -import com.vaadin.terminal.gwt.client.ui.ManagedLayout; -import com.vaadin.terminal.gwt.client.ui.PostLayoutListener; -import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout; -import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeEvent; -import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeListener; -import com.vaadin.terminal.gwt.client.ui.layout.LayoutDependencyTree; -import com.vaadin.terminal.gwt.client.ui.notification.VNotification; - -public class LayoutManager { - private static final String LOOP_ABORT_MESSAGE = "Aborting layout after 100 passes. This would probably be an infinite loop."; - - private static final boolean debugLogging = false; - - private ApplicationConnection connection; - private final Set<Element> measuredNonConnectorElements = new HashSet<Element>(); - private final MeasuredSize nullSize = new MeasuredSize(); - - private LayoutDependencyTree currentDependencyTree; - - private final Collection<ManagedLayout> needsHorizontalLayout = new HashSet<ManagedLayout>(); - private final Collection<ManagedLayout> needsVerticalLayout = new HashSet<ManagedLayout>(); - - private final Collection<ComponentConnector> needsMeasure = new HashSet<ComponentConnector>(); - - private Collection<ComponentConnector> pendingOverflowFixes = new HashSet<ComponentConnector>(); - - private final Map<Element, Collection<ElementResizeListener>> elementResizeListeners = new HashMap<Element, Collection<ElementResizeListener>>(); - private final Set<Element> listenersToFire = new HashSet<Element>(); - - private boolean layoutPending = false; - private Timer layoutTimer = new Timer() { - @Override - public void run() { - cancel(); - layoutNow(); - } - }; - private boolean everythingNeedsMeasure = false; - - public void setConnection(ApplicationConnection connection) { - if (this.connection != null) { - throw new RuntimeException( - "LayoutManager connection can never be changed"); - } - this.connection = connection; - } - - /** - * Gets the layout manager associated with the given - * {@link ApplicationConnection}. - * - * @param connection - * the application connection to get a layout manager for - * @return the layout manager associated with the provided application - * connection - */ - public static LayoutManager get(ApplicationConnection connection) { - return connection.getLayoutManager(); - } - - /** - * Registers that a ManagedLayout is depending on the size of an Element. - * This causes this layout manager to measure the element in the beginning - * of every layout phase and call the appropriate layout method of the - * managed layout if the size of the element has changed. - * - * @param owner - * the ManagedLayout that depends on an element - * @param element - * the Element that should be measured - */ - public void registerDependency(ManagedLayout owner, Element element) { - MeasuredSize measuredSize = ensureMeasured(element); - setNeedsLayout(owner); - measuredSize.addDependent(owner.getConnectorId()); - } - - private MeasuredSize ensureMeasured(Element element) { - MeasuredSize measuredSize = getMeasuredSize(element, null); - if (measuredSize == null) { - measuredSize = new MeasuredSize(); - - if (ConnectorMap.get(connection).getConnector(element) == null) { - measuredNonConnectorElements.add(element); - } - setMeasuredSize(element, measuredSize); - } - return measuredSize; - } - - private boolean needsMeasure(Element e) { - if (connection.getConnectorMap().getConnectorId(e) != null) { - return true; - } else if (elementResizeListeners.containsKey(e)) { - return true; - } else if (getMeasuredSize(e, nullSize).hasDependents()) { - return true; - } else { - return false; - } - } - - /** - * Assigns a measured size to an element. Method defined as protected to - * allow separate implementation for IE8. - * - * @param element - * the dom element to attach the measured size to - * @param measuredSize - * the measured size to attach to the element. If - * <code>null</code>, any previous measured size is removed. - */ - protected native void setMeasuredSize(Element element, - MeasuredSize measuredSize) - /*-{ - if (measuredSize) { - element.vMeasuredSize = measuredSize; - } else { - delete element.vMeasuredSize; - } - }-*/; - - /** - * Gets the measured size for an element. Method defined as protected to - * allow separate implementation for IE8. - * - * @param element - * The element to get measured size for - * @param defaultSize - * The size to return if no measured size could be found - * @return The measured size for the element or {@literal defaultSize} - */ - protected native MeasuredSize getMeasuredSize(Element element, - MeasuredSize defaultSize) - /*-{ - return element.vMeasuredSize || defaultSize; - }-*/; - - private final MeasuredSize getMeasuredSize(ComponentConnector connector) { - Element element = connector.getWidget().getElement(); - MeasuredSize measuredSize = getMeasuredSize(element, null); - if (measuredSize == null) { - measuredSize = new MeasuredSize(); - setMeasuredSize(element, measuredSize); - } - return measuredSize; - } - - /** - * Registers that a ManagedLayout is no longer depending on the size of an - * Element. - * - * @see #registerDependency(ManagedLayout, Element) - * - * @param owner - * the ManagedLayout no longer depends on an element - * @param element - * the Element that that no longer needs to be measured - */ - public void unregisterDependency(ManagedLayout owner, Element element) { - MeasuredSize measuredSize = getMeasuredSize(element, null); - if (measuredSize == null) { - return; - } - measuredSize.removeDependent(owner.getConnectorId()); - stopMeasuringIfUnecessary(element); - } - - public boolean isLayoutRunning() { - return currentDependencyTree != null; - } - - private void countLayout(Map<ManagedLayout, Integer> layoutCounts, - ManagedLayout layout) { - Integer count = layoutCounts.get(layout); - if (count == null) { - count = Integer.valueOf(0); - } else { - count = Integer.valueOf(count.intValue() + 1); - } - layoutCounts.put(layout, count); - if (count.intValue() > 2) { - VConsole.error(Util.getConnectorString(layout) - + " has been layouted " + count.intValue() + " times"); - } - } - - private void layoutLater() { - if (!layoutPending) { - layoutPending = true; - layoutTimer.schedule(100); - } - } - - public void layoutNow() { - if (isLayoutRunning()) { - throw new IllegalStateException( - "Can't start a new layout phase before the previous layout phase ends."); - } - layoutPending = false; - try { - currentDependencyTree = new LayoutDependencyTree(); - doLayout(); - } finally { - currentDependencyTree = null; - } - } - - private void doLayout() { - VConsole.log("Starting layout phase"); - - Map<ManagedLayout, Integer> layoutCounts = new HashMap<ManagedLayout, Integer>(); - - int passes = 0; - Duration totalDuration = new Duration(); - - for (ManagedLayout layout : needsHorizontalLayout) { - currentDependencyTree.setNeedsHorizontalLayout(layout, true); - } - for (ManagedLayout layout : needsVerticalLayout) { - currentDependencyTree.setNeedsVerticalLayout(layout, true); - } - needsHorizontalLayout.clear(); - needsVerticalLayout.clear(); - - for (ComponentConnector connector : needsMeasure) { - currentDependencyTree.setNeedsMeasure(connector, true); - } - needsMeasure.clear(); - - measureNonConnectors(); - - VConsole.log("Layout init in " + totalDuration.elapsedMillis() + " ms"); - - while (true) { - Duration passDuration = new Duration(); - passes++; - - int measuredConnectorCount = measureConnectors( - currentDependencyTree, everythingNeedsMeasure); - everythingNeedsMeasure = false; - if (measuredConnectorCount == 0) { - VConsole.log("No more changes in pass " + passes); - break; - } - - int measureTime = passDuration.elapsedMillis(); - VConsole.log(" Measured " + measuredConnectorCount - + " elements in " + measureTime + " ms"); - - if (!listenersToFire.isEmpty()) { - for (Element element : listenersToFire) { - Collection<ElementResizeListener> listeners = elementResizeListeners - .get(element); - ElementResizeListener[] array = listeners - .toArray(new ElementResizeListener[listeners.size()]); - ElementResizeEvent event = new ElementResizeEvent(this, - element); - for (ElementResizeListener listener : array) { - try { - listener.onElementResize(event); - } catch (RuntimeException e) { - VConsole.error(e); - } - } - } - int measureListenerTime = passDuration.elapsedMillis(); - VConsole.log(" Fired resize listeners for " - + listenersToFire.size() + " elements in " - + (measureListenerTime - measureTime) + " ms"); - measureTime = measuredConnectorCount; - listenersToFire.clear(); - } - - FastStringSet updatedSet = FastStringSet.create(); - - while (currentDependencyTree.hasHorizontalConnectorToLayout() - || currentDependencyTree.hasVerticaConnectorToLayout()) { - for (ManagedLayout layout : currentDependencyTree - .getHorizontalLayoutTargets()) { - if (layout instanceof DirectionalManagedLayout) { - currentDependencyTree - .markAsHorizontallyLayouted(layout); - DirectionalManagedLayout cl = (DirectionalManagedLayout) layout; - try { - cl.layoutHorizontally(); - } catch (RuntimeException e) { - VConsole.error(e); - } - countLayout(layoutCounts, cl); - } else { - currentDependencyTree - .markAsHorizontallyLayouted(layout); - currentDependencyTree.markAsVerticallyLayouted(layout); - SimpleManagedLayout rr = (SimpleManagedLayout) layout; - try { - rr.layout(); - } catch (RuntimeException e) { - VConsole.error(e); - } - countLayout(layoutCounts, rr); - } - if (debugLogging) { - updatedSet.add(layout.getConnectorId()); - } - } - - for (ManagedLayout layout : currentDependencyTree - .getVerticalLayoutTargets()) { - if (layout instanceof DirectionalManagedLayout) { - currentDependencyTree.markAsVerticallyLayouted(layout); - DirectionalManagedLayout cl = (DirectionalManagedLayout) layout; - try { - cl.layoutVertically(); - } catch (RuntimeException e) { - VConsole.error(e); - } - countLayout(layoutCounts, cl); - } else { - currentDependencyTree - .markAsHorizontallyLayouted(layout); - currentDependencyTree.markAsVerticallyLayouted(layout); - SimpleManagedLayout rr = (SimpleManagedLayout) layout; - try { - rr.layout(); - } catch (RuntimeException e) { - VConsole.error(e); - } - countLayout(layoutCounts, rr); - } - if (debugLogging) { - updatedSet.add(layout.getConnectorId()); - } - } - } - - if (debugLogging) { - JsArrayString changedCids = updatedSet.dump(); - - StringBuilder b = new StringBuilder(" "); - b.append(changedCids.length()); - b.append(" requestLayout invocations in "); - b.append(passDuration.elapsedMillis() - measureTime); - b.append(" ms"); - if (changedCids.length() < 30) { - for (int i = 0; i < changedCids.length(); i++) { - if (i != 0) { - b.append(", "); - } else { - b.append(": "); - } - String connectorString = changedCids.get(i); - if (changedCids.length() < 10) { - ServerConnector connector = ConnectorMap.get( - connection).getConnector(connectorString); - connectorString = Util - .getConnectorString(connector); - } - b.append(connectorString); - } - } - VConsole.log(b.toString()); - } - - VConsole.log("Pass " + passes + " completed in " - + passDuration.elapsedMillis() + " ms"); - - if (passes > 100) { - VConsole.log(LOOP_ABORT_MESSAGE); - VNotification.createNotification(VNotification.DELAY_FOREVER) - .show(LOOP_ABORT_MESSAGE, VNotification.CENTERED, - "error"); - break; - } - } - - int postLayoutStart = totalDuration.elapsedMillis(); - for (ComponentConnector connector : connection.getConnectorMap() - .getComponentConnectors()) { - if (connector instanceof PostLayoutListener) { - ((PostLayoutListener) connector).postLayout(); - } - } - int postLayoutDone = (totalDuration.elapsedMillis() - postLayoutStart); - VConsole.log("Invoke post layout listeners in " + postLayoutDone - + " ms"); - - cleanMeasuredSizes(); - int cleaningDone = (totalDuration.elapsedMillis() - postLayoutDone); - VConsole.log("Cleaned old measured sizes in " + cleaningDone + "ms"); - - VConsole.log("Total layout phase time: " - + totalDuration.elapsedMillis() + "ms"); - } - - private void logConnectorStatus(int connectorId) { - currentDependencyTree - .logDependencyStatus((ComponentConnector) ConnectorMap.get( - connection).getConnector(Integer.toString(connectorId))); - } - - private int measureConnectors(LayoutDependencyTree layoutDependencyTree, - boolean measureAll) { - if (!pendingOverflowFixes.isEmpty()) { - Duration duration = new Duration(); - - HashMap<Element, String> originalOverflows = new HashMap<Element, String>(); - - HashSet<ComponentConnector> delayedOverflowFixes = new HashSet<ComponentConnector>(); - - // First set overflow to hidden (and save previous value so it can - // be restored later) - for (ComponentConnector componentConnector : pendingOverflowFixes) { - // Delay the overflow fix if the involved connectors might still - // change - boolean connectorChangesExpected = !currentDependencyTree - .noMoreChangesExpected(componentConnector); - boolean parentChangesExcpected = componentConnector.getParent() instanceof ComponentConnector - && !currentDependencyTree - .noMoreChangesExpected((ComponentConnector) componentConnector - .getParent()); - if (connectorChangesExpected || parentChangesExcpected) { - delayedOverflowFixes.add(componentConnector); - continue; - } - - if (debugLogging) { - VConsole.log("Doing overflow fix for " - + Util.getConnectorString(componentConnector) - + " in " - + Util.getConnectorString(componentConnector - .getParent())); - } - - Element parentElement = componentConnector.getWidget() - .getElement().getParentElement(); - Style style = parentElement.getStyle(); - String originalOverflow = style.getOverflow(); - - if (originalOverflow != null - && !originalOverflows.containsKey(parentElement)) { - // Store original value for restore, but only the first time - // the value is changed - originalOverflows.put(parentElement, originalOverflow); - } - - style.setOverflow(Overflow.HIDDEN); - } - - pendingOverflowFixes.removeAll(delayedOverflowFixes); - - // Then ensure all scrolling elements are reflowed by measuring - for (ComponentConnector componentConnector : pendingOverflowFixes) { - componentConnector.getWidget().getElement().getParentElement() - .getOffsetHeight(); - } - - // Finally restore old overflow value and update bookkeeping - for (ComponentConnector componentConnector : pendingOverflowFixes) { - Element parentElement = componentConnector.getWidget() - .getElement().getParentElement(); - parentElement.getStyle().setProperty("overflow", - originalOverflows.get(parentElement)); - - layoutDependencyTree.setNeedsMeasure(componentConnector, true); - } - if (!pendingOverflowFixes.isEmpty()) { - VConsole.log("Did overflow fix for " - + pendingOverflowFixes.size() + " elements in " - + duration.elapsedMillis() + " ms"); - } - pendingOverflowFixes = delayedOverflowFixes; - } - - int measureCount = 0; - if (measureAll) { - ComponentConnector[] connectors = ConnectorMap.get(connection) - .getComponentConnectors(); - for (ComponentConnector connector : connectors) { - measureConnector(connector); - } - for (ComponentConnector connector : connectors) { - layoutDependencyTree.setNeedsMeasure(connector, false); - } - measureCount += connectors.length; - } - - while (layoutDependencyTree.hasConnectorsToMeasure()) { - Collection<ComponentConnector> measureTargets = layoutDependencyTree - .getMeasureTargets(); - for (ComponentConnector connector : measureTargets) { - measureConnector(connector); - measureCount++; - } - for (ComponentConnector connector : measureTargets) { - layoutDependencyTree.setNeedsMeasure(connector, false); - } - } - return measureCount; - } - - private void measureConnector(ComponentConnector connector) { - Element element = connector.getWidget().getElement(); - MeasuredSize measuredSize = getMeasuredSize(connector); - MeasureResult measureResult = measuredAndUpdate(element, measuredSize); - - if (measureResult.isChanged()) { - onConnectorChange(connector, measureResult.isWidthChanged(), - measureResult.isHeightChanged()); - } - } - - private void onConnectorChange(ComponentConnector connector, - boolean widthChanged, boolean heightChanged) { - setNeedsOverflowFix(connector); - if (heightChanged) { - currentDependencyTree.markHeightAsChanged(connector); - } - if (widthChanged) { - currentDependencyTree.markWidthAsChanged(connector); - } - } - - private void setNeedsOverflowFix(ComponentConnector connector) { - // IE9 doesn't need the original fix, but for some reason it needs this - if (BrowserInfo.get().requiresOverflowAutoFix() - || BrowserInfo.get().isIE9()) { - ComponentConnector scrollingBoundary = currentDependencyTree - .getScrollingBoundary(connector); - if (scrollingBoundary != null) { - pendingOverflowFixes.add(scrollingBoundary); - } - } - } - - private void measureNonConnectors() { - for (Element element : measuredNonConnectorElements) { - measuredAndUpdate(element, getMeasuredSize(element, null)); - } - VConsole.log("Measured " + measuredNonConnectorElements.size() - + " non connector elements"); - } - - private MeasureResult measuredAndUpdate(Element element, - MeasuredSize measuredSize) { - MeasureResult measureResult = measuredSize.measure(element); - if (measureResult.isChanged()) { - notifyListenersAndDepdendents(element, - measureResult.isWidthChanged(), - measureResult.isHeightChanged()); - } - return measureResult; - } - - private void notifyListenersAndDepdendents(Element element, - boolean widthChanged, boolean heightChanged) { - assert widthChanged || heightChanged; - - MeasuredSize measuredSize = getMeasuredSize(element, nullSize); - JsArrayString dependents = measuredSize.getDependents(); - for (int i = 0; i < dependents.length(); i++) { - String pid = dependents.get(i); - ManagedLayout dependent = (ManagedLayout) connection - .getConnectorMap().getConnector(pid); - if (dependent != null) { - if (heightChanged) { - currentDependencyTree.setNeedsVerticalLayout(dependent, - true); - } - if (widthChanged) { - currentDependencyTree.setNeedsHorizontalLayout(dependent, - true); - } - } - } - if (elementResizeListeners.containsKey(element)) { - listenersToFire.add(element); - } - } - - private static boolean isManagedLayout(ComponentConnector connector) { - return connector instanceof ManagedLayout; - } - - public void forceLayout() { - ConnectorMap connectorMap = connection.getConnectorMap(); - ComponentConnector[] componentConnectors = connectorMap - .getComponentConnectors(); - for (ComponentConnector connector : componentConnectors) { - if (connector instanceof ManagedLayout) { - setNeedsLayout((ManagedLayout) connector); - } - } - setEverythingNeedsMeasure(); - layoutNow(); - } - - /** - * Marks that a ManagedLayout should be layouted in the next layout phase - * even if none of the elements managed by the layout have been resized. - * - * @param layout - * the managed layout that should be layouted - */ - public final void setNeedsLayout(ManagedLayout layout) { - setNeedsHorizontalLayout(layout); - setNeedsVerticalLayout(layout); - } - - /** - * Marks that a ManagedLayout should be layouted horizontally in the next - * layout phase even if none of the elements managed by the layout have been - * resized horizontally. - * - * For SimpleManagedLayout which is always layouted in both directions, this - * has the same effect as {@link #setNeedsLayout(ManagedLayout)}. - * - * @param layout - * the managed layout that should be layouted - */ - public final void setNeedsHorizontalLayout(ManagedLayout layout) { - needsHorizontalLayout.add(layout); - } - - /** - * Marks that a ManagedLayout should be layouted vertically in the next - * layout phase even if none of the elements managed by the layout have been - * resized vertically. - * - * For SimpleManagedLayout which is always layouted in both directions, this - * has the same effect as {@link #setNeedsLayout(ManagedLayout)}. - * - * @param layout - * the managed layout that should be layouted - */ - public final void setNeedsVerticalLayout(ManagedLayout layout) { - needsVerticalLayout.add(layout); - } - - /** - * Gets the outer height (including margins, paddings and borders) of the - * given element, provided that it has been measured. These elements are - * guaranteed to be measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * -1 is returned if the element has not been measured. If 0 is returned, it - * might indicate that the element is not attached to the DOM. - * - * @param element - * the element to get the measured size for - * @return the measured outer height (including margins, paddings and - * borders) of the element in pixels. - */ - public final int getOuterHeight(Element element) { - return getMeasuredSize(element, nullSize).getOuterHeight(); - } - - /** - * Gets the outer width (including margins, paddings and borders) of the - * given element, provided that it has been measured. These elements are - * guaranteed to be measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * -1 is returned if the element has not been measured. If 0 is returned, it - * might indicate that the element is not attached to the DOM. - * - * @param element - * the element to get the measured size for - * @return the measured outer width (including margins, paddings and - * borders) of the element in pixels. - */ - public final int getOuterWidth(Element element) { - return getMeasuredSize(element, nullSize).getOuterWidth(); - } - - /** - * Gets the inner height (excluding margins, paddings and borders) of the - * given element, provided that it has been measured. These elements are - * guaranteed to be measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * -1 is returned if the element has not been measured. If 0 is returned, it - * might indicate that the element is not attached to the DOM. - * - * @param element - * the element to get the measured size for - * @return the measured inner height (excluding margins, paddings and - * borders) of the element in pixels. - */ - public final int getInnerHeight(Element element) { - return getMeasuredSize(element, nullSize).getInnerHeight(); - } - - /** - * Gets the inner width (excluding margins, paddings and borders) of the - * given element, provided that it has been measured. These elements are - * guaranteed to be measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * -1 is returned if the element has not been measured. If 0 is returned, it - * might indicate that the element is not attached to the DOM. - * - * @param element - * the element to get the measured size for - * @return the measured inner width (excluding margins, paddings and - * borders) of the element in pixels. - */ - public final int getInnerWidth(Element element) { - return getMeasuredSize(element, nullSize).getInnerWidth(); - } - - /** - * Gets the border height (top border + bottom border) of the given element, - * provided that it has been measured. These elements are guaranteed to be - * measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * A negative number is returned if the element has not been measured. If 0 - * is returned, it might indicate that the element is not attached to the - * DOM. - * - * @param element - * the element to get the measured size for - * @return the measured border height (top border + bottom border) of the - * element in pixels. - */ - public final int getBorderHeight(Element element) { - return getMeasuredSize(element, nullSize).getBorderHeight(); - } - - /** - * Gets the padding height (top padding + bottom padding) of the given - * element, provided that it has been measured. These elements are - * guaranteed to be measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * A negative number is returned if the element has not been measured. If 0 - * is returned, it might indicate that the element is not attached to the - * DOM. - * - * @param element - * the element to get the measured size for - * @return the measured padding height (top padding + bottom padding) of the - * element in pixels. - */ - public int getPaddingHeight(Element element) { - return getMeasuredSize(element, nullSize).getPaddingHeight(); - } - - /** - * Gets the border width (left border + right border) of the given element, - * provided that it has been measured. These elements are guaranteed to be - * measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * A negative number is returned if the element has not been measured. If 0 - * is returned, it might indicate that the element is not attached to the - * DOM. - * - * @param element - * the element to get the measured size for - * @return the measured border width (left border + right border) of the - * element in pixels. - */ - public int getBorderWidth(Element element) { - return getMeasuredSize(element, nullSize).getBorderWidth(); - } - - /** - * Gets the padding width (left padding + right padding) of the given - * element, provided that it has been measured. These elements are - * guaranteed to be measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * A negative number is returned if the element has not been measured. If 0 - * is returned, it might indicate that the element is not attached to the - * DOM. - * - * @param element - * the element to get the measured size for - * @return the measured padding width (left padding + right padding) of the - * element in pixels. - */ - public int getPaddingWidth(Element element) { - return getMeasuredSize(element, nullSize).getPaddingWidth(); - } - - /** - * Gets the top padding of the given element, provided that it has been - * measured. These elements are guaranteed to be measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * A negative number is returned if the element has not been measured. If 0 - * is returned, it might indicate that the element is not attached to the - * DOM. - * - * @param element - * the element to get the measured size for - * @return the measured top padding of the element in pixels. - */ - public int getPaddingTop(Element element) { - return getMeasuredSize(element, nullSize).getPaddingTop(); - } - - /** - * Gets the left padding of the given element, provided that it has been - * measured. These elements are guaranteed to be measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * A negative number is returned if the element has not been measured. If 0 - * is returned, it might indicate that the element is not attached to the - * DOM. - * - * @param element - * the element to get the measured size for - * @return the measured left padding of the element in pixels. - */ - public int getPaddingLeft(Element element) { - return getMeasuredSize(element, nullSize).getPaddingLeft(); - } - - /** - * Gets the bottom padding of the given element, provided that it has been - * measured. These elements are guaranteed to be measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * A negative number is returned if the element has not been measured. If 0 - * is returned, it might indicate that the element is not attached to the - * DOM. - * - * @param element - * the element to get the measured size for - * @return the measured bottom padding of the element in pixels. - */ - public int getPaddingBottom(Element element) { - return getMeasuredSize(element, nullSize).getPaddingBottom(); - } - - /** - * Gets the right padding of the given element, provided that it has been - * measured. These elements are guaranteed to be measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * A negative number is returned if the element has not been measured. If 0 - * is returned, it might indicate that the element is not attached to the - * DOM. - * - * @param element - * the element to get the measured size for - * @return the measured right padding of the element in pixels. - */ - public int getPaddingRight(Element element) { - return getMeasuredSize(element, nullSize).getPaddingRight(); - } - - /** - * Gets the top margin of the given element, provided that it has been - * measured. These elements are guaranteed to be measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * A negative number is returned if the element has not been measured. If 0 - * is returned, it might indicate that the element is not attached to the - * DOM. - * - * @param element - * the element to get the measured size for - * @return the measured top margin of the element in pixels. - */ - public int getMarginTop(Element element) { - return getMeasuredSize(element, nullSize).getMarginTop(); - } - - /** - * Gets the right margin of the given element, provided that it has been - * measured. These elements are guaranteed to be measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * A negative number is returned if the element has not been measured. If 0 - * is returned, it might indicate that the element is not attached to the - * DOM. - * - * @param element - * the element to get the measured size for - * @return the measured right margin of the element in pixels. - */ - public int getMarginRight(Element element) { - return getMeasuredSize(element, nullSize).getMarginRight(); - } - - /** - * Gets the bottom margin of the given element, provided that it has been - * measured. These elements are guaranteed to be measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * A negative number is returned if the element has not been measured. If 0 - * is returned, it might indicate that the element is not attached to the - * DOM. - * - * @param element - * the element to get the measured size for - * @return the measured bottom margin of the element in pixels. - */ - public int getMarginBottom(Element element) { - return getMeasuredSize(element, nullSize).getMarginBottom(); - } - - /** - * Gets the left margin of the given element, provided that it has been - * measured. These elements are guaranteed to be measured: - * <ul> - * <li>ManagedLayotus and their child Connectors - * <li>Elements for which there is at least one ElementResizeListener - * <li>Elements for which at least one ManagedLayout has registered a - * dependency - * </ul> - * - * A negative number is returned if the element has not been measured. If 0 - * is returned, it might indicate that the element is not attached to the - * DOM. - * - * @param element - * the element to get the measured size for - * @return the measured left margin of the element in pixels. - */ - public int getMarginLeft(Element element) { - return getMeasuredSize(element, nullSize).getMarginLeft(); - } - - /** - * Registers the outer height (including margins, borders and paddings) of a - * component. This can be used as an optimization by ManagedLayouts; by - * informing the LayoutManager about what size a component will have, the - * layout propagation can continue directly without first measuring the - * potentially resized elements. - * - * @param component - * the component for which the size is reported - * @param outerHeight - * the new outer height (including margins, borders and paddings) - * of the component in pixels - */ - public void reportOuterHeight(ComponentConnector component, int outerHeight) { - MeasuredSize measuredSize = getMeasuredSize(component); - if (isLayoutRunning()) { - boolean heightChanged = measuredSize.setOuterHeight(outerHeight); - - if (heightChanged) { - onConnectorChange(component, false, true); - notifyListenersAndDepdendents(component.getWidget() - .getElement(), false, true); - } - currentDependencyTree.setNeedsVerticalMeasure(component, false); - } else if (measuredSize.getOuterHeight() != outerHeight) { - setNeedsMeasure(component); - } - } - - /** - * Registers the height reserved for a relatively sized component. This can - * be used as an optimization by ManagedLayouts; by informing the - * LayoutManager about what size a component will have, the layout - * propagation can continue directly without first measuring the potentially - * resized elements. - * - * @param component - * the relatively sized component for which the size is reported - * @param assignedHeight - * the inner height of the relatively sized component's parent - * element in pixels - */ - public void reportHeightAssignedToRelative(ComponentConnector component, - int assignedHeight) { - assert component.isRelativeHeight(); - - float percentSize = parsePercent(component.getState().getHeight()); - int effectiveHeight = Math.round(assignedHeight * (percentSize / 100)); - - reportOuterHeight(component, effectiveHeight); - } - - /** - * Registers the width reserved for a relatively sized component. This can - * be used as an optimization by ManagedLayouts; by informing the - * LayoutManager about what size a component will have, the layout - * propagation can continue directly without first measuring the potentially - * resized elements. - * - * @param component - * the relatively sized component for which the size is reported - * @param assignedWidth - * the inner width of the relatively sized component's parent - * element in pixels - */ - public void reportWidthAssignedToRelative(ComponentConnector component, - int assignedWidth) { - assert component.isRelativeWidth(); - - float percentSize = parsePercent(component.getState().getWidth()); - int effectiveWidth = Math.round(assignedWidth * (percentSize / 100)); - - reportOuterWidth(component, effectiveWidth); - } - - private static float parsePercent(String size) { - return Float.parseFloat(size.substring(0, size.length() - 1)); - } - - /** - * Registers the outer width (including margins, borders and paddings) of a - * component. This can be used as an optimization by ManagedLayouts; by - * informing the LayoutManager about what size a component will have, the - * layout propagation can continue directly without first measuring the - * potentially resized elements. - * - * @param component - * the component for which the size is reported - * @param outerWidth - * the new outer width (including margins, borders and paddings) - * of the component in pixels - */ - public void reportOuterWidth(ComponentConnector component, int outerWidth) { - MeasuredSize measuredSize = getMeasuredSize(component); - if (isLayoutRunning()) { - boolean widthChanged = measuredSize.setOuterWidth(outerWidth); - - if (widthChanged) { - onConnectorChange(component, true, false); - notifyListenersAndDepdendents(component.getWidget() - .getElement(), true, false); - } - currentDependencyTree.setNeedsHorizontalMeasure(component, false); - } else if (measuredSize.getOuterWidth() != outerWidth) { - setNeedsMeasure(component); - } - } - - /** - * Adds a listener that will be notified whenever the size of a specific - * element changes. Adding a listener to an element also ensures that all - * sizes for that element will be available starting from the next layout - * phase. - * - * @param element - * the element that should be checked for size changes - * @param listener - * an ElementResizeListener that will be informed whenever the - * size of the target element has changed - */ - public void addElementResizeListener(Element element, - ElementResizeListener listener) { - Collection<ElementResizeListener> listeners = elementResizeListeners - .get(element); - if (listeners == null) { - listeners = new HashSet<ElementResizeListener>(); - elementResizeListeners.put(element, listeners); - ensureMeasured(element); - } - listeners.add(listener); - } - - /** - * Removes an element resize listener from the provided element. This might - * cause this LayoutManager to stop tracking the size of the element if no - * other sources are interested in the size. - * - * @param element - * the element to which the element resize listener was - * previously added - * @param listener - * the ElementResizeListener that should no longer get informed - * about size changes to the target element. - */ - public void removeElementResizeListener(Element element, - ElementResizeListener listener) { - Collection<ElementResizeListener> listeners = elementResizeListeners - .get(element); - if (listeners != null) { - listeners.remove(listener); - if (listeners.isEmpty()) { - elementResizeListeners.remove(element); - stopMeasuringIfUnecessary(element); - } - } - } - - private void stopMeasuringIfUnecessary(Element element) { - if (!needsMeasure(element)) { - measuredNonConnectorElements.remove(element); - setMeasuredSize(element, null); - } - } - - /** - * Informs this LayoutManager that the size of a component might have - * changed. If there is no upcoming layout phase, a new layout phase is - * scheduled. This method should be used whenever a size might have changed - * from outside of Vaadin's normal update phase, e.g. when an icon has been - * loaded or when the user resizes some part of the UI using the mouse. - * - * @param component - * the component whose size might have changed. - */ - public void setNeedsMeasure(ComponentConnector component) { - if (isLayoutRunning()) { - currentDependencyTree.setNeedsMeasure(component, true); - } else { - needsMeasure.add(component); - layoutLater(); - } - } - - public void setEverythingNeedsMeasure() { - everythingNeedsMeasure = true; - } - - /** - * Clean measured sizes which are no longer needed. Only for IE8. - */ - protected void cleanMeasuredSizes() { - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/LayoutManagerIE8.java b/client/src/com/vaadin/terminal/gwt/client/LayoutManagerIE8.java deleted file mode 100644 index 3e47865cdc..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/LayoutManagerIE8.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Element; -import com.google.gwt.user.client.ui.RootPanel; - -public class LayoutManagerIE8 extends LayoutManager { - - private Map<Element, MeasuredSize> measuredSizes = new HashMap<Element, MeasuredSize>(); - - @Override - protected void setMeasuredSize(Element element, MeasuredSize measuredSize) { - if (measuredSize != null) { - measuredSizes.put(element, measuredSize); - } else { - measuredSizes.remove(element); - } - } - - @Override - protected MeasuredSize getMeasuredSize(Element element, - MeasuredSize defaultSize) { - MeasuredSize measured = measuredSizes.get(element); - if (measured != null) { - return measured; - } else { - return defaultSize; - } - } - - @Override - protected void cleanMeasuredSizes() { - Document document = RootPanel.get().getElement().getOwnerDocument(); - - Iterator<Element> i = measuredSizes.keySet().iterator(); - while (i.hasNext()) { - Element e = i.next(); - if (e.getOwnerDocument() != document) { - i.remove(); - } - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/LocaleNotLoadedException.java b/client/src/com/vaadin/terminal/gwt/client/LocaleNotLoadedException.java deleted file mode 100644 index a2d6bdc860..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/LocaleNotLoadedException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -@SuppressWarnings("serial") -public class LocaleNotLoadedException extends Exception { - - public LocaleNotLoadedException(String locale) { - super(locale); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/LocaleService.java b/client/src/com/vaadin/terminal/gwt/client/LocaleService.java deleted file mode 100644 index 15a3230c58..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/LocaleService.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import com.google.gwt.core.client.JsArray; - -/** - * Date / time etc. localisation service for all widgets. Caches all loaded - * locales as JSONObjects. - * - * @author Vaadin Ltd. - * - */ -public class LocaleService { - - private static Map<String, ValueMap> cache = new HashMap<String, ValueMap>(); - private static String defaultLocale; - - public static void addLocale(ValueMap valueMap) { - - final String key = valueMap.getString("name"); - if (cache.containsKey(key)) { - cache.remove(key); - } - cache.put(key, valueMap); - if (cache.size() == 1) { - setDefaultLocale(key); - } - } - - public static void setDefaultLocale(String locale) { - defaultLocale = locale; - } - - public static String getDefaultLocale() { - return defaultLocale; - } - - public static Set<String> getAvailableLocales() { - return cache.keySet(); - } - - public static String[] getMonthNames(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getStringArray("mn"); - } else { - throw new LocaleNotLoadedException(locale); - } - } - - public static String[] getShortMonthNames(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getStringArray("smn"); - } else { - throw new LocaleNotLoadedException(locale); - } - } - - public static String[] getDayNames(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getStringArray("dn"); - } else { - throw new LocaleNotLoadedException(locale); - } - } - - public static String[] getShortDayNames(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getStringArray("sdn"); - } else { - throw new LocaleNotLoadedException(locale); - } - } - - public static int getFirstDayOfWeek(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getInt("fdow"); - } else { - throw new LocaleNotLoadedException(locale); - } - } - - public static String getDateFormat(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getString("df"); - } else { - throw new LocaleNotLoadedException(locale); - } - } - - public static boolean isTwelveHourClock(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getBoolean("thc"); - } else { - throw new LocaleNotLoadedException(locale); - } - } - - public static String getClockDelimiter(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getString("hmd"); - } else { - throw new LocaleNotLoadedException(locale); - } - } - - public static String[] getAmPmStrings(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - final ValueMap l = cache.get(locale); - return l.getStringArray("ampm"); - } else { - throw new LocaleNotLoadedException(locale); - } - - } - - public static void addLocales(JsArray<ValueMap> valueMapArray) { - for (int i = 0; i < valueMapArray.length(); i++) { - addLocale(valueMapArray.get(i)); - - } - - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/MeasuredSize.java b/client/src/com/vaadin/terminal/gwt/client/MeasuredSize.java deleted file mode 100644 index ff8b591461..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/MeasuredSize.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.core.client.JsArrayString; -import com.google.gwt.dom.client.Element; - -public class MeasuredSize { - public static class MeasureResult { - private final boolean widthChanged; - private final boolean heightChanged; - - private MeasureResult(boolean widthChanged, boolean heightChanged) { - this.widthChanged = widthChanged; - this.heightChanged = heightChanged; - } - - public boolean isHeightChanged() { - return heightChanged; - } - - public boolean isWidthChanged() { - return widthChanged; - } - - public boolean isChanged() { - return heightChanged || widthChanged; - } - } - - private int width = -1; - private int height = -1; - - private int[] paddings = new int[4]; - private int[] borders = new int[4]; - private int[] margins = new int[4]; - - private FastStringSet dependents = FastStringSet.create(); - - public int getOuterHeight() { - return height; - } - - public int getOuterWidth() { - return width; - } - - public void addDependent(String pid) { - dependents.add(pid); - } - - public void removeDependent(String pid) { - dependents.remove(pid); - } - - public boolean hasDependents() { - return !dependents.isEmpty(); - } - - public JsArrayString getDependents() { - return dependents.dump(); - } - - private static int sumWidths(int[] sizes) { - return sizes[1] + sizes[3]; - } - - private static int sumHeights(int[] sizes) { - return sizes[0] + sizes[2]; - } - - public int getInnerHeight() { - return height - sumHeights(margins) - sumHeights(borders) - - sumHeights(paddings); - } - - public int getInnerWidth() { - return width - sumWidths(margins) - sumWidths(borders) - - sumWidths(paddings); - } - - public boolean setOuterHeight(int height) { - if (this.height != height) { - this.height = height; - return true; - } else { - return false; - } - } - - public boolean setOuterWidth(int width) { - if (this.width != width) { - this.width = width; - return true; - } else { - return false; - } - } - - public int getBorderHeight() { - return sumHeights(borders); - } - - public int getBorderWidth() { - return sumWidths(borders); - } - - public int getPaddingHeight() { - return sumHeights(paddings); - } - - public int getPaddingWidth() { - return sumWidths(paddings); - } - - public int getMarginHeight() { - return sumHeights(margins); - } - - public int getMarginWidth() { - return sumWidths(margins); - } - - public int getMarginTop() { - return margins[0]; - } - - public int getMarginRight() { - return margins[1]; - } - - public int getMarginBottom() { - return margins[2]; - } - - public int getMarginLeft() { - return margins[3]; - } - - public int getBorderTop() { - return margins[0]; - } - - public int getBorderRight() { - return margins[1]; - } - - public int getBorderBottom() { - return margins[2]; - } - - public int getBorderLeft() { - return margins[3]; - } - - public int getPaddingTop() { - return paddings[0]; - } - - public int getPaddingRight() { - return paddings[1]; - } - - public int getPaddingBottom() { - return paddings[2]; - } - - public int getPaddingLeft() { - return paddings[3]; - } - - public MeasureResult measure(Element element) { - boolean heightChanged = false; - boolean widthChanged = false; - - ComputedStyle computedStyle = new ComputedStyle(element); - int[] paddings = computedStyle.getPadding(); - if (!heightChanged && hasHeightChanged(this.paddings, paddings)) { - heightChanged = true; - } - if (!widthChanged && hasWidthChanged(this.paddings, paddings)) { - widthChanged = true; - } - this.paddings = paddings; - - int[] margins = computedStyle.getMargin(); - if (!heightChanged && hasHeightChanged(this.margins, margins)) { - heightChanged = true; - } - if (!widthChanged && hasWidthChanged(this.margins, margins)) { - widthChanged = true; - } - this.margins = margins; - - int[] borders = computedStyle.getBorder(); - if (!heightChanged && hasHeightChanged(this.borders, borders)) { - heightChanged = true; - } - if (!widthChanged && hasWidthChanged(this.borders, borders)) { - widthChanged = true; - } - this.borders = borders; - - int requiredHeight = Util.getRequiredHeight(element); - int marginHeight = sumHeights(margins); - if (setOuterHeight(requiredHeight + marginHeight)) { - heightChanged = true; - } - - int requiredWidth = Util.getRequiredWidth(element); - int marginWidth = sumWidths(margins); - if (setOuterWidth(requiredWidth + marginWidth)) { - widthChanged = true; - } - - return new MeasureResult(widthChanged, heightChanged); - } - - private static boolean hasWidthChanged(int[] sizes1, int[] sizes2) { - return sizes1[1] != sizes2[1] || sizes1[3] != sizes2[3]; - } - - private static boolean hasHeightChanged(int[] sizes1, int[] sizes2) { - return sizes1[0] != sizes2[0] || sizes1[2] != sizes2[2]; - } - -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/MouseEventDetailsBuilder.java b/client/src/com/vaadin/terminal/gwt/client/MouseEventDetailsBuilder.java deleted file mode 100644 index 51af1a73a9..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/MouseEventDetailsBuilder.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.user.client.Event; -import com.vaadin.shared.MouseEventDetails; - -/** - * Helper class for constructing a MouseEventDetails object from a - * {@link NativeEvent}. - * - * @author Vaadin Ltd - * @since 7.0.0 - * - */ -public class MouseEventDetailsBuilder { - - /** - * Construct a {@link MouseEventDetails} object from the given event - * - * @param evt - * The event to use as a source for the details - * @return a MouseEventDetails containing information from the event - */ - public static MouseEventDetails buildMouseEventDetails(NativeEvent evt) { - return buildMouseEventDetails(evt, null); - } - - /** - * Construct a {@link MouseEventDetails} object from the given event - * - * @param evt - * The event to use as a source for the details - * @param relativeToElement - * The element whose position - * {@link MouseEventDetails#getRelativeX()} and - * {@link MouseEventDetails#getRelativeY()} are relative to. - * @return a MouseEventDetails containing information from the event - */ - public static MouseEventDetails buildMouseEventDetails(NativeEvent evt, - Element relativeToElement) { - MouseEventDetails mouseEventDetails = new MouseEventDetails(); - mouseEventDetails.setType(Event.getTypeInt(evt.getType())); - mouseEventDetails.setClientX(Util.getTouchOrMouseClientX(evt)); - mouseEventDetails.setClientY(Util.getTouchOrMouseClientY(evt)); - mouseEventDetails.setButton(evt.getButton()); - mouseEventDetails.setAltKey(evt.getAltKey()); - mouseEventDetails.setCtrlKey(evt.getCtrlKey()); - mouseEventDetails.setMetaKey(evt.getMetaKey()); - mouseEventDetails.setShiftKey(evt.getShiftKey()); - if (relativeToElement != null) { - mouseEventDetails.setRelativeX(getRelativeX( - mouseEventDetails.getClientX(), relativeToElement)); - mouseEventDetails.setRelativeY(getRelativeY( - mouseEventDetails.getClientY(), relativeToElement)); - } - return mouseEventDetails; - - } - - private static int getRelativeX(int clientX, Element target) { - return clientX - target.getAbsoluteLeft() + target.getScrollLeft() - + target.getOwnerDocument().getScrollLeft(); - } - - private static int getRelativeY(int clientY, Element target) { - return clientY - target.getAbsoluteTop() + target.getScrollTop() - + target.getOwnerDocument().getScrollTop(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/NullConsole.java b/client/src/com/vaadin/terminal/gwt/client/NullConsole.java deleted file mode 100644 index b17eaddd9f..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/NullConsole.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import java.util.Set; - -import com.google.gwt.core.client.GWT; - -/** - * Client side console implementation for non-debug mode that discards all - * messages. - * - */ -public class NullConsole implements Console { - - @Override - public void dirUIDL(ValueMap u, ApplicationConnection conn) { - } - - @Override - public void error(String msg) { - GWT.log(msg); - } - - @Override - public void log(String msg) { - GWT.log(msg); - } - - @Override - public void printObject(Object msg) { - GWT.log(msg.toString()); - } - - @Override - public void printLayoutProblems(ValueMap meta, - ApplicationConnection applicationConnection, - Set<ComponentConnector> zeroHeightComponents, - Set<ComponentConnector> zeroWidthComponents) { - } - - @Override - public void log(Throwable e) { - GWT.log(e.getMessage(), e); - } - - @Override - public void error(Throwable e) { - // Borrow exception handling from VDebugConsole - VDebugConsole.handleError(e, this); - } - - @Override - public void setQuietMode(boolean quietDebugMode) { - } - - @Override - public void init() { - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/Paintable.java b/client/src/com/vaadin/terminal/gwt/client/Paintable.java deleted file mode 100644 index 739f9d6594..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/Paintable.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -/** - * An interface used by client-side widgets or paintable parts to receive - * updates from the corresponding server-side components in the form of - * {@link UIDL}. - * - * Updates can be sent back to the server using the - * {@link ApplicationConnection#updateVariable()} methods. - */ -@Deprecated -public interface Paintable { - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/RenderInformation.java b/client/src/com/vaadin/terminal/gwt/client/RenderInformation.java deleted file mode 100644 index 0fef0a9d65..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/RenderInformation.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.user.client.Element; - -/** - * Contains size information about a rendered container and its content area. - * - * @author Artur Signell - * - */ -public class RenderInformation { - - private RenderSpace contentArea = new RenderSpace(); - private Size renderedSize = new Size(-1, -1); - - public void setContentAreaWidth(int w) { - contentArea.setWidth(w); - } - - public void setContentAreaHeight(int h) { - contentArea.setHeight(h); - } - - public RenderSpace getContentAreaSize() { - return contentArea; - - } - - public Size getRenderedSize() { - return renderedSize; - } - - /** - * Update the size of the widget. - * - * @param widget - * - * @return true if the size has changed since last update - */ - public boolean updateSize(Element element) { - Size newSize = new Size(element.getOffsetWidth(), - element.getOffsetHeight()); - if (newSize.equals(renderedSize)) { - return false; - } else { - renderedSize = newSize; - return true; - } - } - - @Override - public String toString() { - return "RenderInformation [contentArea=" + contentArea - + ",renderedSize=" + renderedSize + "]"; - - } - - public static class FloatSize { - - private float width, height; - - public FloatSize(float width, float height) { - this.width = width; - this.height = height; - } - - public float getWidth() { - return width; - } - - public void setWidth(float width) { - this.width = width; - } - - public float getHeight() { - return height; - } - - public void setHeight(float height) { - this.height = height; - } - - } - - public static class Size { - - private int width, height; - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Size)) { - return false; - } - Size other = (Size) obj; - return other.width == width && other.height == height; - } - - @Override - public int hashCode() { - return (width << 8) | height; - } - - public Size() { - } - - public Size(int width, int height) { - this.height = height; - this.width = width; - } - - public int getWidth() { - return width; - } - - public void setWidth(int width) { - this.width = width; - } - - public int getHeight() { - return height; - } - - public void setHeight(int height) { - this.height = height; - } - - @Override - public String toString() { - return "Size [width=" + width + ",height=" + height + "]"; - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/RenderSpace.java b/client/src/com/vaadin/terminal/gwt/client/RenderSpace.java deleted file mode 100644 index e92a72de86..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/RenderSpace.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import com.vaadin.terminal.gwt.client.RenderInformation.Size; - -/** - * Contains information about render area. - */ -public class RenderSpace extends Size { - - private int scrollBarSize = 0; - - public RenderSpace(int width, int height) { - super(width, height); - } - - public RenderSpace() { - } - - public RenderSpace(int width, int height, boolean useNativeScrollbarSize) { - super(width, height); - if (useNativeScrollbarSize) { - scrollBarSize = Util.getNativeScrollbarSize(); - } - } - - /** - * Returns pixels available vertically for contained widget, including - * possible scrollbars. - */ - @Override - public int getHeight() { - return super.getHeight(); - } - - /** - * Returns pixels available horizontally for contained widget, including - * possible scrollbars. - */ - @Override - public int getWidth() { - return super.getWidth(); - } - - /** - * In case containing block has oveflow: auto, this method must return - * number of pixels used by scrollbar. Returning zero means either that no - * scrollbar will be visible. - */ - public int getScrollbarSize() { - return scrollBarSize; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ResourceLoader.java b/client/src/com/vaadin/terminal/gwt/client/ResourceLoader.java deleted file mode 100644 index 57083641ba..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ResourceLoader.java +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import com.google.gwt.core.client.Duration; -import com.google.gwt.core.client.GWT; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.RepeatingCommand; -import com.google.gwt.dom.client.AnchorElement; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.LinkElement; -import com.google.gwt.dom.client.NodeList; -import com.google.gwt.dom.client.ObjectElement; -import com.google.gwt.dom.client.ScriptElement; -import com.google.gwt.user.client.Timer; - -/** - * ResourceLoader lets you dynamically include external scripts and styles on - * the page and lets you know when the resource has been loaded. - * - * You can also preload resources, allowing them to get cached by the browser - * without being evaluated. This enables downloading multiple resources at once - * while still controlling in which order e.g. scripts are executed. - * - * @author Vaadin Ltd - * @since 7.0.0 - */ -public class ResourceLoader { - /** - * Event fired when a resource has been loaded. - */ - public static class ResourceLoadEvent { - private ResourceLoader loader; - private String resourceUrl; - private final boolean preload; - - /** - * Creates a new event. - * - * @param loader - * the resource loader that has loaded the resource - * @param resourceUrl - * the url of the loaded resource - * @param preload - * true if the resource has only been preloaded, false if - * it's fully loaded - */ - public ResourceLoadEvent(ResourceLoader loader, String resourceUrl, - boolean preload) { - this.loader = loader; - this.resourceUrl = resourceUrl; - this.preload = preload; - } - - /** - * Gets the resource loader that has fired this event - * - * @return the resource loader - */ - public ResourceLoader getResourceLoader() { - return loader; - } - - /** - * Gets the absolute url of the loaded resource. - * - * @return the absolute url of the loaded resource - */ - public String getResourceUrl() { - return resourceUrl; - } - - /** - * Returns true if the resource has been preloaded, false if it's fully - * loaded - * - * @see ResourceLoader#preloadResource(String, ResourceLoadListener) - * - * @return true if the resource has been preloaded, false if it's fully - * loaded - */ - public boolean isPreload() { - return preload; - } - } - - /** - * Event listener that gets notified when a resource has been loaded - */ - public interface ResourceLoadListener { - /** - * Notifies this ResourceLoadListener that a resource has been loaded. - * Some browsers do not support any way of detecting load errors. In - * these cases, onLoad will be called regardless of the status. - * - * @see ResourceLoadEvent - * - * @param event - * a resource load event with information about the loaded - * resource - */ - public void onLoad(ResourceLoadEvent event); - - /** - * Notifies this ResourceLoadListener that a resource could not be - * loaded, e.g. because the file could not be found or because the - * server did not respond. Some browsers do not support any way of - * detecting load errors. In these cases, onLoad will be called - * regardless of the status. - * - * @see ResourceLoadEvent - * - * @param event - * a resource load event with information about the resource - * that could not be loaded. - */ - public void onError(ResourceLoadEvent event); - } - - private static final ResourceLoader INSTANCE = GWT - .create(ResourceLoader.class); - - private ApplicationConnection connection; - - private final Set<String> loadedResources = new HashSet<String>(); - private final Set<String> preloadedResources = new HashSet<String>(); - - private final Map<String, Collection<ResourceLoadListener>> loadListeners = new HashMap<String, Collection<ResourceLoadListener>>(); - private final Map<String, Collection<ResourceLoadListener>> preloadListeners = new HashMap<String, Collection<ResourceLoadListener>>(); - - private final Element head; - - /** - * Creates a new resource loader. You should generally not create you own - * resource loader, but instead use {@link ResourceLoader#get()} to get an - * instance. - */ - protected ResourceLoader() { - Document document = Document.get(); - head = document.getElementsByTagName("head").getItem(0); - - // detect already loaded scripts and stylesheets - NodeList<Element> scripts = document.getElementsByTagName("script"); - for (int i = 0; i < scripts.getLength(); i++) { - ScriptElement element = ScriptElement.as(scripts.getItem(i)); - String src = element.getSrc(); - if (src != null && src.length() != 0) { - loadedResources.add(src); - } - } - - NodeList<Element> links = document.getElementsByTagName("link"); - for (int i = 0; i < links.getLength(); i++) { - LinkElement linkElement = LinkElement.as(links.getItem(i)); - String rel = linkElement.getRel(); - String href = linkElement.getHref(); - if ("stylesheet".equalsIgnoreCase(rel) && href != null - && href.length() != 0) { - loadedResources.add(href); - } - } - } - - /** - * Returns the default ResourceLoader - * - * @return the default ResourceLoader - */ - public static ResourceLoader get() { - return INSTANCE; - } - - /** - * Load a script and notify a listener when the script is loaded. Calling - * this method when the script is currently loading or already loaded - * doesn't cause the script to be loaded again, but the listener will still - * be notified when appropriate. - * - * - * @param scriptUrl - * the url of the script to load - * @param resourceLoadListener - * the listener that will get notified when the script is loaded - */ - public void loadScript(final String scriptUrl, - final ResourceLoadListener resourceLoadListener) { - final String url = getAbsoluteUrl(scriptUrl); - ResourceLoadEvent event = new ResourceLoadEvent(this, url, false); - if (loadedResources.contains(url)) { - if (resourceLoadListener != null) { - resourceLoadListener.onLoad(event); - } - return; - } - - if (preloadListeners.containsKey(url)) { - // Preload going on, continue when preloaded - preloadResource(url, new ResourceLoadListener() { - @Override - public void onLoad(ResourceLoadEvent event) { - loadScript(url, resourceLoadListener); - } - - @Override - public void onError(ResourceLoadEvent event) { - // Preload failed -> signal error to own listener - if (resourceLoadListener != null) { - resourceLoadListener.onError(event); - } - } - }); - return; - } - - if (addListener(url, resourceLoadListener, loadListeners)) { - ScriptElement scriptTag = Document.get().createScriptElement(); - scriptTag.setSrc(url); - scriptTag.setType("text/javascript"); - addOnloadHandler(scriptTag, new ResourceLoadListener() { - @Override - public void onLoad(ResourceLoadEvent event) { - fireLoad(event); - } - - @Override - public void onError(ResourceLoadEvent event) { - fireError(event); - } - }, event); - head.appendChild(scriptTag); - } - } - - private static String getAbsoluteUrl(String url) { - AnchorElement a = Document.get().createAnchorElement(); - a.setHref(url); - return a.getHref(); - } - - /** - * Download a resource and notify a listener when the resource is loaded - * without attempting to interpret the resource. When a resource has been - * preloaded, it will be present in the browser's cache (provided the HTTP - * headers allow caching), making a subsequent load operation complete - * without having to wait for the resource to be downloaded again. - * - * Calling this method when the resource is currently loading, currently - * preloading, already preloaded or already loaded doesn't cause the - * resource to be preloaded again, but the listener will still be notified - * when appropriate. - * - * @param url - * the url of the resource to preload - * @param resourceLoadListener - * the listener that will get notified when the resource is - * preloaded - */ - public void preloadResource(String url, - ResourceLoadListener resourceLoadListener) { - url = getAbsoluteUrl(url); - ResourceLoadEvent event = new ResourceLoadEvent(this, url, true); - if (loadedResources.contains(url) || preloadedResources.contains(url)) { - // Already loaded or preloaded -> just fire listener - if (resourceLoadListener != null) { - resourceLoadListener.onLoad(event); - } - return; - } - - if (addListener(url, resourceLoadListener, preloadListeners) - && !loadListeners.containsKey(url)) { - // Inject loader element if this is the first time this is preloaded - // AND the resources isn't already being loaded in the normal way - - Element element = getPreloadElement(url); - addOnloadHandler(element, new ResourceLoadListener() { - @Override - public void onLoad(ResourceLoadEvent event) { - fireLoad(event); - } - - @Override - public void onError(ResourceLoadEvent event) { - fireError(event); - } - }, event); - - // TODO Remove object when loaded (without causing spinner in FF) - Document.get().getBody().appendChild(element); - } - } - - private static Element getPreloadElement(String url) { - if (BrowserInfo.get().isIE()) { - ScriptElement element = Document.get().createScriptElement(); - element.setSrc(url); - element.setType("text/cache"); - return element; - } else { - ObjectElement element = Document.get().createObjectElement(); - element.setData(url); - element.setType("text/plain"); - element.setHeight("0px"); - element.setWidth("0px"); - return element; - } - } - - private native void addOnloadHandler(Element element, - ResourceLoadListener listener, ResourceLoadEvent event) - /*-{ - element.onload = $entry(function() { - element.onload = null; - element.onerror = null; - element.onreadystatechange = null; - listener.@com.vaadin.terminal.gwt.client.ResourceLoader.ResourceLoadListener::onLoad(Lcom/vaadin/terminal/gwt/client/ResourceLoader$ResourceLoadEvent;)(event); - }); - element.onerror = $entry(function() { - element.onload = null; - element.onerror = null; - element.onreadystatechange = null; - listener.@com.vaadin.terminal.gwt.client.ResourceLoader.ResourceLoadListener::onError(Lcom/vaadin/terminal/gwt/client/ResourceLoader$ResourceLoadEvent;)(event); - }); - element.onreadystatechange = function() { - if ("loaded" === element.readyState || "complete" === element.readyState ) { - element.onload(arguments[0]); - } - }; - }-*/; - - /** - * Load a stylesheet and notify a listener when the stylesheet is loaded. - * Calling this method when the stylesheet is currently loading or already - * loaded doesn't cause the stylesheet to be loaded again, but the listener - * will still be notified when appropriate. - * - * @param stylesheetUrl - * the url of the stylesheet to load - * @param resourceLoadListener - * the listener that will get notified when the stylesheet is - * loaded - */ - public void loadStylesheet(final String stylesheetUrl, - final ResourceLoadListener resourceLoadListener) { - final String url = getAbsoluteUrl(stylesheetUrl); - final ResourceLoadEvent event = new ResourceLoadEvent(this, url, false); - if (loadedResources.contains(url)) { - if (resourceLoadListener != null) { - resourceLoadListener.onLoad(event); - } - return; - } - - if (preloadListeners.containsKey(url)) { - // Preload going on, continue when preloaded - preloadResource(url, new ResourceLoadListener() { - @Override - public void onLoad(ResourceLoadEvent event) { - loadStylesheet(url, resourceLoadListener); - } - - @Override - public void onError(ResourceLoadEvent event) { - // Preload failed -> signal error to own listener - if (resourceLoadListener != null) { - resourceLoadListener.onError(event); - } - } - }); - return; - } - - if (addListener(url, resourceLoadListener, loadListeners)) { - LinkElement linkElement = Document.get().createLinkElement(); - linkElement.setRel("stylesheet"); - linkElement.setType("text/css"); - linkElement.setHref(url); - - if (BrowserInfo.get().isSafari()) { - // Safari doesn't fire any events for link elements - // See http://www.phpied.com/when-is-a-stylesheet-really-loaded/ - Scheduler.get().scheduleFixedPeriod(new RepeatingCommand() { - private final Duration duration = new Duration(); - - @Override - public boolean execute() { - int styleSheetLength = getStyleSheetLength(url); - if (getStyleSheetLength(url) > 0) { - fireLoad(event); - return false; // Stop repeating - } else if (styleSheetLength == 0) { - // "Loaded" empty sheet -> most likely 404 error - fireError(event); - return true; - } else if (duration.elapsedMillis() > 60 * 1000) { - fireError(event); - return false; - } else { - return true; // Continue repeating - } - } - }, 10); - } else { - addOnloadHandler(linkElement, new ResourceLoadListener() { - @Override - public void onLoad(ResourceLoadEvent event) { - // Chrome && IE fires load for errors, must check - // stylesheet data - if (BrowserInfo.get().isChrome() - || BrowserInfo.get().isIE()) { - int styleSheetLength = getStyleSheetLength(url); - // Error if there's an empty stylesheet - if (styleSheetLength == 0) { - fireError(event); - return; - } - } - fireLoad(event); - } - - @Override - public void onError(ResourceLoadEvent event) { - fireError(event); - } - }, event); - if (BrowserInfo.get().isOpera()) { - // Opera onerror never fired, assume error if no onload in x - // seconds - new Timer() { - @Override - public void run() { - if (!loadedResources.contains(url)) { - fireError(event); - } - } - }.schedule(5 * 1000); - } - } - - head.appendChild(linkElement); - } - } - - private static native int getStyleSheetLength(String url) - /*-{ - for(var i = 0; i < $doc.styleSheets.length; i++) { - if ($doc.styleSheets[i].href === url) { - var sheet = $doc.styleSheets[i]; - try { - var rules = sheet.cssRules - if (rules === undefined) { - rules = sheet.rules; - } - - if (rules === null) { - // Style sheet loaded, but can't access length because of XSS -> assume there's something there - return 1; - } - - // Return length so we can distinguish 0 (probably 404 error) from normal case. - return rules.length; - } catch (err) { - return 1; - } - } - } - // No matching stylesheet found -> not yet loaded - return -1; - }-*/; - - private static boolean addListener(String url, - ResourceLoadListener listener, - Map<String, Collection<ResourceLoadListener>> listenerMap) { - Collection<ResourceLoadListener> listeners = listenerMap.get(url); - if (listeners == null) { - listeners = new HashSet<ResourceLoader.ResourceLoadListener>(); - listeners.add(listener); - listenerMap.put(url, listeners); - return true; - } else { - listeners.add(listener); - return false; - } - } - - private void fireError(ResourceLoadEvent event) { - String resource = event.getResourceUrl(); - - Collection<ResourceLoadListener> listeners; - if (event.isPreload()) { - // Also fire error for load listeners - fireError(new ResourceLoadEvent(this, resource, false)); - listeners = preloadListeners.remove(resource); - } else { - listeners = loadListeners.remove(resource); - } - if (listeners != null && !listeners.isEmpty()) { - for (ResourceLoadListener listener : listeners) { - if (listener != null) { - listener.onError(event); - } - } - } - } - - private void fireLoad(ResourceLoadEvent event) { - String resource = event.getResourceUrl(); - Collection<ResourceLoadListener> listeners; - if (event.isPreload()) { - preloadedResources.add(resource); - listeners = preloadListeners.remove(resource); - } else { - if (preloadListeners.containsKey(resource)) { - // Also fire preload events for potential listeners - fireLoad(new ResourceLoadEvent(this, resource, true)); - } - preloadedResources.remove(resource); - loadedResources.add(resource); - listeners = loadListeners.remove(resource); - } - if (listeners != null && !listeners.isEmpty()) { - for (ResourceLoadListener listener : listeners) { - if (listener != null) { - listener.onLoad(event); - } - } - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ServerConnector.java b/client/src/com/vaadin/terminal/gwt/client/ServerConnector.java deleted file mode 100644 index d988c5f4a2..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ServerConnector.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import java.util.Collection; -import java.util.List; - -import com.google.gwt.event.shared.GwtEvent; -import com.google.web.bindery.event.shared.HandlerRegistration; -import com.vaadin.shared.Connector; -import com.vaadin.shared.communication.ClientRpc; -import com.vaadin.shared.communication.SharedState; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler; - -/** - * Interface implemented by all client side classes that can be communicate with - * the server. Classes implementing this interface are initialized by the - * framework when needed and have the ability to communicate with the server. - * - * @author Vaadin Ltd - * @since 7.0.0 - */ -public interface ServerConnector extends Connector { - - /** - * Gets ApplicationConnection instance that created this connector. - * - * @return The ApplicationConnection as set by - * {@link #doInit(String, ApplicationConnection)} - */ - public ApplicationConnection getConnection(); - - /** - * Tests whether the connector is enabled or not. This method checks that - * the connector is enabled in context, i.e. if the parent connector is - * disabled, this method must return false. - * - * @return true if the connector is enabled, false otherwise - */ - public boolean isEnabled(); - - /** - * - * Called once by the framework to initialize the connector. - * <p> - * Note that the shared state is not yet available at this point nor any - * hierarchy information. - */ - public void doInit(String connectorId, ApplicationConnection connection); - - /** - * For internal use by the framework: returns the registered RPC - * implementations for an RPC interface identifier. - * - * TODO interface identifier type or format may change - * - * @param rpcInterfaceId - * RPC interface identifier: fully qualified interface type name - * @return RPC interface implementations registered for an RPC interface, - * not null - */ - public <T extends ClientRpc> Collection<T> getRpcImplementations( - String rpcInterfaceId); - - /** - * Adds a handler that is called whenever any part of the state has been - * updated by the server. - * - * @param handler - * The handler that should be added. - * @return A handler registration reference that can be used to unregister - * the handler - */ - public HandlerRegistration addStateChangeHandler(StateChangeHandler handler); - - /** - * Adds a handler that is called whenever the given part of the state has - * been updated by the server. - * - * @param propertyName - * the name of the property for which the handler should be - * called - * @param handler - * The handler that should be added. - * @return A handler registration reference that can be used to unregister - * the handler - */ - public HandlerRegistration addStateChangeHandler(String propertyName, - StateChangeHandler handler); - - /** - * Sends the given event to all registered handlers. - * - * @param event - * The event to send. - */ - public void fireEvent(GwtEvent<?> event); - - /** - * Event called when connector has been unregistered. - */ - public void onUnregister(); - - /** - * Returns the parent of this connector. Can be null for only the root - * connector. - * - * @return The parent of this connector, as set by - * {@link #setParent(ServerConnector)}. - */ - @Override - public ServerConnector getParent(); - - /** - * Sets the parent for this connector. This method should only be called by - * the framework to ensure that the connector hierarchy on the client side - * and the server side are in sync. - * <p> - * Note that calling this method does not fire a - * {@link ConnectorHierarchyChangeEvent}. The event is fired only when the - * whole hierarchy has been updated. - * - * @param parent - * The new parent of the connector - */ - public void setParent(ServerConnector parent); - - public void updateEnabledState(boolean enabledState); - - public void setChildren(List<ServerConnector> children); - - public List<ServerConnector> getChildren(); - - /** - * Gets the current shared state of the connector. - * - * @since 7.0. - * @return state The shared state object. Can be any sub type of - * {@link SharedState}. Never null. - */ - public SharedState getState(); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/SimpleTree.java b/client/src/com/vaadin/terminal/gwt/client/SimpleTree.java deleted file mode 100644 index d5d81d7e44..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/SimpleTree.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.SpanElement; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.BorderStyle; -import com.google.gwt.dom.client.Style.Cursor; -import com.google.gwt.dom.client.Style.Display; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.ComplexPanel; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.Widget; - -public class SimpleTree extends ComplexPanel { - private Element children = Document.get().createDivElement().cast(); - private SpanElement handle = Document.get().createSpanElement(); - private SpanElement text = Document.get().createSpanElement(); - - public SimpleTree() { - setElement(Document.get().createDivElement()); - Style style = getElement().getStyle(); - style.setProperty("whiteSpace", "nowrap"); - style.setPadding(3, Unit.PX); - style.setPaddingLeft(12, Unit.PX); - - style = handle.getStyle(); - style.setDisplay(Display.NONE); - style.setProperty("textAlign", "center"); - style.setWidth(10, Unit.PX); - style.setCursor(Cursor.POINTER); - style.setBorderStyle(BorderStyle.SOLID); - style.setBorderColor("#666"); - style.setBorderWidth(1, Unit.PX); - style.setMarginRight(3, Unit.PX); - style.setProperty("borderRadius", "4px"); - handle.setInnerHTML("+"); - getElement().appendChild(handle); - getElement().appendChild(text); - style = children.getStyle(); - style.setPaddingLeft(9, Unit.PX); - style.setDisplay(Display.NONE); - - getElement().appendChild(children); - addDomHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - if (event.getNativeEvent().getEventTarget().cast() == handle) { - if (children.getStyle().getDisplay().intern() == Display.NONE - .getCssName()) { - open(event.getNativeEvent().getShiftKey()); - } else { - close(); - } - - } else if (event.getNativeEvent().getEventTarget().cast() == text) { - select(event); - } - } - }, ClickEvent.getType()); - } - - protected void select(ClickEvent event) { - - } - - public void close() { - children.getStyle().setDisplay(Display.NONE); - handle.setInnerHTML("+"); - } - - public void open(boolean recursive) { - handle.setInnerHTML("-"); - children.getStyle().setDisplay(Display.BLOCK); - if (recursive) { - for (Widget w : getChildren()) { - if (w instanceof SimpleTree) { - SimpleTree str = (SimpleTree) w; - str.open(true); - } - } - } - } - - public SimpleTree(String caption) { - this(); - setText(caption); - } - - public void setText(String text) { - this.text.setInnerText(text); - } - - public void addItem(String text) { - Label label = new Label(text); - add(label, children); - } - - @Override - public void add(Widget child) { - add(child, children); - } - - @Override - protected void add(Widget child, Element container) { - super.add(child, container); - handle.getStyle().setDisplay(Display.INLINE_BLOCK); - getElement().getStyle().setPaddingLeft(3, Unit.PX); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/StyleConstants.java b/client/src/com/vaadin/terminal/gwt/client/StyleConstants.java deleted file mode 100644 index b4955ccd14..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/StyleConstants.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -public class StyleConstants { - - public static final String MARGIN_TOP = "margin-top"; - public static final String MARGIN_RIGHT = "margin-right"; - public static final String MARGIN_BOTTOM = "margin-bottom"; - public static final String MARGIN_LEFT = "margin-left"; - - public static final String VERTICAL_SPACING = "vspacing"; - public static final String HORIZONTAL_SPACING = "hspacing"; - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/SuperDevMode.java b/client/src/com/vaadin/terminal/gwt/client/SuperDevMode.java deleted file mode 100644 index 200ceb730a..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/SuperDevMode.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.http.client.UrlBuilder; -import com.google.gwt.jsonp.client.JsonpRequestBuilder; -import com.google.gwt.storage.client.Storage; -import com.google.gwt.user.client.Window.Location; -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.vaadin.terminal.gwt.client.ui.notification.VNotification; -import com.vaadin.terminal.gwt.client.ui.notification.VNotification.EventListener; -import com.vaadin.terminal.gwt.client.ui.notification.VNotification.HideEvent; - -/** - * Class that enables SuperDevMode using a ?superdevmode parameter in the url. - * - * @author Vaadin Ltd - * @since 7.0 - * - */ -public class SuperDevMode { - - private static final int COMPILE_TIMEOUT_IN_SECONDS = 60; - protected static final String SKIP_RECOMPILE = "VaadinSuperDevMode_skip_recompile"; - - public static class RecompileResult extends JavaScriptObject { - protected RecompileResult() { - - } - - public final native boolean ok() - /*-{ - return this.status == "ok"; - }-*/; - } - - private static void recompileWidgetsetAndStartInDevMode( - final String serverUrl) { - VConsole.log("Recompiling widgetset using<br/>" + serverUrl - + "<br/>and then reloading in super dev mode"); - VNotification n = new VNotification(); - n.show("<b>Recompiling widgetset, this should not take too long</b>", - VNotification.CENTERED, VNotification.STYLE_SYSTEM); - - JsonpRequestBuilder b = new JsonpRequestBuilder(); - b.setCallbackParam("_callback"); - b.setTimeout(COMPILE_TIMEOUT_IN_SECONDS * 1000); - b.requestObject(serverUrl + "recompile/" + GWT.getModuleName() + "?" - + getRecompileParameters(GWT.getModuleName()), - new AsyncCallback<RecompileResult>() { - - @Override - public void onSuccess(RecompileResult result) { - VConsole.log("JSONP compile call successful"); - - if (!result.ok()) { - VConsole.log("* result: " + result); - failed(); - return; - } - - setSession( - getSuperDevModeHookKey(), - getSuperDevWidgetSetUrl(GWT.getModuleName(), - serverUrl)); - setSession(SKIP_RECOMPILE, "1"); - - VConsole.log("* result: OK. Reloading"); - Location.reload(); - } - - @Override - public void onFailure(Throwable caught) { - VConsole.error("JSONP compile call failed"); - // Don't log exception as they are shown as - // notifications - VConsole.error(Util.getSimpleName(caught) + ": " - + caught.getMessage()); - failed(); - - } - - private void failed() { - VNotification n = new VNotification(); - n.addEventListener(new EventListener() { - - @Override - public void notificationHidden(HideEvent event) { - recompileWidgetsetAndStartInDevMode(serverUrl); - } - }); - n.show("Recompilation failed.<br/>" - + "Make sure CodeServer is running, " - + "check its output and click to retry", - VNotification.CENTERED, - VNotification.STYLE_SYSTEM); - } - }); - - } - - protected static String getSuperDevWidgetSetUrl(String widgetsetName, - String serverUrl) { - return serverUrl + GWT.getModuleName() + "/" + GWT.getModuleName() - + ".nocache.js"; - } - - private native static String getRecompileParameters(String moduleName) - /*-{ - var prop_map = $wnd.__gwt_activeModules[moduleName].bindings(); - - // convert map to URL parameter string - var props = []; - for (var key in prop_map) { - props.push(encodeURIComponent(key) + '=' + encodeURIComponent(prop_map[key])) - } - - return props.join('&') + '&'; - }-*/; - - private static void setSession(String key, String value) { - Storage.getSessionStorageIfSupported().setItem(key, value); - } - - private static String getSession(String key) { - return Storage.getSessionStorageIfSupported().getItem(key); - } - - private static void removeSession(String key) { - Storage.getSessionStorageIfSupported().removeItem(key); - } - - protected static void disableDevModeAndReload() { - removeSession(getSuperDevModeHookKey()); - redirect(false); - } - - protected static void redirect(boolean devModeOn) { - UrlBuilder createUrlBuilder = Location.createUrlBuilder(); - if (!devModeOn) { - createUrlBuilder.removeParameter("superdevmode"); - } else { - createUrlBuilder.setParameter("superdevmode", ""); - } - - Location.assign(createUrlBuilder.buildString()); - - } - - private static String getSuperDevModeHookKey() { - String widgetsetName = GWT.getModuleName(); - final String superDevModeKey = "__gwtDevModeHook:" + widgetsetName; - return superDevModeKey; - } - - private static boolean hasSession(String key) { - return getSession(key) != null; - } - - /** - * The URL of the code server. The default URL (http://localhost:9876/) will - * be used if this is empty or null. - * - * @param serverUrl - * The url of the code server or null to use the default - * @return true if recompile started, false if we are running in - * SuperDevMode - */ - protected static boolean recompileIfNeeded(String serverUrl) { - if (serverUrl == null || "".equals(serverUrl)) { - serverUrl = "http://localhost:9876/"; - } else { - serverUrl = "http://" + serverUrl + "/"; - } - - if (hasSession(SKIP_RECOMPILE)) { - VConsole.log("Running in SuperDevMode"); - // When we get here, we are running in super dev mode - - // Remove the flag so next reload will recompile - removeSession(SKIP_RECOMPILE); - - // Remove the gwt flag so we will not end up in dev mode if we - // remove the url parameter manually - removeSession(getSuperDevModeHookKey()); - - return false; - } - - recompileWidgetsetAndStartInDevMode(serverUrl); - return true; - } - - protected static boolean isSuperDevModeEnabledInModule() { - String moduleName = GWT.getModuleName(); - return isSuperDevModeEnabledInModule(moduleName); - } - - protected native static boolean isSuperDevModeEnabledInModule( - String moduleName) - /*-{ - if (!$wnd.__gwt_activeModules) - return false; - var mod = $wnd.__gwt_activeModules[moduleName]; - if (!mod) - return false; - - if (mod.superdevmode) { - // Running in super dev mode already, it is supported - return true; - } - - return !!mod.canRedirect; - }-*/; - - /** - * Enables SuperDevMode if the url contains the "superdevmode" parameter. - * <p> - * The caller should not continue initialization of the application if this - * method returns true. The application will be restarted once compilation - * is done and then this method will return false. - * </p> - * - * @return true if a recompile operation has started and the page will be - * reloaded once it is done, false if no recompilation will be done. - */ - public static boolean enableBasedOnParameter() { - String superDevModeParameter = Location.getParameter("superdevmode"); - if (superDevModeParameter != null) { - // Need to check the recompile flag also because if we are running - // in super dev mode, as a result of the recompile, the enabled - // check will fail... - if (!isSuperDevModeEnabledInModule()) { - showError("SuperDevMode is not enabled for this module/widgetset.<br/>" - + "Ensure that your module definition (.gwt.xml) contains <br/>" - + "<add-linker name="xsiframe"/><br/>" - + "<set-configuration-property name="devModeRedirectEnabled" value="true" /><br/>"); - return false; - } - return SuperDevMode.recompileIfNeeded(superDevModeParameter); - } - return false; - } - - private static void showError(String message) { - VNotification n = new VNotification(); - n.show(message, VNotification.CENTERED_TOP, VNotification.STYLE_SYSTEM); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/SynchronousXHR.java b/client/src/com/vaadin/terminal/gwt/client/SynchronousXHR.java deleted file mode 100644 index a0a399842a..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/SynchronousXHR.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.xhr.client.XMLHttpRequest; - -public class SynchronousXHR extends XMLHttpRequest { - - protected SynchronousXHR() { - } - - public native final void synchronousPost(String uri, String requestData) - /*-{ - try { - this.open("POST", uri, false); - this.setRequestHeader("Content-Type", "text/plain;charset=utf-8"); - this.send(requestData); - } catch (e) { - // No errors are managed as this is synchronous forceful send that can just fail - } - }-*/; - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/TooltipInfo.java b/client/src/com/vaadin/terminal/gwt/client/TooltipInfo.java deleted file mode 100644 index e0a398b90d..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/TooltipInfo.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -public class TooltipInfo { - - private String title; - - private String errorMessageHtml; - - public TooltipInfo() { - } - - public TooltipInfo(String tooltip) { - setTitle(tooltip); - } - - public TooltipInfo(String tooltip, String errorMessage) { - setTitle(tooltip); - setErrorMessage(errorMessage); - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getErrorMessage() { - return errorMessageHtml; - } - - public void setErrorMessage(String errorMessage) { - errorMessageHtml = errorMessage; - } - - /** - * Checks is a message has been defined for the tooltip. - * - * @return true if title or error message is present, false if both are - * empty - */ - public boolean hasMessage() { - return (title != null && !title.isEmpty()) - || (errorMessageHtml != null && !errorMessageHtml.isEmpty()); - } - - public boolean equals(TooltipInfo other) { - return (other != null && other.title == title && other.errorMessageHtml == errorMessageHtml); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/UIDL.java b/client/src/com/vaadin/terminal/gwt/client/UIDL.java deleted file mode 100644 index 9032a04e24..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/UIDL.java +++ /dev/null @@ -1,563 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.JsArrayString; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.ui.AbstractComponent; -import com.vaadin.ui.Component; - -/** - * When a component is updated, it's client side widget's - * {@link ComponentConnector#updateFromUIDL(UIDL, ApplicationConnection) - * updateFromUIDL()} will be called with the updated ("changes") UIDL received - * from the server. - * <p> - * UIDL is hierarchical, and there are a few methods to retrieve the children, - * {@link #getChildCount()}, {@link #getChildIterator()} - * {@link #getChildString(int)}, {@link #getChildUIDL(int)}. - * </p> - * <p> - * It can be helpful to keep in mind that UIDL was originally modeled in XML, so - * it's structure is very XML -like. For instance, the first to children in the - * underlying UIDL representation will contain the "tag" name and attributes, - * but will be skipped by the methods mentioned above. - * </p> - */ -public final class UIDL extends JavaScriptObject { - - protected UIDL() { - } - - /** - * Shorthand for getting the attribute named "id", which for Paintables is - * the essential paintableId which binds the server side component to the - * client side widget. - * - * @return the value of the id attribute, if available - */ - public String getId() { - return getStringAttribute("id"); - } - - /** - * Gets the name of this UIDL section, as created with - * {@link PaintTarget#startTag(String) PaintTarget.startTag()} in the - * server-side {@link Component#paint(PaintTarget) Component.paint()} or - * (usually) {@link AbstractComponent#paintContent(PaintTarget) - * AbstractComponent.paintContent()}. Note that if the UIDL corresponds to a - * Paintable, a component identifier will be returned instead - this is used - * internally and is not needed within - * {@link ComponentConnector#updateFromUIDL(UIDL, ApplicationConnection) - * updateFromUIDL()}. - * - * @return the name for this section - */ - public native String getTag() - /*-{ - return this[0]; - }-*/; - - private native ValueMap attr() - /*-{ - return this[1]; - }-*/; - - private native ValueMap var() - /*-{ - return this[1]["v"]; - }-*/; - - private native boolean hasVariables() - /*-{ - return Boolean(this[1]["v"]); - }-*/; - - /** - * Gets the named attribute as a String. - * - * @param name - * the name of the attribute to get - * @return the attribute value - */ - public String getStringAttribute(String name) { - return attr().getString(name); - } - - /** - * Gets the names of the attributes available. - * - * @return the names of available attributes - */ - public Set<String> getAttributeNames() { - Set<String> keySet = attr().getKeySet(); - keySet.remove("v"); - return keySet; - } - - /** - * Gets the names of variables available. - * - * @return the names of available variables - */ - public Set<String> getVariableNames() { - if (!hasVariables()) { - return new HashSet<String>(); - } else { - Set<String> keySet = var().getKeySet(); - return keySet; - } - } - - /** - * Gets the named attribute as an int. - * - * @param name - * the name of the attribute to get - * @return the attribute value - */ - public int getIntAttribute(String name) { - return attr().getInt(name); - } - - /** - * Gets the named attribute as a long. - * - * @param name - * the name of the attribute to get - * @return the attribute value - */ - public long getLongAttribute(String name) { - return (long) attr().getRawNumber(name); - } - - /** - * Gets the named attribute as a float. - * - * @param name - * the name of the attribute to get - * @return the attribute value - */ - public float getFloatAttribute(String name) { - return (float) attr().getRawNumber(name); - } - - /** - * Gets the named attribute as a double. - * - * @param name - * the name of the attribute to get - * @return the attribute value - */ - public double getDoubleAttribute(String name) { - return attr().getRawNumber(name); - } - - /** - * Gets the named attribute as a boolean. - * - * @param name - * the name of the attribute to get - * @return the attribute value - */ - public boolean getBooleanAttribute(String name) { - return attr().getBoolean(name); - } - - /** - * Gets the named attribute as a Map of named values (key/value pairs). - * - * @param name - * the name of the attribute to get - * @return the attribute Map - */ - public ValueMap getMapAttribute(String name) { - return attr().getValueMap(name); - } - - /** - * Gets the named attribute as an array of Strings. - * - * @param name - * the name of the attribute to get - * @return the attribute value - */ - public String[] getStringArrayAttribute(String name) { - return attr().getStringArray(name); - } - - /** - * Gets the named attribute as an int array. - * - * @param name - * the name of the attribute to get - * @return the attribute value - */ - public int[] getIntArrayAttribute(final String name) { - return attr().getIntArray(name); - } - - /** - * Get attributes value as string whatever the type is - * - * @param name - * @return string presentation of attribute - */ - native String getAttribute(String name) - /*-{ - return '' + this[1][name]; - }-*/; - - native String getVariable(String name) - /*-{ - return '' + this[1]['v'][name]; - }-*/; - - /** - * Indicates whether or not the named attribute is available. - * - * @param name - * the name of the attribute to check - * @return true if the attribute is available, false otherwise - */ - public boolean hasAttribute(final String name) { - return attr().containsKey(name); - } - - /** - * Gets the UIDL for the child at the given index. - * - * @param i - * the index of the child to get - * @return the UIDL of the child if it exists - */ - public native UIDL getChildUIDL(int i) - /*-{ - return this[i + 2]; - }-*/; - - /** - * Gets the child at the given index as a String. - * - * @param i - * the index of the child to get - * @return the String representation of the child if it exists - */ - public native String getChildString(int i) - /*-{ - return this[i + 2]; - }-*/; - - private native XML getChildXML(int index) - /*-{ - return this[index + 2]; - }-*/; - - /** - * Gets an iterator that can be used to iterate trough the children of this - * UIDL. - * <p> - * The Object returned by <code>next()</code> will be appropriately typed - - * if it's UIDL, {@link #getTag()} can be used to check which section is in - * question. - * </p> - * <p> - * The basic use case is to iterate over the children of an UIDL update, and - * update the appropriate part of the widget for each child encountered, e.g - * if <code>getTag()</code> returns "color", one would update the widgets - * color to reflect the value of the "color" section. - * </p> - * - * @return an iterator for iterating over UIDL children - */ - public Iterator<Object> getChildIterator() { - - return new Iterator<Object>() { - - int index = -1; - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - @Override - public Object next() { - - if (hasNext()) { - int typeOfChild = typeOfChild(++index); - switch (typeOfChild) { - case CHILD_TYPE_UIDL: - UIDL childUIDL = getChildUIDL(index); - return childUIDL; - case CHILD_TYPE_STRING: - return getChildString(index); - case CHILD_TYPE_XML: - return getChildXML(index); - default: - throw new IllegalStateException( - "Illegal child in tag " + getTag() - + " at index " + index); - } - } - return null; - } - - @Override - public boolean hasNext() { - int count = getChildCount(); - return count > index + 1; - } - - }; - } - - private static final int CHILD_TYPE_STRING = 0; - private static final int CHILD_TYPE_UIDL = 1; - private static final int CHILD_TYPE_XML = 2; - - private native int typeOfChild(int index) - /*-{ - var t = typeof this[index + 2]; - if(t == "object") { - if(typeof(t.length) == "number") { - return 1; - } else { - return 2; - } - } else if (t == "string") { - return 0; - } - return -1; - }-*/; - - /** - * @deprecated - */ - @Deprecated - public String getChildrenAsXML() { - return toString(); - } - - /** - * Checks if the named variable is available. - * - * @param name - * the name of the variable desired - * @return true if the variable exists, false otherwise - */ - public boolean hasVariable(String name) { - return hasVariables() && var().containsKey(name); - } - - /** - * Gets the value of the named variable. - * - * @param name - * the name of the variable - * @return the value of the variable - */ - public String getStringVariable(String name) { - return var().getString(name); - } - - /** - * Gets the value of the named variable. - * - * @param name - * the name of the variable - * @return the value of the variable - */ - public int getIntVariable(String name) { - return var().getInt(name); - } - - /** - * Gets the value of the named variable. - * - * @param name - * the name of the variable - * @return the value of the variable - */ - public long getLongVariable(String name) { - return (long) var().getRawNumber(name); - } - - /** - * Gets the value of the named variable. - * - * @param name - * the name of the variable - * @return the value of the variable - */ - public float getFloatVariable(String name) { - return (float) var().getRawNumber(name); - } - - /** - * Gets the value of the named variable. - * - * @param name - * the name of the variable - * @return the value of the variable - */ - public double getDoubleVariable(String name) { - return var().getRawNumber(name); - } - - /** - * Gets the value of the named variable. - * - * @param name - * the name of the variable - * @return the value of the variable - */ - public boolean getBooleanVariable(String name) { - return var().getBoolean(name); - } - - /** - * Gets the value of the named variable. - * - * @param name - * the name of the variable - * @return the value of the variable - */ - public String[] getStringArrayVariable(String name) { - return var().getStringArray(name); - } - - /** - * Gets the value of the named String[] variable as a Set of Strings. - * - * @param name - * the name of the variable - * @return the value of the variable - */ - public Set<String> getStringArrayVariableAsSet(final String name) { - final HashSet<String> s = new HashSet<String>(); - JsArrayString a = var().getJSStringArray(name); - for (int i = 0; i < a.length(); i++) { - s.add(a.get(i)); - } - return s; - } - - /** - * Gets the value of the named variable. - * - * @param name - * the name of the variable - * @return the value of the variable - */ - public int[] getIntArrayVariable(String name) { - return var().getIntArray(name); - } - - /** - * @deprecated should not be used anymore - */ - @Deprecated - public final static class XML extends JavaScriptObject { - protected XML() { - } - - public native String getXMLAsString() - /*-{ - var buf = new Array(); - var self = this; - for(j in self) { - buf.push("<"); - buf.push(j); - buf.push(">"); - buf.push(self[j]); - buf.push("</"); - buf.push(j); - buf.push(">"); - } - return buf.join(""); - }-*/; - } - - /** - * Returns the number of children. - * - * @return the number of children - */ - public native int getChildCount() - /*-{ - return this.length - 2; - }-*/; - - native boolean isMapAttribute(String name) - /*-{ - return typeof this[1][name] == "object"; - }-*/; - - /** - * Gets the Paintable with the id found in the named attributes's value. - * - * @param name - * the name of the attribute - * @return the Paintable referenced by the attribute, if it exists - */ - public ServerConnector getPaintableAttribute(String name, - ApplicationConnection connection) { - return ConnectorMap.get(connection).getConnector( - getStringAttribute(name)); - } - - /** - * Gets the Paintable with the id found in the named variable's value. - * - * @param name - * the name of the variable - * @return the Paintable referenced by the variable, if it exists - */ - public ServerConnector getPaintableVariable(String name, - ApplicationConnection connection) { - return ConnectorMap.get(connection).getConnector( - getStringVariable(name)); - } - - /** - * Returns the child UIDL by its name. If several child nodes exist with the - * given name, the first child UIDL will be returned. - * - * @param tagName - * @return the child UIDL or null if child wit given name was not found - */ - public UIDL getChildByTagName(String tagName) { - Iterator<Object> childIterator = getChildIterator(); - while (childIterator.hasNext()) { - Object next = childIterator.next(); - if (next instanceof UIDL) { - UIDL childUIDL = (UIDL) next; - if (childUIDL.getTag().equals(tagName)) { - return childUIDL; - } - } - } - return null; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/Util.java b/client/src/com/vaadin/terminal/gwt/client/Util.java deleted file mode 100644 index 96344f0792..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/Util.java +++ /dev/null @@ -1,1194 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.dom.client.Node; -import com.google.gwt.dom.client.NodeList; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Touch; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.EventListener; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.HasWidgets; -import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ApplicationConstants; -import com.vaadin.shared.ComponentState; -import com.vaadin.shared.communication.MethodInvocation; -import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize; -import com.vaadin.terminal.gwt.client.ui.VOverlay; - -public class Util { - - /** - * Helper method for debugging purposes. - * - * Stops execution on firefox browsers on a breakpoint. - * - */ - public static native void browserDebugger() - /*-{ - if($wnd.console) - debugger; - }-*/; - - /** - * - * Returns the topmost element of from given coordinates. - * - * TODO fix crossplat issues clientX vs pageX. See quircksmode. Not critical - * for vaadin as we scroll div istead of page. - * - * @param x - * @param y - * @return the element at given coordinates - */ - public static native Element getElementFromPoint(int clientX, int clientY) - /*-{ - var el = $wnd.document.elementFromPoint(clientX, clientY); - if(el != null && el.nodeType == 3) { - el = el.parentNode; - } - return el; - }-*/; - - /** - * This helper method can be called if components size have been changed - * outside rendering phase. It notifies components parent about the size - * change so it can react. - * - * When using this method, developer should consider if size changes could - * be notified lazily. If lazy flag is true, method will save widget and - * wait for a moment until it notifies parents in chunks. This may vastly - * optimize layout in various situation. Example: if component have a lot of - * images their onload events may fire "layout phase" many times in a short - * period. - * - * @param widget - * @param lazy - * run componentSizeUpdated lazyly - * - * @deprecated since 7.0, use - * {@link LayoutManager#setNeedsMeasure(ComponentConnector)} - * instead - */ - @Deprecated - public static void notifyParentOfSizeChange(Widget widget, boolean lazy) { - ComponentConnector connector = findConnectorFor(widget); - if (connector != null) { - connector.getLayoutManager().setNeedsMeasure(connector); - if (!lazy) { - connector.getLayoutManager().layoutNow(); - } - } - } - - private static ComponentConnector findConnectorFor(Widget widget) { - List<ApplicationConnection> runningApplications = ApplicationConfiguration - .getRunningApplications(); - for (ApplicationConnection applicationConnection : runningApplications) { - ConnectorMap connectorMap = applicationConnection.getConnectorMap(); - ComponentConnector connector = connectorMap.getConnector(widget); - if (connector == null) { - continue; - } - if (connector.getConnection() == applicationConnection) { - return connector; - } - } - - return null; - } - - public static float parseRelativeSize(String size) { - if (size == null || !size.endsWith("%")) { - return -1; - } - - try { - return Float.parseFloat(size.substring(0, size.length() - 1)); - } catch (Exception e) { - VConsole.log("Unable to parse relative size"); - return -1; - } - } - - private static final Element escapeHtmlHelper = DOM.createDiv(); - - /** - * Converts html entities to text. - * - * @param html - * @return escaped string presentation of given html - */ - public static String escapeHTML(String html) { - DOM.setInnerText(escapeHtmlHelper, html); - String escapedText = DOM.getInnerHTML(escapeHtmlHelper); - if (BrowserInfo.get().isIE8()) { - // #7478 IE8 "incorrectly" returns "<br>" for newlines set using - // setInnerText. The same for " " which is converted to " " - escapedText = escapedText.replaceAll("<(BR|br)>", "\n"); - escapedText = escapedText.replaceAll(" ", " "); - } - return escapedText; - } - - /** - * Escapes the string so it is safe to write inside an HTML attribute. - * - * @param attribute - * The string to escape - * @return An escaped version of <literal>attribute</literal>. - */ - public static String escapeAttribute(String attribute) { - attribute = attribute.replace("\"", """); - attribute = attribute.replace("'", "'"); - attribute = attribute.replace(">", ">"); - attribute = attribute.replace("<", "<"); - attribute = attribute.replace("&", "&"); - return attribute; - } - - /** - * Clones given element as in JavaScript. - * - * Deprecate this if there appears similar method into GWT someday. - * - * @param element - * @param deep - * clone child tree also - * @return - */ - public static native Element cloneNode(Element element, boolean deep) - /*-{ - return element.cloneNode(deep); - }-*/; - - public static int measureHorizontalPaddingAndBorder(Element element, - int paddingGuess) { - String originalWidth = DOM.getStyleAttribute(element, "width"); - - int originalOffsetWidth = element.getOffsetWidth(); - int widthGuess = (originalOffsetWidth - paddingGuess); - if (widthGuess < 1) { - widthGuess = 1; - } - DOM.setStyleAttribute(element, "width", widthGuess + "px"); - int padding = element.getOffsetWidth() - widthGuess; - - DOM.setStyleAttribute(element, "width", originalWidth); - - return padding; - } - - public static int measureVerticalPaddingAndBorder(Element element, - int paddingGuess) { - String originalHeight = DOM.getStyleAttribute(element, "height"); - int originalOffsetHeight = element.getOffsetHeight(); - int widthGuess = (originalOffsetHeight - paddingGuess); - if (widthGuess < 1) { - widthGuess = 1; - } - DOM.setStyleAttribute(element, "height", widthGuess + "px"); - int padding = element.getOffsetHeight() - widthGuess; - - DOM.setStyleAttribute(element, "height", originalHeight); - return padding; - } - - public static int measureHorizontalBorder(Element element) { - int borders; - - if (BrowserInfo.get().isIE()) { - String width = element.getStyle().getProperty("width"); - String height = element.getStyle().getProperty("height"); - - int offsetWidth = element.getOffsetWidth(); - int offsetHeight = element.getOffsetHeight(); - if (offsetHeight < 1) { - offsetHeight = 1; - } - if (offsetWidth < 1) { - offsetWidth = 10; - } - element.getStyle().setPropertyPx("height", offsetHeight); - element.getStyle().setPropertyPx("width", offsetWidth); - - borders = element.getOffsetWidth() - element.getClientWidth(); - - element.getStyle().setProperty("width", width); - element.getStyle().setProperty("height", height); - } else { - borders = element.getOffsetWidth() - - element.getPropertyInt("clientWidth"); - } - assert borders >= 0; - - return borders; - } - - public static int measureVerticalBorder(Element element) { - int borders; - if (BrowserInfo.get().isIE()) { - String width = element.getStyle().getProperty("width"); - String height = element.getStyle().getProperty("height"); - - int offsetWidth = element.getOffsetWidth(); - int offsetHeight = element.getOffsetHeight(); - if (offsetHeight < 1) { - offsetHeight = 1; - } - if (offsetWidth < 1) { - offsetWidth = 10; - } - element.getStyle().setPropertyPx("width", offsetWidth); - - element.getStyle().setPropertyPx("height", offsetHeight); - - borders = element.getOffsetHeight() - - element.getPropertyInt("clientHeight"); - - element.getStyle().setProperty("height", height); - element.getStyle().setProperty("width", width); - } else { - borders = element.getOffsetHeight() - - element.getPropertyInt("clientHeight"); - } - assert borders >= 0; - - return borders; - } - - public static int measureMarginLeft(Element element) { - return element.getAbsoluteLeft() - - element.getParentElement().getAbsoluteLeft(); - } - - public static int setHeightExcludingPaddingAndBorder(Widget widget, - String height, int paddingBorderGuess) { - if (height.equals("")) { - setHeight(widget, ""); - return paddingBorderGuess; - } else if (height.endsWith("px")) { - int pixelHeight = Integer.parseInt(height.substring(0, - height.length() - 2)); - return setHeightExcludingPaddingAndBorder(widget.getElement(), - pixelHeight, paddingBorderGuess, false); - } else { - // Set the height in unknown units - setHeight(widget, height); - // Use the offsetWidth - return setHeightExcludingPaddingAndBorder(widget.getElement(), - widget.getOffsetHeight(), paddingBorderGuess, true); - } - } - - private static void setWidth(Widget widget, String width) { - DOM.setStyleAttribute(widget.getElement(), "width", width); - } - - private static void setHeight(Widget widget, String height) { - DOM.setStyleAttribute(widget.getElement(), "height", height); - } - - public static int setWidthExcludingPaddingAndBorder(Widget widget, - String width, int paddingBorderGuess) { - if (width.equals("")) { - setWidth(widget, ""); - return paddingBorderGuess; - } else if (width.endsWith("px")) { - int pixelWidth = Integer.parseInt(width.substring(0, - width.length() - 2)); - return setWidthExcludingPaddingAndBorder(widget.getElement(), - pixelWidth, paddingBorderGuess, false); - } else { - setWidth(widget, width); - return setWidthExcludingPaddingAndBorder(widget.getElement(), - widget.getOffsetWidth(), paddingBorderGuess, true); - } - } - - public static int setWidthExcludingPaddingAndBorder(Element element, - int requestedWidth, int horizontalPaddingBorderGuess, - boolean requestedWidthIncludesPaddingBorder) { - - int widthGuess = requestedWidth - horizontalPaddingBorderGuess; - if (widthGuess < 0) { - widthGuess = 0; - } - - DOM.setStyleAttribute(element, "width", widthGuess + "px"); - int captionOffsetWidth = DOM.getElementPropertyInt(element, - "offsetWidth"); - - int actualPadding = captionOffsetWidth - widthGuess; - - if (requestedWidthIncludesPaddingBorder) { - actualPadding += actualPadding; - } - - if (actualPadding != horizontalPaddingBorderGuess) { - int w = requestedWidth - actualPadding; - if (w < 0) { - // Cannot set negative width even if we would want to - w = 0; - } - DOM.setStyleAttribute(element, "width", w + "px"); - - } - - return actualPadding; - - } - - public static int setHeightExcludingPaddingAndBorder(Element element, - int requestedHeight, int verticalPaddingBorderGuess, - boolean requestedHeightIncludesPaddingBorder) { - - int heightGuess = requestedHeight - verticalPaddingBorderGuess; - if (heightGuess < 0) { - heightGuess = 0; - } - - DOM.setStyleAttribute(element, "height", heightGuess + "px"); - int captionOffsetHeight = DOM.getElementPropertyInt(element, - "offsetHeight"); - - int actualPadding = captionOffsetHeight - heightGuess; - - if (requestedHeightIncludesPaddingBorder) { - actualPadding += actualPadding; - } - - if (actualPadding != verticalPaddingBorderGuess) { - int h = requestedHeight - actualPadding; - if (h < 0) { - // Cannot set negative height even if we would want to - h = 0; - } - DOM.setStyleAttribute(element, "height", h + "px"); - - } - - return actualPadding; - - } - - public static String getSimpleName(Object widget) { - if (widget == null) { - return "(null)"; - } - - String name = widget.getClass().getName(); - return name.substring(name.lastIndexOf('.') + 1); - } - - public static void setFloat(Element element, String value) { - if (BrowserInfo.get().isIE()) { - DOM.setStyleAttribute(element, "styleFloat", value); - } else { - DOM.setStyleAttribute(element, "cssFloat", value); - } - } - - private static int detectedScrollbarSize = -1; - - public static int getNativeScrollbarSize() { - if (detectedScrollbarSize < 0) { - Element scroller = DOM.createDiv(); - scroller.getStyle().setProperty("width", "50px"); - scroller.getStyle().setProperty("height", "50px"); - scroller.getStyle().setProperty("overflow", "scroll"); - scroller.getStyle().setProperty("position", "absolute"); - scroller.getStyle().setProperty("marginLeft", "-5000px"); - RootPanel.getBodyElement().appendChild(scroller); - detectedScrollbarSize = scroller.getOffsetWidth() - - scroller.getPropertyInt("clientWidth"); - - RootPanel.getBodyElement().removeChild(scroller); - } - return detectedScrollbarSize; - } - - /** - * Run workaround for webkits overflow auto issue. - * - * See: our bug #2138 and https://bugs.webkit.org/show_bug.cgi?id=21462 - * - * @param elem - * with overflow auto - */ - public static void runWebkitOverflowAutoFix(final Element elem) { - // Add max version if fix lands sometime to Webkit - // Starting from Opera 11.00, also a problem in Opera - if (BrowserInfo.get().requiresOverflowAutoFix()) { - final String originalOverflow = elem.getStyle().getProperty( - "overflow"); - if ("hidden".equals(originalOverflow)) { - return; - } - - // check the scrolltop value before hiding the element - final int scrolltop = elem.getScrollTop(); - final int scrollleft = elem.getScrollLeft(); - elem.getStyle().setProperty("overflow", "hidden"); - - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - // Dough, Safari scroll auto means actually just a moped - elem.getStyle().setProperty("overflow", originalOverflow); - - if (scrolltop > 0 || elem.getScrollTop() > 0) { - int scrollvalue = scrolltop; - if (scrollvalue == 0) { - // mysterious are the ways of webkits scrollbar - // handling. In some cases webkit reports bad (0) - // scrolltop before hiding the element temporary, - // sometimes after. - scrollvalue = elem.getScrollTop(); - } - // fix another bug where scrollbar remains in wrong - // position - elem.setScrollTop(scrollvalue - 1); - elem.setScrollTop(scrollvalue); - } - - // fix for #6940 : Table horizontal scroll sometimes not - // updated when collapsing/expanding columns - // Also appeared in Safari 5.1 with webkit 534 (#7667) - if ((BrowserInfo.get().isChrome() || (BrowserInfo.get() - .isSafari() && BrowserInfo.get().getWebkitVersion() >= 534)) - && (scrollleft > 0 || elem.getScrollLeft() > 0)) { - int scrollvalue = scrollleft; - - if (scrollvalue == 0) { - // mysterious are the ways of webkits scrollbar - // handling. In some cases webkit may report a bad - // (0) scrollleft before hiding the element - // temporary, sometimes after. - scrollvalue = elem.getScrollLeft(); - } - // fix another bug where scrollbar remains in wrong - // position - elem.setScrollLeft(scrollvalue - 1); - elem.setScrollLeft(scrollvalue); - } - } - }); - } - - } - - /** - * Parses shared state and fetches the relative size of the component. If a - * dimension is not specified as relative it will return -1. If the shared - * state does not contain width or height specifications this will return - * null. - * - * @param state - * @return - */ - public static FloatSize parseRelativeSize(ComponentState state) { - if (state.isUndefinedHeight() && state.isUndefinedWidth()) { - return null; - } - - float relativeWidth = Util.parseRelativeSize(state.getWidth()); - float relativeHeight = Util.parseRelativeSize(state.getHeight()); - - FloatSize relativeSize = new FloatSize(relativeWidth, relativeHeight); - return relativeSize; - - } - - @Deprecated - public static boolean isCached(UIDL uidl) { - return uidl.getBooleanAttribute("cached"); - } - - public static void alert(String string) { - if (true) { - Window.alert(string); - } - } - - public static boolean equals(Object a, Object b) { - if (a == null) { - return b == null; - } - - return a.equals(b); - } - - public static void updateRelativeChildrenAndSendSizeUpdateEvent( - ApplicationConnection client, HasWidgets container, Widget widget) { - notifyParentOfSizeChange(widget, false); - } - - public static native int getRequiredWidth( - com.google.gwt.dom.client.Element element) - /*-{ - if (element.getBoundingClientRect) { - var rect = element.getBoundingClientRect(); - return Math.ceil(rect.right - rect.left); - } else { - return element.offsetWidth; - } - }-*/; - - public static native int getRequiredHeight( - com.google.gwt.dom.client.Element element) - /*-{ - var height; - if (element.getBoundingClientRect != null) { - var rect = element.getBoundingClientRect(); - height = Math.ceil(rect.bottom - rect.top); - } else { - height = element.offsetHeight; - } - return height; - }-*/; - - public static int getRequiredWidth(Widget widget) { - return getRequiredWidth(widget.getElement()); - } - - public static int getRequiredHeight(Widget widget) { - return getRequiredHeight(widget.getElement()); - } - - /** - * Detects what is currently the overflow style attribute in given element. - * - * @param pe - * the element to detect - * @return true if auto or scroll - */ - public static boolean mayHaveScrollBars(com.google.gwt.dom.client.Element pe) { - String overflow = getComputedStyle(pe, "overflow"); - if (overflow != null) { - if (overflow.equals("auto") || overflow.equals("scroll")) { - return true; - } else { - return false; - } - } else { - return false; - } - } - - /** - * A simple helper method to detect "computed style" (aka style sheets + - * element styles). Values returned differ a lot depending on browsers. - * Always be very careful when using this. - * - * @param el - * the element from which the style property is detected - * @param p - * the property to detect - * @return String value of style property - */ - private static native String getComputedStyle( - com.google.gwt.dom.client.Element el, String p) - /*-{ - try { - - if (el.currentStyle) { - // IE - return el.currentStyle[p]; - } else if (window.getComputedStyle) { - // Sa, FF, Opera - var view = el.ownerDocument.defaultView; - return view.getComputedStyle(el,null).getPropertyValue(p); - } else { - // fall back for non IE, Sa, FF, Opera - return ""; - } - } catch (e) { - return ""; - } - - }-*/; - - /** - * Locates the nested child component of <literal>parent</literal> which - * contains the element <literal>element</literal>. The child component is - * also returned if "element" is part of its caption. If - * <literal>element</literal> is not part of any child component, null is - * returned. - * - * This method returns the deepest nested VPaintableWidget. - * - * @param client - * A reference to ApplicationConnection - * @param parent - * The widget that contains <literal>element</literal>. - * @param element - * An element that is a sub element of the parent - * @return The VPaintableWidget which the element is a part of. Null if the - * element does not belong to a child. - */ - public static ComponentConnector getConnectorForElement( - ApplicationConnection client, Widget parent, Element element) { - - Element browseElement = element; - Element rootElement = parent.getElement(); - - while (browseElement != null && browseElement != rootElement) { - - ComponentConnector connector = ConnectorMap.get(client) - .getConnector(browseElement); - - if (connector == null) { - String ownerPid = VCaption.getCaptionOwnerPid(browseElement); - if (ownerPid != null) { - connector = (ComponentConnector) ConnectorMap.get(client) - .getConnector(ownerPid); - } - } - - if (connector != null) { - // check that inside the rootElement - while (browseElement != null && browseElement != rootElement) { - browseElement = (Element) browseElement.getParentElement(); - } - if (browseElement != rootElement) { - return null; - } else { - return connector; - } - } - - browseElement = (Element) browseElement.getParentElement(); - } - - // No connector found, element is possibly inside a VOverlay - // If the overlay has an owner, try to find the owner's connector - VOverlay overlay = findWidget(element, VOverlay.class); - if (overlay != null && overlay.getOwner() != null) { - return getConnectorForElement(client, RootPanel.get(), overlay - .getOwner().getElement()); - } else { - return null; - } - } - - /** - * Will (attempt) to focus the given DOM Element. - * - * @param el - * the element to focus - */ - public static native void focus(Element el) - /*-{ - try { - el.focus(); - } catch (e) { - - } - }-*/; - - /** - * Helper method to find the nearest parent paintable instance by traversing - * the DOM upwards from given element. - * - * @param element - * the element to start from - */ - public static ComponentConnector findPaintable( - ApplicationConnection client, Element element) { - Widget widget = Util.findWidget(element, null); - ConnectorMap vPaintableMap = ConnectorMap.get(client); - while (widget != null && !vPaintableMap.isConnector(widget)) { - widget = widget.getParent(); - } - return vPaintableMap.getConnector(widget); - - } - - /** - * Helper method to find first instance of given Widget type found by - * traversing DOM upwards from given element. - * - * @param element - * the element where to start seeking of Widget - * @param class1 - * the Widget type to seek for - */ - public static <T> T findWidget(Element element, - Class<? extends Widget> class1) { - if (element != null) { - /* First seek for the first EventListener (~Widget) from dom */ - EventListener eventListener = null; - while (eventListener == null && element != null) { - eventListener = Event.getEventListener(element); - if (eventListener == null) { - element = (Element) element.getParentElement(); - } - } - if (eventListener != null) { - /* - * Then find the first widget of type class1 from widget - * hierarchy - */ - Widget w = (Widget) eventListener; - while (w != null) { - if (class1 == null || w.getClass() == class1) { - return (T) w; - } - w = w.getParent(); - } - } - } - return null; - } - - /** - * Force webkit to redraw an element - * - * @param element - * The element that should be redrawn - */ - public static void forceWebkitRedraw(Element element) { - Style style = element.getStyle(); - String s = style.getProperty("webkitTransform"); - if (s == null || s.length() == 0) { - style.setProperty("webkitTransform", "scale(1)"); - } else { - style.setProperty("webkitTransform", ""); - } - } - - /** - * Detaches and re-attaches the element from its parent. The element is - * reattached at the same position in the DOM as it was before. - * - * Does nothing if the element is not attached to the DOM. - * - * @param element - * The element to detach and re-attach - */ - public static void detachAttach(Element element) { - if (element == null) { - return; - } - - Node nextSibling = element.getNextSibling(); - Node parent = element.getParentNode(); - if (parent == null) { - return; - } - - parent.removeChild(element); - if (nextSibling == null) { - parent.appendChild(element); - } else { - parent.insertBefore(element, nextSibling); - } - - } - - public static void sinkOnloadForImages(Element element) { - NodeList<com.google.gwt.dom.client.Element> imgElements = element - .getElementsByTagName("img"); - for (int i = 0; i < imgElements.getLength(); i++) { - DOM.sinkEvents((Element) imgElements.getItem(i), Event.ONLOAD); - } - - } - - /** - * Returns the index of the childElement within its parent. - * - * @param subElement - * @return - */ - public static int getChildElementIndex(Element childElement) { - int idx = 0; - Node n = childElement; - while ((n = n.getPreviousSibling()) != null) { - idx++; - } - - return idx; - } - - private static void printConnectorInvocations( - ArrayList<MethodInvocation> invocations, String id, - ApplicationConnection c) { - ServerConnector connector = ConnectorMap.get(c).getConnector(id); - if (connector != null) { - VConsole.log("\t" + id + " (" + connector.getClass() + ") :"); - } else { - VConsole.log("\t" + id - + ": Warning: no corresponding connector for id " + id); - } - for (MethodInvocation invocation : invocations) { - Object[] parameters = invocation.getParameters(); - String formattedParams = null; - if (ApplicationConstants.UPDATE_VARIABLE_METHOD.equals(invocation - .getMethodName()) && parameters.length == 2) { - // name, value - Object value = parameters[1]; - // TODO paintables inside lists/maps get rendered as - // components in the debug console - String formattedValue = value instanceof ServerConnector ? ((ServerConnector) value) - .getConnectorId() : String.valueOf(value); - formattedParams = parameters[0] + " : " + formattedValue; - } - if (null == formattedParams) { - formattedParams = (null != parameters) ? Arrays - .toString(parameters) : null; - } - VConsole.log("\t\t" + invocation.getInterfaceName() + "." - + invocation.getMethodName() + "(" + formattedParams + ")"); - } - } - - static void logVariableBurst(ApplicationConnection c, - Collection<MethodInvocation> loggedBurst) { - try { - VConsole.log("Variable burst to be sent to server:"); - String curId = null; - ArrayList<MethodInvocation> invocations = new ArrayList<MethodInvocation>(); - for (MethodInvocation methodInvocation : loggedBurst) { - String id = methodInvocation.getConnectorId(); - - if (curId == null) { - curId = id; - } else if (!curId.equals(id)) { - printConnectorInvocations(invocations, curId, c); - invocations.clear(); - curId = id; - } - invocations.add(methodInvocation); - } - if (!invocations.isEmpty()) { - printConnectorInvocations(invocations, curId, c); - } - } catch (Exception e) { - VConsole.error(e); - } - } - - /** - * Temporarily sets the {@code styleProperty} to {@code tempValue} and then - * resets it to its current value. Used mainly to work around rendering - * issues in IE (and possibly in other browsers) - * - * @param element - * The target element - * @param styleProperty - * The name of the property to set - * @param tempValue - * The temporary value - */ - public static void setStyleTemporarily(Element element, - final String styleProperty, String tempValue) { - final Style style = element.getStyle(); - final String currentValue = style.getProperty(styleProperty); - - style.setProperty(styleProperty, tempValue); - element.getOffsetWidth(); - style.setProperty(styleProperty, currentValue); - - } - - /** - * A helper method to return the client position from an event. Returns - * position from either first changed touch (if touch event) or from the - * event itself. - * - * @param event - * @return - */ - public static int getTouchOrMouseClientX(Event event) { - if (isTouchEvent(event)) { - return event.getChangedTouches().get(0).getClientX(); - } else { - return event.getClientX(); - } - } - - /** - * Find the element corresponding to the coordinates in the passed mouse - * event. Please note that this is not always the same as the target of the - * event e.g. if event capture is used. - * - * @param event - * the mouse event to get coordinates from - * @return the element at the coordinates of the event - */ - public static Element getElementUnderMouse(NativeEvent event) { - int pageX = getTouchOrMouseClientX(event); - int pageY = getTouchOrMouseClientY(event); - - return getElementFromPoint(pageX, pageY); - } - - /** - * A helper method to return the client position from an event. Returns - * position from either first changed touch (if touch event) or from the - * event itself. - * - * @param event - * @return - */ - public static int getTouchOrMouseClientY(Event event) { - if (isTouchEvent(event)) { - return event.getChangedTouches().get(0).getClientY(); - } else { - return event.getClientY(); - } - } - - /** - * - * @see #getTouchOrMouseClientY(Event) - * @param currentGwtEvent - * @return - */ - public static int getTouchOrMouseClientY(NativeEvent currentGwtEvent) { - return getTouchOrMouseClientY(Event.as(currentGwtEvent)); - } - - /** - * @see #getTouchOrMouseClientX(Event) - * - * @param event - * @return - */ - public static int getTouchOrMouseClientX(NativeEvent event) { - return getTouchOrMouseClientX(Event.as(event)); - } - - public static boolean isTouchEvent(Event event) { - return event.getType().contains("touch"); - } - - public static boolean isTouchEvent(NativeEvent event) { - return isTouchEvent(Event.as(event)); - } - - public static void simulateClickFromTouchEvent(Event touchevent, - Widget widget) { - Touch touch = touchevent.getChangedTouches().get(0); - final NativeEvent createMouseUpEvent = Document.get() - .createMouseUpEvent(0, touch.getScreenX(), touch.getScreenY(), - touch.getClientX(), touch.getClientY(), false, false, - false, false, NativeEvent.BUTTON_LEFT); - final NativeEvent createMouseDownEvent = Document.get() - .createMouseDownEvent(0, touch.getScreenX(), - touch.getScreenY(), touch.getClientX(), - touch.getClientY(), false, false, false, false, - NativeEvent.BUTTON_LEFT); - final NativeEvent createMouseClickEvent = Document.get() - .createClickEvent(0, touch.getScreenX(), touch.getScreenY(), - touch.getClientX(), touch.getClientY(), false, false, - false, false); - - /* - * Get target with element from point as we want the actual element, not - * the one that sunk the event. - */ - final Element target = getElementFromPoint(touch.getClientX(), - touch.getClientY()); - - /* - * Fixes infocusable form fields in Safari of iOS 5.x and some Android - * browsers. - */ - Widget targetWidget = findWidget(target, null); - if (targetWidget instanceof com.google.gwt.user.client.ui.Focusable) { - final com.google.gwt.user.client.ui.Focusable toBeFocusedWidget = (com.google.gwt.user.client.ui.Focusable) targetWidget; - toBeFocusedWidget.setFocus(true); - } else if (targetWidget instanceof Focusable) { - ((Focusable) targetWidget).focus(); - } - - Scheduler.get().scheduleDeferred(new ScheduledCommand() { - @Override - public void execute() { - try { - target.dispatchEvent(createMouseDownEvent); - target.dispatchEvent(createMouseUpEvent); - target.dispatchEvent(createMouseClickEvent); - } catch (Exception e) { - } - - } - }); - - } - - /** - * Gets the currently focused element for Internet Explorer. - * - * @return The currently focused element - */ - public native static Element getIEFocusedElement() - /*-{ - if ($wnd.document.activeElement) { - return $wnd.document.activeElement; - } - - return null; - }-*/ - ; - - /** - * Kind of stronger version of isAttached(). In addition to std isAttached, - * this method checks that this widget nor any of its parents is hidden. Can - * be e.g used to check whether component should react to some events or - * not. - * - * @param widget - * @return true if attached and displayed - */ - public static boolean isAttachedAndDisplayed(Widget widget) { - if (widget.isAttached()) { - /* - * Failfast using offset size, then by iterating the widget tree - */ - boolean notZeroSized = widget.getOffsetHeight() > 0 - || widget.getOffsetWidth() > 0; - return notZeroSized || checkVisibilityRecursively(widget); - } else { - return false; - } - } - - private static boolean checkVisibilityRecursively(Widget widget) { - if (widget.isVisible()) { - Widget parent = widget.getParent(); - if (parent == null) { - return true; // root panel - } else { - return checkVisibilityRecursively(parent); - } - } else { - return false; - } - } - - /** - * Scrolls an element into view vertically only. Modified version of - * Element.scrollIntoView. - * - * @param elem - * The element to scroll into view - */ - public static native void scrollIntoViewVertically(Element elem) - /*-{ - var top = elem.offsetTop; - var height = elem.offsetHeight; - - if (elem.parentNode != elem.offsetParent) { - top -= elem.parentNode.offsetTop; - } - - var cur = elem.parentNode; - while (cur && (cur.nodeType == 1)) { - if (top < cur.scrollTop) { - cur.scrollTop = top; - } - if (top + height > cur.scrollTop + cur.clientHeight) { - cur.scrollTop = (top + height) - cur.clientHeight; - } - - var offsetTop = cur.offsetTop; - if (cur.parentNode != cur.offsetParent) { - offsetTop -= cur.parentNode.offsetTop; - } - - top += offsetTop - cur.scrollTop; - cur = cur.parentNode; - } - }-*/; - - /** - * Checks if the given event is either a touch event or caused by the left - * mouse button - * - * @param event - * @return true if the event is a touch event or caused by the left mouse - * button, false otherwise - */ - public static boolean isTouchEventOrLeftMouseButton(Event event) { - boolean touchEvent = Util.isTouchEvent(event); - return touchEvent || event.getButton() == Event.BUTTON_LEFT; - } - - /** - * Performs a shallow comparison of the collections. - * - * @param collection1 - * The first collection - * @param collection2 - * The second collection - * @return true if the collections contain the same elements in the same - * order, false otherwise - */ - public static boolean collectionsEquals(Collection collection1, - Collection collection2) { - if (collection1 == null) { - return collection2 == null; - } - if (collection2 == null) { - return false; - } - Iterator<Object> collection1Iterator = collection1.iterator(); - Iterator<Object> collection2Iterator = collection2.iterator(); - - while (collection1Iterator.hasNext()) { - if (!collection2Iterator.hasNext()) { - return false; - } - Object collection1Object = collection1Iterator.next(); - Object collection2Object = collection2Iterator.next(); - if (collection1Object != collection2Object) { - return false; - } - } - if (collection2Iterator.hasNext()) { - return false; - } - - return true; - } - - public static String getConnectorString(ServerConnector p) { - if (p == null) { - return "null"; - } - return getSimpleName(p) + " (" + p.getConnectorId() + ")"; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/VCaption.java b/client/src/com/vaadin/terminal/gwt/client/VCaption.java deleted file mode 100644 index d6da84eb8c..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/VCaption.java +++ /dev/null @@ -1,607 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.HTML; -import com.vaadin.shared.AbstractFieldState; -import com.vaadin.shared.ComponentState; -import com.vaadin.terminal.gwt.client.ui.AbstractFieldConnector; -import com.vaadin.terminal.gwt.client.ui.Icon; - -public class VCaption extends HTML { - - public static final String CLASSNAME = "v-caption"; - - private final ComponentConnector owner; - - private Element errorIndicatorElement; - - private Element requiredFieldIndicator; - - private Icon icon; - - private Element captionText; - - private final ApplicationConnection client; - - private boolean placedAfterComponent = false; - - private int maxWidth = -1; - - private enum InsertPosition { - ICON, CAPTION, REQUIRED, ERROR - } - - private TooltipInfo tooltipInfo = null; - - /** - * Creates a caption that is not linked to a {@link ComponentConnector}. - * - * When using this constructor, {@link #getOwner()} returns null. - * - * @param client - * ApplicationConnection - * @deprecated all captions should be associated with a paintable widget and - * be updated from shared state, not UIDL - */ - @Deprecated - public VCaption(ApplicationConnection client) { - super(); - this.client = client; - owner = null; - - setStyleName(CLASSNAME); - sinkEvents(VTooltip.TOOLTIP_EVENTS); - - } - - /** - * Creates a caption for a {@link ComponentConnector}. - * - * @param component - * owner of caption, not null - * @param client - * ApplicationConnection - */ - public VCaption(ComponentConnector component, ApplicationConnection client) { - super(); - this.client = client; - owner = component; - - if (client != null && owner != null) { - setOwnerPid(getElement(), owner.getConnectorId()); - } - - setStyleName(CLASSNAME); - } - - /** - * Updates the caption from UIDL. - * - * This method may only be called when the caption has an owner - otherwise, - * use {@link #updateCaptionWithoutOwner(UIDL, String, boolean, boolean)}. - * - * @return true if the position where the caption should be placed has - * changed - */ - public boolean updateCaption() { - boolean wasPlacedAfterComponent = placedAfterComponent; - - // Caption is placed after component unless there is some part which - // moves it above. - placedAfterComponent = true; - - String style = CLASSNAME; - if (owner.getState().hasStyles()) { - for (String customStyle : owner.getState().getStyles()) { - style += " " + CLASSNAME + "-" + customStyle; - } - } - if (!owner.isEnabled()) { - style += " " + ApplicationConnection.DISABLED_CLASSNAME; - } - setStyleName(style); - - boolean hasIcon = owner.getState().getIcon() != null; - boolean showRequired = false; - boolean showError = owner.getState().getErrorMessage() != null; - if (owner.getState() instanceof AbstractFieldState) { - AbstractFieldState abstractFieldState = (AbstractFieldState) owner - .getState(); - showError = showError && !abstractFieldState.isHideErrors(); - } - if (owner instanceof AbstractFieldConnector) { - showRequired = ((AbstractFieldConnector) owner).isRequired(); - } - - if (hasIcon) { - if (icon == null) { - icon = new Icon(client); - icon.setWidth("0"); - icon.setHeight("0"); - - DOM.insertChild(getElement(), icon.getElement(), - getInsertPosition(InsertPosition.ICON)); - } - // Icon forces the caption to be above the component - placedAfterComponent = false; - - icon.setUri(owner.getState().getIcon().getURL()); - - } else if (icon != null) { - // Remove existing - DOM.removeChild(getElement(), icon.getElement()); - icon = null; - } - - if (owner.getState().getCaption() != null) { - // A caption text should be shown if the attribute is set - // If the caption is null the ATTRIBUTE_CAPTION should not be set to - // avoid ending up here. - - if (captionText == null) { - captionText = DOM.createDiv(); - captionText.setClassName("v-captiontext"); - - DOM.insertChild(getElement(), captionText, - getInsertPosition(InsertPosition.CAPTION)); - } - - // Update caption text - String c = owner.getState().getCaption(); - // A text forces the caption to be above the component. - placedAfterComponent = false; - if (c == null || c.trim().equals("")) { - // Not sure if c even can be null. Should not. - - // This is required to ensure that the caption uses space in all - // browsers when it is set to the empty string. If there is an - // icon, error indicator or required indicator they will ensure - // that space is reserved. - if (!hasIcon && !showRequired && !showError) { - captionText.setInnerHTML(" "); - } - } else { - DOM.setInnerText(captionText, c); - } - - } else if (captionText != null) { - // Remove existing - DOM.removeChild(getElement(), captionText); - captionText = null; - } - - if (owner.getState().hasDescription() && captionText != null) { - addStyleDependentName("hasdescription"); - } else { - removeStyleDependentName("hasdescription"); - } - - if (showRequired) { - if (requiredFieldIndicator == null) { - requiredFieldIndicator = DOM.createDiv(); - requiredFieldIndicator - .setClassName("v-required-field-indicator"); - DOM.setInnerText(requiredFieldIndicator, "*"); - - DOM.insertChild(getElement(), requiredFieldIndicator, - getInsertPosition(InsertPosition.REQUIRED)); - } - } else if (requiredFieldIndicator != null) { - // Remove existing - DOM.removeChild(getElement(), requiredFieldIndicator); - requiredFieldIndicator = null; - } - - if (showError) { - if (errorIndicatorElement == null) { - errorIndicatorElement = DOM.createDiv(); - DOM.setInnerHTML(errorIndicatorElement, " "); - DOM.setElementProperty(errorIndicatorElement, "className", - "v-errorindicator"); - - DOM.insertChild(getElement(), errorIndicatorElement, - getInsertPosition(InsertPosition.ERROR)); - } - } else if (errorIndicatorElement != null) { - // Remove existing - getElement().removeChild(errorIndicatorElement); - errorIndicatorElement = null; - } - - return (wasPlacedAfterComponent != placedAfterComponent); - } - - private int getInsertPosition(InsertPosition element) { - int pos = 0; - if (InsertPosition.ICON.equals(element)) { - return pos; - } - if (icon != null) { - pos++; - } - - if (InsertPosition.CAPTION.equals(element)) { - return pos; - } - - if (captionText != null) { - pos++; - } - - if (InsertPosition.REQUIRED.equals(element)) { - return pos; - } - if (requiredFieldIndicator != null) { - pos++; - } - - // if (InsertPosition.ERROR.equals(element)) { - // } - return pos; - - } - - @Deprecated - public boolean updateCaptionWithoutOwner(String caption, boolean disabled, - boolean hasDescription, boolean hasError, String iconURL) { - boolean wasPlacedAfterComponent = placedAfterComponent; - - // Caption is placed after component unless there is some part which - // moves it above. - placedAfterComponent = true; - - String style = VCaption.CLASSNAME; - if (disabled) { - style += " " + ApplicationConnection.DISABLED_CLASSNAME; - } - setStyleName(style); - if (hasDescription) { - if (captionText != null) { - addStyleDependentName("hasdescription"); - } else { - removeStyleDependentName("hasdescription"); - } - } - boolean hasIcon = iconURL != null; - - if (hasIcon) { - if (icon == null) { - icon = new Icon(client); - icon.setWidth("0"); - icon.setHeight("0"); - - DOM.insertChild(getElement(), icon.getElement(), - getInsertPosition(InsertPosition.ICON)); - } - // Icon forces the caption to be above the component - placedAfterComponent = false; - - icon.setUri(iconURL); - - } else if (icon != null) { - // Remove existing - DOM.removeChild(getElement(), icon.getElement()); - icon = null; - } - - if (caption != null) { - // A caption text should be shown if the attribute is set - // If the caption is null the ATTRIBUTE_CAPTION should not be set to - // avoid ending up here. - - if (captionText == null) { - captionText = DOM.createDiv(); - captionText.setClassName("v-captiontext"); - - DOM.insertChild(getElement(), captionText, - getInsertPosition(InsertPosition.CAPTION)); - } - - // Update caption text - // A text forces the caption to be above the component. - placedAfterComponent = false; - if (caption.trim().equals("")) { - // This is required to ensure that the caption uses space in all - // browsers when it is set to the empty string. If there is an - // icon, error indicator or required indicator they will ensure - // that space is reserved. - if (!hasIcon && !hasError) { - captionText.setInnerHTML(" "); - } - } else { - DOM.setInnerText(captionText, caption); - } - - } else if (captionText != null) { - // Remove existing - DOM.removeChild(getElement(), captionText); - captionText = null; - } - - if (hasError) { - if (errorIndicatorElement == null) { - errorIndicatorElement = DOM.createDiv(); - DOM.setInnerHTML(errorIndicatorElement, " "); - DOM.setElementProperty(errorIndicatorElement, "className", - "v-errorindicator"); - - DOM.insertChild(getElement(), errorIndicatorElement, - getInsertPosition(InsertPosition.ERROR)); - } - } else if (errorIndicatorElement != null) { - // Remove existing - getElement().removeChild(errorIndicatorElement); - errorIndicatorElement = null; - } - - return (wasPlacedAfterComponent != placedAfterComponent); - } - - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - final Element target = DOM.eventGetTarget(event); - - if (DOM.eventGetType(event) == Event.ONLOAD - && icon.getElement() == target) { - icon.setWidth(""); - icon.setHeight(""); - - // if max width defined, recalculate - if (maxWidth != -1) { - setMaxWidth(maxWidth); - } else { - String width = getElement().getStyle().getProperty("width"); - if (width != null && !width.equals("")) { - setWidth(getRequiredWidth() + "px"); - } - } - - /* - * The size of the icon might affect the size of the component so we - * must report the size change to the parent TODO consider moving - * the responsibility of reacting to ONLOAD from VCaption to layouts - */ - if (owner != null) { - Util.notifyParentOfSizeChange(owner.getWidget(), true); - } else { - VConsole.log("Warning: Icon load event was not propagated because VCaption owner is unknown."); - } - } - } - - public static boolean isNeeded(ComponentState state) { - if (state.getCaption() != null) { - return true; - } - if (state.getIcon() != null) { - return true; - } - if (state.getErrorMessage() != null) { - return true; - } - - return false; - } - - /** - * Returns Paintable for which this Caption belongs to. - * - * @return owner Widget - */ - public ComponentConnector getOwner() { - return owner; - } - - public boolean shouldBePlacedAfterComponent() { - return placedAfterComponent; - } - - public int getRenderedWidth() { - int width = 0; - - if (icon != null) { - width += Util.getRequiredWidth(icon.getElement()); - } - - if (captionText != null) { - width += Util.getRequiredWidth(captionText); - } - if (requiredFieldIndicator != null) { - width += Util.getRequiredWidth(requiredFieldIndicator); - } - if (errorIndicatorElement != null) { - width += Util.getRequiredWidth(errorIndicatorElement); - } - - return width; - - } - - public int getRequiredWidth() { - int width = 0; - - if (icon != null) { - width += Util.getRequiredWidth(icon.getElement()); - } - if (captionText != null) { - int textWidth = captionText.getScrollWidth(); - if (BrowserInfo.get().isFirefox()) { - /* - * In Firefox3 the caption might require more space than the - * scrollWidth returns as scrollWidth is rounded down. - */ - int requiredWidth = Util.getRequiredWidth(captionText); - if (requiredWidth > textWidth) { - textWidth = requiredWidth; - } - - } - width += textWidth; - } - if (requiredFieldIndicator != null) { - width += Util.getRequiredWidth(requiredFieldIndicator); - } - if (errorIndicatorElement != null) { - width += Util.getRequiredWidth(errorIndicatorElement); - } - - return width; - - } - - public int getHeight() { - int height = 0; - int h; - - if (icon != null) { - h = Util.getRequiredHeight(icon.getElement()); - if (h > height) { - height = h; - } - } - - if (captionText != null) { - h = Util.getRequiredHeight(captionText); - if (h > height) { - height = h; - } - } - if (requiredFieldIndicator != null) { - h = Util.getRequiredHeight(requiredFieldIndicator); - if (h > height) { - height = h; - } - } - if (errorIndicatorElement != null) { - h = Util.getRequiredHeight(errorIndicatorElement); - if (h > height) { - height = h; - } - } - - return height; - } - - public void setAlignment(String alignment) { - DOM.setStyleAttribute(getElement(), "textAlign", alignment); - } - - public void setMaxWidth(int maxWidth) { - this.maxWidth = maxWidth; - DOM.setStyleAttribute(getElement(), "width", maxWidth + "px"); - - if (icon != null) { - DOM.setStyleAttribute(icon.getElement(), "width", ""); - } - - if (captionText != null) { - DOM.setStyleAttribute(captionText, "width", ""); - } - - int requiredWidth = getRequiredWidth(); - /* - * ApplicationConnection.getConsole().log( "Caption maxWidth: " + - * maxWidth + ", requiredWidth: " + requiredWidth); - */ - if (requiredWidth > maxWidth) { - // Needs to truncate and clip - int availableWidth = maxWidth; - - // DOM.setStyleAttribute(getElement(), "width", maxWidth + "px"); - if (requiredFieldIndicator != null) { - availableWidth -= Util.getRequiredWidth(requiredFieldIndicator); - } - - if (errorIndicatorElement != null) { - availableWidth -= Util.getRequiredWidth(errorIndicatorElement); - } - - if (availableWidth < 0) { - availableWidth = 0; - } - - if (icon != null) { - int iconRequiredWidth = Util - .getRequiredWidth(icon.getElement()); - if (availableWidth > iconRequiredWidth) { - availableWidth -= iconRequiredWidth; - } else { - DOM.setStyleAttribute(icon.getElement(), "width", - availableWidth + "px"); - availableWidth = 0; - } - } - if (captionText != null) { - int captionWidth = Util.getRequiredWidth(captionText); - if (availableWidth > captionWidth) { - availableWidth -= captionWidth; - - } else { - DOM.setStyleAttribute(captionText, "width", availableWidth - + "px"); - availableWidth = 0; - } - - } - - } - } - - /** - * Sets the tooltip that should be shown for the caption - * - * @param tooltipInfo - * The tooltip that should be shown or null if no tooltip should - * be shown - */ - public void setTooltipInfo(TooltipInfo tooltipInfo) { - this.tooltipInfo = tooltipInfo; - } - - /** - * Returns the tooltip that should be shown for the caption - * - * @return The tooltip to show or null if no tooltip should be shown - */ - public TooltipInfo getTooltipInfo() { - return tooltipInfo; - } - - protected Element getTextElement() { - return captionText; - } - - public static String getCaptionOwnerPid(Element e) { - return getOwnerPid(e); - } - - private native static void setOwnerPid(Element el, String pid) - /*-{ - el.vOwnerPid = pid; - }-*/; - - public native static String getOwnerPid(Element el) - /*-{ - return el.vOwnerPid; - }-*/; - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/VCaptionWrapper.java b/client/src/com/vaadin/terminal/gwt/client/VCaptionWrapper.java deleted file mode 100644 index f3e1802689..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/VCaptionWrapper.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.user.client.ui.FlowPanel; - -public class VCaptionWrapper extends FlowPanel { - - public static final String CLASSNAME = "v-captionwrapper"; - VCaption caption; - ComponentConnector wrappedConnector; - - /** - * Creates a new caption wrapper panel. - * - * @param toBeWrapped - * paintable that the caption is associated with, not null - * @param client - * ApplicationConnection - */ - public VCaptionWrapper(ComponentConnector toBeWrapped, - ApplicationConnection client) { - caption = new VCaption(toBeWrapped, client); - add(caption); - wrappedConnector = toBeWrapped; - add(wrappedConnector.getWidget()); - setStyleName(CLASSNAME); - } - - public void updateCaption() { - caption.updateCaption(); - } - - public ComponentConnector getWrappedConnector() { - return wrappedConnector; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/VConsole.java b/client/src/com/vaadin/terminal/gwt/client/VConsole.java deleted file mode 100644 index 73427c5beb..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/VConsole.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import java.util.Set; - -import com.google.gwt.core.client.GWT; - -/** - * A helper class to do some client side logging. - * <p> - * This class replaces previously used loggin style: - * ApplicationConnection.getConsole().log("foo"). - * <p> - * The default widgetset provides three modes for debugging: - * <ul> - * <li>NullConsole (Default, displays no errors at all) - * <li>VDebugConsole ( Enabled by appending ?debug to url. Displays a floating - * console in the browser and also prints to browsers internal console (builtin - * or Firebug) and GWT's development mode console if available.) - * <li>VDebugConsole in quiet mode (Enabled by appending ?debug=quiet. Same as - * previous but without the console floating over application). - * </ul> - * <p> - * Implementations can be customized with GWT deferred binding by overriding - * NullConsole.class or VDebugConsole.class. This way developer can for example - * build mechanism to send client side logging data to a server. - * <p> - * Note that logging in client side is not fully optimized away even in - * production mode. Use logging moderately in production code to keep the size - * of client side engine small. An exception is {@link GWT#log(String)} style - * logging, which is available only in GWT development mode, but optimized away - * when compiled to web mode. - * - * - * TODO improve javadocs of individual methods - * - */ -public class VConsole { - private static Console impl; - - /** - * Used by ApplicationConfiguration to initialize VConsole. - * - * @param console - */ - static void setImplementation(Console console) { - impl = console; - } - - /** - * Used by ApplicationConnection to support deprecated getConsole() api. - */ - static Console getImplementation() { - return impl; - } - - public static void log(String msg) { - if (impl != null) { - impl.log(msg); - } - } - - public static void log(Throwable e) { - if (impl != null) { - impl.log(e); - } - } - - public static void error(Throwable e) { - if (impl != null) { - impl.error(e); - } - } - - public static void error(String msg) { - if (impl != null) { - impl.error(msg); - } - } - - public static void printObject(Object msg) { - if (impl != null) { - impl.printObject(msg); - } - } - - public static void dirUIDL(ValueMap u, ApplicationConnection client) { - if (impl != null) { - impl.dirUIDL(u, client); - } - } - - public static void printLayoutProblems(ValueMap meta, - ApplicationConnection applicationConnection, - Set<ComponentConnector> zeroHeightComponents, - Set<ComponentConnector> zeroWidthComponents) { - if (impl != null) { - impl.printLayoutProblems(meta, applicationConnection, - zeroHeightComponents, zeroWidthComponents); - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/VDebugConsole.java b/client/src/com/vaadin/terminal/gwt/client/VDebugConsole.java deleted file mode 100644 index 022171f2bb..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/VDebugConsole.java +++ /dev/null @@ -1,1015 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import java.util.Collection; -import java.util.Date; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.core.client.JsArray; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.FontWeight; -import com.google.gwt.dom.client.Style.Overflow; -import com.google.gwt.dom.client.Style.Position; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.MouseOutEvent; -import com.google.gwt.event.dom.client.MouseOutHandler; -import com.google.gwt.event.logical.shared.ValueChangeEvent; -import com.google.gwt.event.logical.shared.ValueChangeHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.event.shared.UmbrellaException; -import com.google.gwt.http.client.Request; -import com.google.gwt.http.client.RequestBuilder; -import com.google.gwt.http.client.RequestCallback; -import com.google.gwt.http.client.RequestException; -import com.google.gwt.http.client.Response; -import com.google.gwt.http.client.UrlBuilder; -import com.google.gwt.i18n.client.DateTimeFormat; -import com.google.gwt.storage.client.Storage; -import com.google.gwt.user.client.Cookies; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Event.NativePreviewEvent; -import com.google.gwt.user.client.Event.NativePreviewHandler; -import com.google.gwt.user.client.EventPreview; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.Window.Location; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.CheckBox; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.HorizontalPanel; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.Panel; -import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.VerticalPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.Version; -import com.vaadin.terminal.gwt.client.ui.VLazyExecutor; -import com.vaadin.terminal.gwt.client.ui.VOverlay; -import com.vaadin.terminal.gwt.client.ui.UI.UIConnector; -import com.vaadin.terminal.gwt.client.ui.notification.VNotification; -import com.vaadin.terminal.gwt.client.ui.window.WindowConnector; - -/** - * A helper console for client side development. The debug console can also be - * used to resolve layout issues, inspect the communication between browser and - * the server, start GWT dev mode and restart application. - * - * <p> - * This implementation is used vaadin is in debug mode (see manual) and - * developer appends "?debug" query parameter to url. Debug information can also - * be shown on browsers internal console only, by appending "?debug=quiet" query - * parameter. - * <p> - * This implementation can be overridden with GWT deferred binding. - * - */ -public class VDebugConsole extends VOverlay implements Console { - - private final class HighlightModeHandler implements NativePreviewHandler { - private final Label label; - - private HighlightModeHandler(Label label) { - this.label = label; - } - - @Override - public void onPreviewNativeEvent(NativePreviewEvent event) { - if (event.getTypeInt() == Event.ONKEYDOWN - && event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ESCAPE) { - highlightModeRegistration.removeHandler(); - VUIDLBrowser.deHiglight(); - return; - } - if (event.getTypeInt() == Event.ONMOUSEMOVE) { - VUIDLBrowser.deHiglight(); - Element eventTarget = Util.getElementFromPoint(event - .getNativeEvent().getClientX(), event.getNativeEvent() - .getClientY()); - if (getElement().isOrHasChild(eventTarget)) { - return; - } - - for (ApplicationConnection a : ApplicationConfiguration - .getRunningApplications()) { - ComponentConnector connector = Util.getConnectorForElement( - a, a.getRootConnector().getWidget(), eventTarget); - if (connector == null) { - connector = Util.getConnectorForElement(a, - RootPanel.get(), eventTarget); - } - if (connector != null) { - String pid = connector.getConnectorId(); - VUIDLBrowser.highlight(connector); - label.setText("Currently focused :" - + connector.getClass() + " ID:" + pid); - event.cancel(); - event.consume(); - event.getNativeEvent().stopPropagation(); - return; - } - } - } - if (event.getTypeInt() == Event.ONCLICK) { - VUIDLBrowser.deHiglight(); - event.cancel(); - event.consume(); - event.getNativeEvent().stopPropagation(); - highlightModeRegistration.removeHandler(); - Element eventTarget = Util.getElementFromPoint(event - .getNativeEvent().getClientX(), event.getNativeEvent() - .getClientY()); - for (ApplicationConnection a : ApplicationConfiguration - .getRunningApplications()) { - ComponentConnector paintable = Util.getConnectorForElement( - a, a.getRootConnector().getWidget(), eventTarget); - if (paintable == null) { - paintable = Util.getConnectorForElement(a, - RootPanel.get(), eventTarget); - } - - if (paintable != null) { - a.highlightComponent(paintable); - return; - } - } - } - event.cancel(); - } - } - - private static final String POS_COOKIE_NAME = "VDebugConsolePos"; - - private HandlerRegistration highlightModeRegistration; - - Element caption = DOM.createDiv(); - - private Panel panel; - - private Button clear = new Button("C"); - private Button restart = new Button("R"); - private Button forceLayout = new Button("FL"); - private Button analyzeLayout = new Button("AL"); - private Button savePosition = new Button("S"); - private Button highlight = new Button("H"); - private Button connectorStats = new Button("CS"); - private CheckBox devMode = new CheckBox("Dev"); - private CheckBox superDevMode = new CheckBox("SDev"); - private CheckBox autoScroll = new CheckBox("Autoscroll "); - private HorizontalPanel actions; - private boolean collapsed = false; - - private boolean resizing; - private int startX; - private int startY; - private int initialW; - private int initialH; - - private boolean moving = false; - - private int origTop; - - private int origLeft; - - private static final String help = "Drag title=move, shift-drag=resize, doubleclick title=min/max." - + "Use debug=quiet to log only to browser console."; - - private static final int DEFAULT_WIDTH = 650; - private static final int DEFAULT_HEIGHT = 400; - - public VDebugConsole() { - super(false, false); - getElement().getStyle().setOverflow(Overflow.HIDDEN); - clear.setTitle("Clear console"); - restart.setTitle("Restart app"); - forceLayout.setTitle("Force layout"); - analyzeLayout.setTitle("Analyze layouts"); - savePosition.setTitle("Save pos"); - } - - private EventPreview dragpreview = new EventPreview() { - - @Override - public boolean onEventPreview(Event event) { - onBrowserEvent(event); - return false; - } - }; - - private boolean quietMode; - - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - switch (DOM.eventGetType(event)) { - case Event.ONMOUSEDOWN: - if (DOM.eventGetShiftKey(event)) { - resizing = true; - DOM.setCapture(getElement()); - startX = DOM.eventGetScreenX(event); - startY = DOM.eventGetScreenY(event); - initialW = VDebugConsole.this.getOffsetWidth(); - initialH = VDebugConsole.this.getOffsetHeight(); - DOM.eventCancelBubble(event, true); - DOM.eventPreventDefault(event); - DOM.addEventPreview(dragpreview); - } else if (DOM.eventGetTarget(event) == caption) { - moving = true; - startX = DOM.eventGetScreenX(event); - startY = DOM.eventGetScreenY(event); - origTop = getAbsoluteTop(); - origLeft = getAbsoluteLeft(); - DOM.eventCancelBubble(event, true); - DOM.eventPreventDefault(event); - DOM.addEventPreview(dragpreview); - } - - break; - case Event.ONMOUSEMOVE: - if (resizing) { - int deltaX = startX - DOM.eventGetScreenX(event); - int detalY = startY - DOM.eventGetScreenY(event); - int w = initialW - deltaX; - if (w < 30) { - w = 30; - } - int h = initialH - detalY; - if (h < 40) { - h = 40; - } - VDebugConsole.this.setPixelSize(w, h); - DOM.eventCancelBubble(event, true); - DOM.eventPreventDefault(event); - } else if (moving) { - int deltaX = startX - DOM.eventGetScreenX(event); - int detalY = startY - DOM.eventGetScreenY(event); - int left = origLeft - deltaX; - if (left < 0) { - left = 0; - } - int top = origTop - detalY; - if (top < 0) { - top = 0; - } - VDebugConsole.this.setPopupPosition(left, top); - DOM.eventCancelBubble(event, true); - DOM.eventPreventDefault(event); - } - break; - case Event.ONLOSECAPTURE: - case Event.ONMOUSEUP: - if (resizing) { - DOM.releaseCapture(getElement()); - resizing = false; - } else if (moving) { - DOM.releaseCapture(getElement()); - moving = false; - } - DOM.removeEventPreview(dragpreview); - break; - case Event.ONDBLCLICK: - if (DOM.eventGetTarget(event) == caption) { - if (collapsed) { - panel.setVisible(true); - setToDefaultSizeAndPos(); - } else { - panel.setVisible(false); - setPixelSize(120, 20); - setPopupPosition(Window.getClientWidth() - 125, - Window.getClientHeight() - 25); - } - collapsed = !collapsed; - } - break; - default: - break; - } - - } - - private void setToDefaultSizeAndPos() { - String cookie = Cookies.getCookie(POS_COOKIE_NAME); - int width, height, top, left; - boolean autoScrollValue = false; - if (cookie != null) { - String[] split = cookie.split(","); - left = Integer.parseInt(split[0]); - top = Integer.parseInt(split[1]); - width = Integer.parseInt(split[2]); - height = Integer.parseInt(split[3]); - autoScrollValue = Boolean.valueOf(split[4]); - } else { - int windowHeight = Window.getClientHeight(); - int windowWidth = Window.getClientWidth(); - width = DEFAULT_WIDTH; - height = DEFAULT_HEIGHT; - - if (height > windowHeight / 2) { - height = windowHeight / 2; - } - if (width > windowWidth / 2) { - width = windowWidth / 2; - } - - top = windowHeight - (height + 10); - left = windowWidth - (width + 10); - } - setPixelSize(width, height); - setPopupPosition(left, top); - autoScroll.setValue(autoScrollValue); - } - - @Override - public void setPixelSize(int width, int height) { - if (height < 20) { - height = 20; - } - if (width < 2) { - width = 2; - } - panel.setHeight((height - 20) + "px"); - panel.setWidth((width - 2) + "px"); - getElement().getStyle().setWidth(width, Unit.PX); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.Console#log(java.lang.String) - */ - @Override - public void log(String msg) { - if (msg == null) { - msg = "null"; - } - msg = addTimestamp(msg); - // remoteLog(msg); - - logToDebugWindow(msg, false); - GWT.log(msg); - consoleLog(msg); - System.out.println(msg); - } - - private List<String> msgQueue = new LinkedList<String>(); - - private ScheduledCommand doSend = new ScheduledCommand() { - @Override - public void execute() { - if (!msgQueue.isEmpty()) { - RequestBuilder requestBuilder = new RequestBuilder( - RequestBuilder.POST, getRemoteLogUrl()); - try { - String requestData = ""; - for (String str : msgQueue) { - requestData += str; - requestData += "\n"; - } - requestBuilder.sendRequest(requestData, - new RequestCallback() { - - @Override - public void onResponseReceived(Request request, - Response response) { - // TODO Auto-generated method stub - - } - - @Override - public void onError(Request request, - Throwable exception) { - // TODO Auto-generated method stub - - } - }); - } catch (RequestException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - msgQueue.clear(); - } - } - - }; - private VLazyExecutor sendToRemoteLog = new VLazyExecutor(350, doSend); - - protected String getRemoteLogUrl() { - return "http://sun-vehje.local:8080/remotelog/"; - } - - protected void remoteLog(String msg) { - msgQueue.add(msg); - sendToRemoteLog.trigger(); - } - - /** - * Logs the given message to the debug window. - * - * @param msg - * The message to log. Must not be null. - */ - private void logToDebugWindow(String msg, boolean error) { - Widget row; - if (error) { - row = createErrorHtml(msg); - } else { - row = new HTML(msg); - } - panel.add(row); - if (autoScroll.getValue()) { - row.getElement().scrollIntoView(); - } - } - - private HTML createErrorHtml(String msg) { - HTML html = new HTML(msg); - html.getElement().getStyle().setColor("#f00"); - html.getElement().getStyle().setFontWeight(FontWeight.BOLD); - return html; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.Console#error(java.lang.String) - */ - @Override - public void error(String msg) { - if (msg == null) { - msg = "null"; - } - msg = addTimestamp(msg); - logToDebugWindow(msg, true); - - GWT.log(msg); - consoleErr(msg); - System.out.println(msg); - - } - - DateTimeFormat timestampFormat = DateTimeFormat.getFormat("HH:mm:ss:SSS"); - - @SuppressWarnings("deprecation") - private String addTimestamp(String msg) { - Date date = new Date(); - String timestamp = timestampFormat.format(date); - return timestamp + " " + msg; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.Console#printObject(java.lang. - * Object) - */ - @Override - public void printObject(Object msg) { - String str; - if (msg == null) { - str = "null"; - } else { - str = msg.toString(); - } - panel.add((new Label(str))); - consoleLog(str); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.Console#dirUIDL(com.vaadin - * .terminal.gwt.client.UIDL) - */ - @Override - public void dirUIDL(ValueMap u, ApplicationConnection client) { - if (panel.isAttached()) { - VUIDLBrowser vuidlBrowser = new VUIDLBrowser(u, client); - vuidlBrowser.setText("Response:"); - panel.add(vuidlBrowser); - } - consoleDir(u); - // consoleLog(u.getChildrenAsXML()); - } - - private static native void consoleDir(ValueMap u) - /*-{ - if($wnd.console && $wnd.console.log) { - if($wnd.console.dir) { - $wnd.console.dir(u); - } else { - $wnd.console.log(u); - } - } - - }-*/; - - private static native void consoleLog(String msg) - /*-{ - if($wnd.console && $wnd.console.log) { - $wnd.console.log(msg); - } - }-*/; - - private static native void consoleErr(String msg) - /*-{ - if($wnd.console) { - if ($wnd.console.error) - $wnd.console.error(msg); - else if ($wnd.console.log) - $wnd.console.log(msg); - } - }-*/; - - @Override - public void printLayoutProblems(ValueMap meta, ApplicationConnection ac, - Set<ComponentConnector> zeroHeightComponents, - Set<ComponentConnector> zeroWidthComponents) { - JsArray<ValueMap> valueMapArray = meta - .getJSValueMapArray("invalidLayouts"); - int size = valueMapArray.length(); - panel.add(new HTML("<div>************************</di>" - + "<h4>Layouts analyzed on server, total top level problems: " - + size + " </h4>")); - if (size > 0) { - SimpleTree root = new SimpleTree("Root problems"); - - for (int i = 0; i < size; i++) { - printLayoutError(valueMapArray.get(i), root, ac); - } - panel.add(root); - - } - if (zeroHeightComponents.size() > 0 || zeroWidthComponents.size() > 0) { - panel.add(new HTML("<h4> Client side notifications</h4>" - + " <em>The following relative sized components were " - + "rendered to a zero size container on the client side." - + " Note that these are not necessarily invalid " - + "states, but reported here as they might be.</em>")); - if (zeroHeightComponents.size() > 0) { - panel.add(new HTML( - "<p><strong>Vertically zero size:</strong><p>")); - printClientSideDetectedIssues(zeroHeightComponents, ac); - } - if (zeroWidthComponents.size() > 0) { - panel.add(new HTML( - "<p><strong>Horizontally zero size:</strong><p>")); - printClientSideDetectedIssues(zeroWidthComponents, ac); - } - } - log("************************"); - } - - private void printClientSideDetectedIssues( - Set<ComponentConnector> zeroHeightComponents, - ApplicationConnection ac) { - for (final ComponentConnector paintable : zeroHeightComponents) { - final ServerConnector parent = paintable.getParent(); - - VerticalPanel errorDetails = new VerticalPanel(); - errorDetails.add(new Label("" + Util.getSimpleName(paintable) - + " inside " + Util.getSimpleName(parent))); - if (parent instanceof ComponentConnector) { - ComponentConnector parentComponent = (ComponentConnector) parent; - final Widget layout = parentComponent.getWidget(); - - final CheckBox emphasisInUi = new CheckBox( - "Emphasize components parent in UI (the actual component is not visible)"); - emphasisInUi.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - Element element2 = layout.getElement(); - Widget.setStyleName(element2, "invalidlayout", - emphasisInUi.getValue().booleanValue()); - } - }); - - errorDetails.add(emphasisInUi); - } - panel.add(errorDetails); - } - } - - private void printLayoutError(ValueMap valueMap, SimpleTree root, - final ApplicationConnection ac) { - final String pid = valueMap.getString("id"); - final ComponentConnector paintable = (ComponentConnector) ConnectorMap - .get(ac).getConnector(pid); - - SimpleTree errorNode = new SimpleTree(); - VerticalPanel errorDetails = new VerticalPanel(); - errorDetails.add(new Label(Util.getSimpleName(paintable) + " id: " - + pid)); - if (valueMap.containsKey("heightMsg")) { - errorDetails.add(new Label("Height problem: " - + valueMap.getString("heightMsg"))); - } - if (valueMap.containsKey("widthMsg")) { - errorDetails.add(new Label("Width problem: " - + valueMap.getString("widthMsg"))); - } - final CheckBox emphasisInUi = new CheckBox("Emphasize component in UI"); - emphasisInUi.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - if (paintable != null) { - Element element2 = paintable.getWidget().getElement(); - Widget.setStyleName(element2, "invalidlayout", - emphasisInUi.getValue()); - } - } - }); - errorDetails.add(emphasisInUi); - errorNode.add(errorDetails); - if (valueMap.containsKey("subErrors")) { - HTML l = new HTML( - "<em>Expand this node to show problems that may be dependent on this problem.</em>"); - errorDetails.add(l); - JsArray<ValueMap> suberrors = valueMap - .getJSValueMapArray("subErrors"); - for (int i = 0; i < suberrors.length(); i++) { - ValueMap value = suberrors.get(i); - printLayoutError(value, errorNode, ac); - } - - } - root.add(errorNode); - } - - @Override - public void log(Throwable e) { - if (e instanceof UmbrellaException) { - UmbrellaException ue = (UmbrellaException) e; - for (Throwable t : ue.getCauses()) { - log(t); - } - return; - } - log(Util.getSimpleName(e) + ": " + e.getMessage()); - GWT.log(e.getMessage(), e); - } - - @Override - public void error(Throwable e) { - handleError(e, this); - } - - static void handleError(Throwable e, Console target) { - if (e instanceof UmbrellaException) { - UmbrellaException ue = (UmbrellaException) e; - for (Throwable t : ue.getCauses()) { - target.error(t); - } - return; - } - String exceptionText = Util.getSimpleName(e); - String message = e.getMessage(); - if (message != null && message.length() != 0) { - exceptionText += ": " + e.getMessage(); - } - target.error(exceptionText); - GWT.log(e.getMessage(), e); - if (!GWT.isProdMode()) { - e.printStackTrace(); - } - try { - VNotification.createNotification(VNotification.DELAY_FOREVER).show( - "<h1>Uncaught client side exception</h1><br />" - + exceptionText, VNotification.CENTERED, "error"); - } catch (Exception e2) { - // Just swallow this exception - } - } - - @Override - public void init() { - panel = new FlowPanel(); - if (!quietMode) { - DOM.appendChild(getContainerElement(), caption); - setWidget(panel); - caption.setClassName("v-debug-console-caption"); - setStyleName("v-debug-console"); - getElement().getStyle().setZIndex(20000); - getElement().getStyle().setOverflow(Overflow.HIDDEN); - - sinkEvents(Event.ONDBLCLICK); - - sinkEvents(Event.MOUSEEVENTS); - - panel.setStyleName("v-debug-console-content"); - - caption.setInnerHTML("Debug window"); - caption.getStyle().setHeight(25, Unit.PX); - caption.setTitle(help); - - show(); - setToDefaultSizeAndPos(); - - actions = new HorizontalPanel(); - Style style = actions.getElement().getStyle(); - style.setPosition(Position.ABSOLUTE); - style.setBackgroundColor("#666"); - style.setLeft(135, Unit.PX); - style.setHeight(25, Unit.PX); - style.setTop(0, Unit.PX); - - actions.add(clear); - actions.add(restart); - actions.add(forceLayout); - actions.add(analyzeLayout); - actions.add(highlight); - actions.add(connectorStats); - connectorStats.setTitle("Show connector statistics for client"); - highlight - .setTitle("Select a component and print details about it to the server log and client side console."); - actions.add(savePosition); - savePosition - .setTitle("Saves the position and size of debug console to a cookie"); - actions.add(autoScroll); - addDevMode(); - addSuperDevMode(); - - autoScroll - .setTitle("Automatically scroll so that new messages are visible"); - - panel.add(actions); - - panel.add(new HTML("<i>" + help + "</i>")); - - clear.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - int width = panel.getOffsetWidth(); - int height = panel.getOffsetHeight(); - panel = new FlowPanel(); - panel.setPixelSize(width, height); - panel.setStyleName("v-debug-console-content"); - panel.add(actions); - setWidget(panel); - } - }); - - restart.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - - String queryString = Window.Location.getQueryString(); - if (queryString != null - && queryString.contains("restartApplications")) { - Window.Location.reload(); - } else { - String url = Location.getHref(); - String separator = "?"; - if (url.contains("?")) { - separator = "&"; - } - if (!url.contains("restartApplication")) { - url += separator; - url += "restartApplication"; - } - if (!"".equals(Location.getHash())) { - String hash = Location.getHash(); - url = url.replace(hash, "") + hash; - } - Window.Location.replace(url); - } - - } - }); - - forceLayout.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - for (ApplicationConnection applicationConnection : ApplicationConfiguration - .getRunningApplications()) { - applicationConnection.forceLayout(); - } - } - }); - - analyzeLayout.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - List<ApplicationConnection> runningApplications = ApplicationConfiguration - .getRunningApplications(); - for (ApplicationConnection applicationConnection : runningApplications) { - applicationConnection.analyzeLayouts(); - } - } - }); - analyzeLayout - .setTitle("Analyzes currently rendered view and " - + "reports possible common problems in usage of relative sizes." - + "Will cause server visit/rendering of whole screen and loss of" - + " all non committed variables form client side."); - - savePosition.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - String pos = getAbsoluteLeft() + "," + getAbsoluteTop() - + "," + getOffsetWidth() + "," + getOffsetHeight() - + "," + autoScroll.getValue(); - Cookies.setCookie(POS_COOKIE_NAME, pos); - } - }); - - highlight.addClickHandler(new ClickHandler() { - - @Override - public void onClick(ClickEvent event) { - final Label label = new Label("--"); - log("<i>Use mouse to select a component or click ESC to exit highlight mode.</i>"); - panel.add(label); - highlightModeRegistration = Event - .addNativePreviewHandler(new HighlightModeHandler( - label)); - - } - }); - - } - connectorStats.addClickHandler(new ClickHandler() { - - @Override - public void onClick(ClickEvent event) { - for (ApplicationConnection a : ApplicationConfiguration - .getRunningApplications()) { - dumpConnectorInfo(a); - } - } - }); - log("Starting Vaadin client side engine. Widgetset: " - + GWT.getModuleName()); - - log("Widget set is built on version: " + Version.getFullVersion()); - - logToDebugWindow("<div class=\"v-theme-version v-theme-version-" - + Version.getFullVersion().replaceAll("\\.", "_") - + "\">Warning: widgetset version " + Version.getFullVersion() - + " does not seem to match theme version </div>", true); - - } - - private void addSuperDevMode() { - final Storage sessionStorage = Storage.getSessionStorageIfSupported(); - if (sessionStorage == null) { - return; - } - actions.add(superDevMode); - if (Location.getParameter("superdevmode") != null) { - superDevMode.setValue(true); - } - superDevMode.addValueChangeHandler(new ValueChangeHandler<Boolean>() { - - @Override - public void onValueChange(ValueChangeEvent<Boolean> event) { - SuperDevMode.redirect(event.getValue()); - } - - }); - - } - - private void addDevMode() { - actions.add(devMode); - if (Location.getParameter("gwt.codesvr") != null) { - devMode.setValue(true); - } - devMode.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - if (devMode.getValue()) { - addHMParameter(); - } else { - removeHMParameter(); - } - } - - private void addHMParameter() { - UrlBuilder createUrlBuilder = Location.createUrlBuilder(); - createUrlBuilder.setParameter("gwt.codesvr", "localhost:9997"); - Location.assign(createUrlBuilder.buildString()); - } - - private void removeHMParameter() { - UrlBuilder createUrlBuilder = Location.createUrlBuilder(); - createUrlBuilder.removeParameter("gwt.codesvr"); - Location.assign(createUrlBuilder.buildString()); - - } - }); - } - - protected void dumpConnectorInfo(ApplicationConnection a) { - UIConnector root = a.getRootConnector(); - log("================"); - log("Connector hierarchy for Root: " + root.getState().getCaption() - + " (" + root.getConnectorId() + ")"); - Set<ServerConnector> connectorsInHierarchy = new HashSet<ServerConnector>(); - SimpleTree rootHierachy = dumpConnectorHierarchy(root, "", - connectorsInHierarchy); - if (panel.isAttached()) { - rootHierachy.open(true); - panel.add(rootHierachy); - } - - ConnectorMap connectorMap = a.getConnectorMap(); - Collection<? extends ServerConnector> registeredConnectors = connectorMap - .getConnectors(); - log("Sub windows:"); - Set<ServerConnector> subWindowHierarchyConnectors = new HashSet<ServerConnector>(); - for (WindowConnector wc : root.getSubWindows()) { - SimpleTree windowHierachy = dumpConnectorHierarchy(wc, "", - subWindowHierarchyConnectors); - if (panel.isAttached()) { - windowHierachy.open(true); - panel.add(windowHierachy); - } - } - log("Registered connectors not in hierarchy (should be empty):"); - for (ServerConnector registeredConnector : registeredConnectors) { - - if (connectorsInHierarchy.contains(registeredConnector)) { - continue; - } - - if (subWindowHierarchyConnectors.contains(registeredConnector)) { - continue; - } - error(getConnectorString(registeredConnector)); - - } - log("Unregistered connectors in hierarchy (should be empty):"); - for (ServerConnector hierarchyConnector : connectorsInHierarchy) { - if (!connectorMap.hasConnector(hierarchyConnector.getConnectorId())) { - error(getConnectorString(hierarchyConnector)); - } - - } - - log("================"); - - } - - private SimpleTree dumpConnectorHierarchy(final ServerConnector connector, - String indent, Set<ServerConnector> connectors) { - SimpleTree simpleTree = new SimpleTree(getConnectorString(connector)) { - @Override - protected void select(ClickEvent event) { - super.select(event); - if (connector instanceof ComponentConnector) { - VUIDLBrowser.highlight((ComponentConnector) connector); - } - } - }; - simpleTree.addDomHandler(new MouseOutHandler() { - @Override - public void onMouseOut(MouseOutEvent event) { - VUIDLBrowser.deHiglight(); - } - }, MouseOutEvent.getType()); - connectors.add(connector); - - String msg = indent + "* " + getConnectorString(connector); - GWT.log(msg); - consoleLog(msg); - System.out.println(msg); - - for (ServerConnector c : connector.getChildren()) { - simpleTree.add(dumpConnectorHierarchy(c, indent + " ", connectors)); - } - return simpleTree; - } - - private static String getConnectorString(ServerConnector connector) { - return Util.getConnectorString(connector); - } - - @Override - public void setQuietMode(boolean quietDebugMode) { - quietMode = quietDebugMode; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/VErrorMessage.java b/client/src/com/vaadin/terminal/gwt/client/VErrorMessage.java deleted file mode 100644 index af94241361..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/VErrorMessage.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.HTML; -import com.vaadin.terminal.gwt.client.ui.VOverlay; - -public class VErrorMessage extends FlowPanel { - public static final String CLASSNAME = "v-errormessage"; - - public VErrorMessage() { - super(); - setStyleName(CLASSNAME); - } - - public void updateMessage(String htmlErrorMessage) { - clear(); - if (htmlErrorMessage == null || htmlErrorMessage.length() == 0) { - add(new HTML(" ")); - } else { - // pre-formatted on the server as div per child - add(new HTML(htmlErrorMessage)); - } - } - - /** - * Shows this error message next to given element. - * - * @param indicatorElement - */ - public void showAt(Element indicatorElement) { - VOverlay errorContainer = (VOverlay) getParent(); - if (errorContainer == null) { - errorContainer = new VOverlay(); - errorContainer.setWidget(this); - } - errorContainer.setPopupPosition( - DOM.getAbsoluteLeft(indicatorElement) - + 2 - * DOM.getElementPropertyInt(indicatorElement, - "offsetHeight"), - DOM.getAbsoluteTop(indicatorElement) - + 2 - * DOM.getElementPropertyInt(indicatorElement, - "offsetHeight")); - errorContainer.show(); - - } - - public void hide() { - final VOverlay errorContainer = (VOverlay) getParent(); - if (errorContainer != null) { - errorContainer.hide(); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/VSchedulerImpl.java b/client/src/com/vaadin/terminal/gwt/client/VSchedulerImpl.java deleted file mode 100644 index 56dec16289..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/VSchedulerImpl.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.core.client.impl.SchedulerImpl; - -public class VSchedulerImpl extends SchedulerImpl { - - /** - * Keeps track of if there are deferred commands that are being executed. 0 - * == no deferred commands currently in progress, > 0 otherwise. - */ - private int deferredCommandTrackers = 0; - - @Override - public void scheduleDeferred(ScheduledCommand cmd) { - deferredCommandTrackers++; - super.scheduleDeferred(cmd); - super.scheduleDeferred(new ScheduledCommand() { - - @Override - public void execute() { - deferredCommandTrackers--; - } - }); - } - - public boolean hasWorkQueued() { - boolean hasWorkQueued = (deferredCommandTrackers != 0); - return hasWorkQueued; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/VTooltip.java b/client/src/com/vaadin/terminal/gwt/client/VTooltip.java deleted file mode 100644 index 1b9321fb16..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/VTooltip.java +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.MouseMoveEvent; -import com.google.gwt.event.dom.client.MouseMoveHandler; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ui.VOverlay; - -/** - * TODO open for extension - */ -public class VTooltip extends VOverlay { - private static final String CLASSNAME = "v-tooltip"; - private static final int MARGIN = 4; - public static final int TOOLTIP_EVENTS = Event.ONKEYDOWN - | Event.ONMOUSEOVER | Event.ONMOUSEOUT | Event.ONMOUSEMOVE - | Event.ONCLICK; - protected static final int MAX_WIDTH = 500; - private static final int QUICK_OPEN_TIMEOUT = 1000; - private static final int CLOSE_TIMEOUT = 300; - private static final int OPEN_DELAY = 750; - private static final int QUICK_OPEN_DELAY = 100; - VErrorMessage em = new VErrorMessage(); - Element description = DOM.createDiv(); - - private boolean closing = false; - private boolean opening = false; - private ApplicationConnection ac; - // Open next tooltip faster. Disabled after 2 sec of showTooltip-silence. - private boolean justClosed = false; - - public VTooltip(ApplicationConnection client) { - super(false, false, true); - ac = client; - setStyleName(CLASSNAME); - FlowPanel layout = new FlowPanel(); - setWidget(layout); - layout.add(em); - DOM.setElementProperty(description, "className", CLASSNAME + "-text"); - DOM.appendChild(layout.getElement(), description); - setSinkShadowEvents(true); - } - - /** - * Show a popup containing the information in the "info" tooltip - * - * @param info - */ - private void show(TooltipInfo info) { - boolean hasContent = false; - if (info.getErrorMessage() != null) { - em.setVisible(true); - em.updateMessage(info.getErrorMessage()); - hasContent = true; - } else { - em.setVisible(false); - } - if (info.getTitle() != null && !"".equals(info.getTitle())) { - DOM.setInnerHTML(description, info.getTitle()); - DOM.setStyleAttribute(description, "display", ""); - hasContent = true; - } else { - DOM.setInnerHTML(description, ""); - DOM.setStyleAttribute(description, "display", "none"); - } - if (hasContent) { - // Issue #8454: With IE7 the tooltips size is calculated based on - // the last tooltip's position, causing problems if the last one was - // in the right or bottom edge. For this reason the tooltip is moved - // first to 0,0 position so that the calculation goes correctly. - setPopupPosition(0, 0); - setPopupPositionAndShow(new PositionCallback() { - @Override - public void setPosition(int offsetWidth, int offsetHeight) { - - if (offsetWidth > MAX_WIDTH) { - setWidth(MAX_WIDTH + "px"); - - // Check new height and width with reflowed content - offsetWidth = getOffsetWidth(); - offsetHeight = getOffsetHeight(); - } - - int x = tooltipEventMouseX + 10 + Window.getScrollLeft(); - int y = tooltipEventMouseY + 10 + Window.getScrollTop(); - - if (x + offsetWidth + MARGIN - Window.getScrollLeft() > Window - .getClientWidth()) { - x = Window.getClientWidth() - offsetWidth - MARGIN; - } - - if (y + offsetHeight + MARGIN - Window.getScrollTop() > Window - .getClientHeight()) { - y = tooltipEventMouseY - 5 - offsetHeight; - if (y - Window.getScrollTop() < 0) { - // tooltip does not fit on top of the mouse either, - // put it at the top of the screen - y = Window.getScrollTop(); - } - } - - setPopupPosition(x, y); - sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT); - } - }); - } else { - hide(); - } - } - - private void showTooltip() { - - // Close current tooltip - if (isShowing()) { - closeNow(); - } - - // Schedule timer for showing the tooltip according to if it was - // recently closed or not. - int timeout = justClosed ? QUICK_OPEN_DELAY : OPEN_DELAY; - showTimer.schedule(timeout); - opening = true; - } - - private void closeNow() { - hide(); - setWidth(""); - closing = false; - } - - private Timer showTimer = new Timer() { - @Override - public void run() { - TooltipInfo info = tooltipEventHandler.getTooltipInfo(); - if (null != info) { - show(info); - } - opening = false; - } - }; - - private Timer closeTimer = new Timer() { - @Override - public void run() { - closeNow(); - justClosedTimer.schedule(2000); - justClosed = true; - } - }; - - private Timer justClosedTimer = new Timer() { - @Override - public void run() { - justClosed = false; - } - }; - - public void hideTooltip() { - if (opening) { - showTimer.cancel(); - opening = false; - } - if (!isAttached()) { - return; - } - if (closing) { - // already about to close - return; - } - closeTimer.schedule(CLOSE_TIMEOUT); - closing = true; - justClosed = true; - justClosedTimer.schedule(QUICK_OPEN_TIMEOUT); - - } - - private int tooltipEventMouseX; - private int tooltipEventMouseY; - - public void updatePosition(Event event) { - tooltipEventMouseX = DOM.eventGetClientX(event); - tooltipEventMouseY = DOM.eventGetClientY(event); - } - - @Override - public void onBrowserEvent(Event event) { - final int type = DOM.eventGetType(event); - // cancel closing event if tooltip is mouseovered; the user might want - // to scroll of cut&paste - - if (type == Event.ONMOUSEOVER) { - // Cancel closing so tooltip stays open and user can copy paste the - // tooltip - closeTimer.cancel(); - closing = false; - } - } - - /** - * Replace current open tooltip with new content - */ - public void replaceCurrentTooltip() { - if (closing) { - closeTimer.cancel(); - closeNow(); - } - - TooltipInfo info = tooltipEventHandler.getTooltipInfo(); - if (null != info) { - show(info); - } - opening = false; - } - - private class TooltipEventHandler implements MouseMoveHandler, - ClickHandler, KeyDownHandler { - - /** - * Current element hovered - */ - private com.google.gwt.dom.client.Element currentElement = null; - - /** - * Current tooltip active - */ - private TooltipInfo currentTooltipInfo = null; - - /** - * Get current active tooltip information - * - * @return Current active tooltip information or null - */ - public TooltipInfo getTooltipInfo() { - return currentTooltipInfo; - } - - /** - * Locate connector and it's tooltip for given element - * - * @param element - * Element used in search - * @return true if connector and tooltip found - */ - private boolean resolveConnector(Element element) { - - ComponentConnector connector = Util.getConnectorForElement(ac, - RootPanel.get(), element); - - // Try to find first connector with proper tooltip info - TooltipInfo info = null; - while (connector != null) { - - info = connector.getTooltipInfo(element); - - if (info != null && info.hasMessage()) { - break; - } - - if (!(connector.getParent() instanceof ComponentConnector)) { - connector = null; - info = null; - break; - } - connector = (ComponentConnector) connector.getParent(); - } - - if (connector != null && info != null) { - currentTooltipInfo = info; - return true; - } - - return false; - } - - /** - * Handle hide event - * - * @param event - * Event causing hide - */ - private void handleHideEvent() { - hideTooltip(); - currentTooltipInfo = null; - } - - @Override - public void onMouseMove(MouseMoveEvent mme) { - Event event = Event.as(mme.getNativeEvent()); - com.google.gwt.dom.client.Element element = Element.as(event - .getEventTarget()); - - // We can ignore move event if it's handled by move or over already - if (currentElement == element) { - return; - } - currentElement = element; - - boolean connectorAndTooltipFound = resolveConnector((com.google.gwt.user.client.Element) element); - if (!connectorAndTooltipFound) { - if (isShowing()) { - handleHideEvent(); - } else { - currentTooltipInfo = null; - } - } else { - updatePosition(event); - if (isShowing()) { - replaceCurrentTooltip(); - } else { - showTooltip(); - } - } - } - - @Override - public void onClick(ClickEvent event) { - handleHideEvent(); - } - - @Override - public void onKeyDown(KeyDownEvent event) { - handleHideEvent(); - } - } - - private final TooltipEventHandler tooltipEventHandler = new TooltipEventHandler(); - - /** - * Connects DOM handlers to widget that are needed for tooltip presentation. - * - * @param widget - * Widget which DOM handlers are connected - */ - public void connectHandlersToWidget(Widget widget) { - widget.addDomHandler(tooltipEventHandler, MouseMoveEvent.getType()); - widget.addDomHandler(tooltipEventHandler, ClickEvent.getType()); - widget.addDomHandler(tooltipEventHandler, KeyDownEvent.getType()); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/VUIDLBrowser.java b/client/src/com/vaadin/terminal/gwt/client/VUIDLBrowser.java deleted file mode 100644 index 3cdc03ee86..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/VUIDLBrowser.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client; - -import java.util.Iterator; -import java.util.Set; - -import com.google.gwt.core.client.JsArray; -import com.google.gwt.core.client.JsArrayString; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Position; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.MouseOutEvent; -import com.google.gwt.event.dom.client.MouseOutHandler; -import com.google.gwt.json.client.JSONArray; -import com.google.gwt.json.client.JSONObject; -import com.google.gwt.json.client.JSONValue; -import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.Connector; -import com.vaadin.terminal.gwt.client.ui.UnknownComponentConnector; -import com.vaadin.terminal.gwt.client.ui.window.VWindow; - -/** - * TODO Rename to something more Vaadin7-ish? - */ -public class VUIDLBrowser extends SimpleTree { - private static final String HELP = "Shift click handle to open recursively. " - + " Click components to highlight them on client side." - + " Shift click components to highlight them also on the server side."; - private ApplicationConnection client; - private String highlightedPid; - - public VUIDLBrowser(final UIDL uidl, ApplicationConnection client) { - this.client = client; - final UIDLItem root = new UIDLItem(uidl); - add(root); - } - - public VUIDLBrowser(ValueMap u, ApplicationConnection client) { - this.client = client; - ValueMap valueMap = u.getValueMap("meta"); - if (valueMap.containsKey("hl")) { - highlightedPid = valueMap.getString("hl"); - } - Set<String> keySet = u.getKeySet(); - for (String key : keySet) { - if (key.equals("state")) { - ValueMap stateJson = u.getValueMap(key); - SimpleTree stateChanges = new SimpleTree("shared state"); - - for (String connectorId : stateJson.getKeySet()) { - stateChanges.add(new SharedStateItem(connectorId, stateJson - .getValueMap(connectorId))); - } - add(stateChanges); - - } else if (key.equals("changes")) { - JsArray<UIDL> jsValueMapArray = u.getJSValueMapArray(key) - .cast(); - for (int i = 0; i < jsValueMapArray.length(); i++) { - UIDL uidl = jsValueMapArray.get(i); - UIDLItem change = new UIDLItem(uidl); - change.setTitle("change " + i); - add(change); - } - } else if (key.equals("meta")) { - - } else { - // TODO consider pretty printing other request data such as - // hierarchy changes - // addItem(key + " : " + u.getAsString(key)); - } - } - open(highlightedPid != null); - setTitle(HELP); - } - - /** - * A debug view of a server-originated component state change. - */ - abstract class StateChangeItem extends SimpleTree { - - protected StateChangeItem() { - setTitle(HELP); - - addDomHandler(new MouseOutHandler() { - @Override - public void onMouseOut(MouseOutEvent event) { - deHiglight(); - } - }, MouseOutEvent.getType()); - } - - @Override - protected void select(ClickEvent event) { - ComponentConnector connector = getConnector(); - highlight(connector); - if (event != null && event.getNativeEvent().getShiftKey()) { - connector.getConnection().highlightComponent(connector); - } - super.select(event); - } - - /** - * Returns the Connector associated with this state change. - */ - protected ComponentConnector getConnector() { - Connector connector = client.getConnectorMap().getConnector( - getConnectorId()); - - if (connector instanceof ComponentConnector) { - return (ComponentConnector) connector; - } else { - return null; - } - } - - protected abstract String getConnectorId(); - } - - /** - * A debug view of a Vaadin 7 style shared state change. - */ - class SharedStateItem extends StateChangeItem { - - private String connectorId; - - SharedStateItem(String connectorId, ValueMap stateChanges) { - this.connectorId = connectorId; - ComponentConnector connector = getConnector(); - if (connector != null) { - setText(Util.getConnectorString(connector)); - } else { - setText("Unknown connector " + connectorId); - } - dir(new JSONObject(stateChanges), this); - } - - @Override - protected String getConnectorId() { - return connectorId; - } - - private void dir(String key, JSONValue value, SimpleTree tree) { - if (value.isObject() != null) { - SimpleTree subtree = new SimpleTree(key + "=object"); - tree.add(subtree); - dir(value.isObject(), subtree); - } else if (value.isArray() != null) { - SimpleTree subtree = new SimpleTree(key + "=array"); - dir(value.isArray(), subtree); - tree.add(subtree); - } else { - tree.addItem(key + "=" + value); - } - } - - private void dir(JSONObject state, SimpleTree tree) { - for (String key : state.keySet()) { - dir(key, state.get(key), tree); - } - } - - private void dir(JSONArray array, SimpleTree tree) { - for (int i = 0; i < array.size(); ++i) { - dir("" + i, array.get(i), tree); - } - } - } - - /** - * A debug view of a Vaadin 6 style hierarchical component state change. - */ - class UIDLItem extends StateChangeItem { - - private UIDL uidl; - - UIDLItem(UIDL uidl) { - this.uidl = uidl; - try { - String name = uidl.getTag(); - try { - name = getNodeName(uidl, client.getConfiguration(), - Integer.parseInt(name)); - } catch (Exception e) { - // NOP - } - setText(name); - addItem("LOADING"); - } catch (Exception e) { - setText(uidl.toString()); - } - } - - @Override - protected String getConnectorId() { - return uidl.getId(); - } - - private String getNodeName(UIDL uidl, ApplicationConfiguration conf, - int tag) { - Class<? extends ServerConnector> widgetClassByDecodedTag = conf - .getConnectorClassByEncodedTag(tag); - if (widgetClassByDecodedTag == UnknownComponentConnector.class) { - return conf.getUnknownServerClassNameByTag(tag) - + "(NO CLIENT IMPLEMENTATION FOUND)"; - } else { - return widgetClassByDecodedTag.getName(); - } - } - - @Override - public void open(boolean recursive) { - if (getWidgetCount() == 1 - && getWidget(0).getElement().getInnerText() - .equals("LOADING")) { - dir(); - } - super.open(recursive); - } - - public void dir() { - remove(0); - - String nodeName = uidl.getTag(); - try { - nodeName = getNodeName(uidl, client.getConfiguration(), - Integer.parseInt(nodeName)); - } catch (Exception e) { - // NOP - } - - Set<String> attributeNames = uidl.getAttributeNames(); - for (String name : attributeNames) { - if (uidl.isMapAttribute(name)) { - try { - ValueMap map = uidl.getMapAttribute(name); - JsArrayString keyArray = map.getKeyArray(); - nodeName += " " + name + "=" + "{"; - for (int i = 0; i < keyArray.length(); i++) { - nodeName += keyArray.get(i) + ":" - + map.getAsString(keyArray.get(i)) + ","; - } - nodeName += "}"; - } catch (Exception e) { - - } - } else { - final String value = uidl.getAttribute(name); - nodeName += " " + name + "=" + value; - } - } - setText(nodeName); - - try { - SimpleTree tmp = null; - Set<String> variableNames = uidl.getVariableNames(); - for (String name : variableNames) { - String value = ""; - try { - value = uidl.getVariable(name); - } catch (final Exception e) { - try { - String[] stringArrayAttribute = uidl - .getStringArrayAttribute(name); - value = stringArrayAttribute.toString(); - } catch (final Exception e2) { - try { - final int intVal = uidl.getIntVariable(name); - value = String.valueOf(intVal); - } catch (final Exception e3) { - value = "unknown"; - } - } - } - if (tmp == null) { - tmp = new SimpleTree("variables"); - } - tmp.addItem(name + "=" + value); - } - if (tmp != null) { - add(tmp); - } - } catch (final Exception e) { - // Ignored, no variables - } - - final Iterator<Object> i = uidl.getChildIterator(); - while (i.hasNext()) { - final Object child = i.next(); - try { - add(new UIDLItem((UIDL) child)); - } catch (final Exception e) { - addItem(child.toString()); - } - } - if (highlightedPid != null && highlightedPid.equals(uidl.getId())) { - getElement().getStyle().setBackgroundColor("#fdd"); - Scheduler.get().scheduleDeferred(new ScheduledCommand() { - @Override - public void execute() { - getElement().scrollIntoView(); - } - }); - } - } - } - - static Element highlight = Document.get().createDivElement(); - - static { - Style style = highlight.getStyle(); - style.setPosition(Position.ABSOLUTE); - style.setZIndex(VWindow.Z_INDEX + 1000); - style.setBackgroundColor("red"); - style.setOpacity(0.2); - if (BrowserInfo.get().isIE()) { - style.setProperty("filter", "alpha(opacity=20)"); - } - } - - static void highlight(ComponentConnector paintable) { - if (paintable != null) { - Widget w = paintable.getWidget(); - Style style = highlight.getStyle(); - style.setTop(w.getAbsoluteTop(), Unit.PX); - style.setLeft(w.getAbsoluteLeft(), Unit.PX); - style.setWidth(w.getOffsetWidth(), Unit.PX); - style.setHeight(w.getOffsetHeight(), Unit.PX); - RootPanel.getBodyElement().appendChild(highlight); - } - } - - static void deHiglight() { - if (highlight.getParentElement() != null) { - highlight.getParentElement().removeChild(highlight); - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ValueMap.java b/client/src/com/vaadin/terminal/gwt/client/ValueMap.java deleted file mode 100644 index bade480e7c..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ValueMap.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client; - -import java.util.HashSet; -import java.util.Set; - -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.JsArray; -import com.google.gwt.core.client.JsArrayString; - -public final class ValueMap extends JavaScriptObject { - protected ValueMap() { - } - - public native double getRawNumber(final String name) - /*-{ - return this[name]; - }-*/; - - public native int getInt(final String name) - /*-{ - return this[name]; - }-*/; - - public native boolean getBoolean(final String name) - /*-{ - return Boolean(this[name]); - }-*/; - - public native String getString(String name) - /*-{ - return this[name]; - }-*/; - - public native JsArrayString getKeyArray() - /*-{ - var a = new Array(); - var attr = this; - for(var j in attr) { - // workaround for the infamous chrome hosted mode hack (__gwt_ObjectId) - if(attr.hasOwnProperty(j)) - a.push(j); - } - return a; - }-*/; - - public Set<String> getKeySet() { - final HashSet<String> attrs = new HashSet<String>(); - JsArrayString attributeNamesArray = getKeyArray(); - for (int i = 0; i < attributeNamesArray.length(); i++) { - attrs.add(attributeNamesArray.get(i)); - } - return attrs; - } - - native JsArrayString getJSStringArray(String name) - /*-{ - return this[name]; - }-*/; - - native JsArray<ValueMap> getJSValueMapArray(String name) - /*-{ - return this[name]; - }-*/; - - public String[] getStringArray(final String name) { - JsArrayString stringArrayAttribute = getJSStringArray(name); - final String[] s = new String[stringArrayAttribute.length()]; - for (int i = 0; i < stringArrayAttribute.length(); i++) { - s[i] = stringArrayAttribute.get(i); - } - return s; - } - - public int[] getIntArray(final String name) { - JsArrayString stringArrayAttribute = getJSStringArray(name); - final int[] s = new int[stringArrayAttribute.length()]; - for (int i = 0; i < stringArrayAttribute.length(); i++) { - s[i] = Integer.parseInt(stringArrayAttribute.get(i)); - } - return s; - } - - public native boolean containsKey(final String name) - /*-{ - return name in this; - }-*/; - - public native ValueMap getValueMap(String name) - /*-{ - return this[name]; - }-*/; - - native String getAsString(String name) - /*-{ - return '' + this[name]; - }-*/; - - native JavaScriptObject getJavaScriptObject(String name) - /*-{ - return this[name]; - }-*/; - -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/WidgetInstantiator.java b/client/src/com/vaadin/terminal/gwt/client/WidgetInstantiator.java deleted file mode 100644 index 347a8dd631..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/WidgetInstantiator.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -/** - * A helper class used by WidgetMap implementation. Used by the generated code. - */ -interface WidgetInstantiator { - public ServerConnector get(); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/WidgetLoader.java b/client/src/com/vaadin/terminal/gwt/client/WidgetLoader.java deleted file mode 100644 index e98aa031c4..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/WidgetLoader.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.core.client.RunAsyncCallback; - -/** A helper class used by WidgetMap implementation. Used by the generated code. */ -abstract class WidgetLoader implements RunAsyncCallback { - - @Override - public void onFailure(Throwable reason) { - ApplicationConfiguration.endDependencyLoading(); - } - - @Override - public void onSuccess() { - addInstantiator(); - ApplicationConfiguration.endDependencyLoading(); - } - - abstract void addInstantiator(); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/WidgetMap.java b/client/src/com/vaadin/terminal/gwt/client/WidgetMap.java deleted file mode 100644 index 4c929714c3..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/WidgetMap.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client; - -import java.util.HashMap; - -/** - * Abstract class mapping between {@link ComponentConnector} instances and their - * instances. - * - * A concrete implementation of this class is generated by WidgetMapGenerator or - * one of its subclasses during widgetset compilation. - */ -abstract class WidgetMap { - - protected static HashMap<Class<? extends ServerConnector>, WidgetInstantiator> instmap = new HashMap<Class<? extends ServerConnector>, WidgetInstantiator>(); - - /** - * Create a new instance of a connector based on its type. - * - * @param classType - * {@link ComponentConnector} class to instantiate - * @return new instance of the connector - */ - public ServerConnector instantiate( - Class<? extends ServerConnector> classType) { - return instmap.get(classType).get(); - } - - /** - * Return the connector class to use for a fully qualified server side - * component class name. - * - * @param fullyqualifiedName - * fully qualified name of the server side component class - * @return component connector class to use - */ - public abstract Class<? extends ServerConnector> getConnectorClassForServerSideClassName( - String fullyqualifiedName); - - /** - * Return the connector classes to load after the initial widgetset load and - * start. - * - * @return component connector class to load after the initial widgetset - * loading - */ - public abstract Class<? extends ServerConnector>[] getDeferredLoadedConnectors(); - - /** - * Make sure the code for a (deferred or lazy) component connector type has - * been loaded, triggering the load and waiting for its completion if - * necessary. - * - * @param classType - * component connector class - */ - public abstract void ensureInstantiator( - Class<? extends ServerConnector> classType); - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/WidgetSet.java b/client/src/com/vaadin/terminal/gwt/client/WidgetSet.java deleted file mode 100644 index 8245371161..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/WidgetSet.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client; - -import com.google.gwt.core.client.GWT; -import com.vaadin.terminal.gwt.client.communication.HasJavaScriptConnectorHelper; -import com.vaadin.terminal.gwt.client.metadata.BundleLoadCallback; -import com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader; -import com.vaadin.terminal.gwt.client.metadata.NoDataException; -import com.vaadin.terminal.gwt.client.metadata.TypeData; -import com.vaadin.terminal.gwt.client.ui.UnknownComponentConnector; - -public class WidgetSet { - /** - * Create an uninitialized connector that best matches given UIDL. The - * connector must implement {@link ServerConnector}. - * - * @param tag - * connector type tag for the connector to create - * @param conf - * the application configuration to use when creating the - * connector - * - * @return New uninitialized and unregistered connector that can paint given - * UIDL. - */ - public ServerConnector createConnector(int tag, - ApplicationConfiguration conf) { - /* - * Yes, this (including the generated code in WidgetMap) may look very - * odd code, but due the nature of GWT, we cannot do this any cleaner. - * Luckily this is mostly written by WidgetSetGenerator, here are just - * some hacks. Extra instantiation code is needed if client side - * connector has no "native" counterpart on client side. - */ - - Class<? extends ServerConnector> classType = resolveInheritedConnectorType( - conf, tag); - - if (classType == null || classType == UnknownComponentConnector.class) { - String serverSideName = conf.getUnknownServerClassNameByTag(tag); - UnknownComponentConnector c = GWT - .create(UnknownComponentConnector.class); - c.setServerSideClassName(serverSideName); - return c; - } else { - /* - * let the auto generated code instantiate this type - */ - try { - ServerConnector connector = (ServerConnector) TypeData.getType( - classType).createInstance(); - if (connector instanceof HasJavaScriptConnectorHelper) { - ((HasJavaScriptConnectorHelper) connector) - .getJavascriptConnectorHelper().setTag(tag); - } - return connector; - } catch (NoDataException e) { - throw new IllegalStateException( - "There is no information about " - + classType - + ". Did you remember to compile the right widgetset?", - e); - } - } - } - - private Class<? extends ServerConnector> resolveInheritedConnectorType( - ApplicationConfiguration conf, int tag) { - Class<? extends ServerConnector> classType = null; - Integer t = tag; - do { - classType = resolveConnectorType(t, conf); - t = conf.getParentTag(t); - } while (classType == null && t != null); - return classType; - } - - protected Class<? extends ServerConnector> resolveConnectorType(int tag, - ApplicationConfiguration conf) { - Class<? extends ServerConnector> connectorClass = conf - .getConnectorClassByEncodedTag(tag); - - return connectorClass; - } - - /** - * Due its nature, GWT does not support dynamic classloading. To bypass this - * limitation, widgetset must have function that returns Class by its fully - * qualified name. - * - * @param tag - * @param applicationConfiguration - * @return - */ - public void ensureConnectorLoaded(int tag, ApplicationConfiguration conf) { - ConnectorBundleLoader loader = ConnectorBundleLoader.get(); - String bundleName = null; - Integer t = tag; - do { - String serverSideClassName = conf.getServerSideClassNameForTag(t); - bundleName = loader.getBundleForIdentifier(serverSideClassName); - - t = conf.getParentTag(t); - } while (bundleName == null && t != null); - - if (bundleName != null && !loader.isBundleLoaded(bundleName)) { - ApplicationConfiguration.startDependencyLoading(); - loader.loadBundle(bundleName, new BundleLoadCallback() { - @Override - public void loaded() { - ApplicationConfiguration.endDependencyLoading(); - } - - @Override - public void failed(Throwable reason) { - VConsole.error(reason); - ApplicationConfiguration.endDependencyLoading(); - } - }); - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/AbstractServerConnectorEvent.java b/client/src/com/vaadin/terminal/gwt/client/communication/AbstractServerConnectorEvent.java deleted file mode 100644 index 7b4114ec07..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/communication/AbstractServerConnectorEvent.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.communication; - -import com.google.gwt.event.shared.EventHandler; -import com.google.gwt.event.shared.GwtEvent; -import com.vaadin.terminal.gwt.client.ServerConnector; - -public abstract class AbstractServerConnectorEvent<H extends EventHandler> - extends GwtEvent<H> { - private ServerConnector connector; - - protected AbstractServerConnectorEvent() { - } - - public ServerConnector getConnector() { - return connector; - } - - public void setConnector(ServerConnector connector) { - this.connector = connector; - } - - /** - * Sends this event to the given handler. - * - * @param handler - * The handler to dispatch. - */ - @Override - public abstract void dispatch(H handler); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/DiffJSONSerializer.java b/client/src/com/vaadin/terminal/gwt/client/communication/DiffJSONSerializer.java deleted file mode 100644 index 1d5415263f..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/communication/DiffJSONSerializer.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.communication; - -import com.google.gwt.json.client.JSONValue; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.metadata.Type; - -public interface DiffJSONSerializer<T> extends JSONSerializer<T> { - /** - * Update the target object in place based on the passed JSON data. - * - * @param target - * @param jsonValue - * @param connection - */ - public void update(T target, Type type, JSONValue jsonValue, - ApplicationConnection connection); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/HasJavaScriptConnectorHelper.java b/client/src/com/vaadin/terminal/gwt/client/communication/HasJavaScriptConnectorHelper.java deleted file mode 100644 index 1c8a96a814..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/communication/HasJavaScriptConnectorHelper.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.communication; - -import com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper; - -public interface HasJavaScriptConnectorHelper { - public JavaScriptConnectorHelper getJavascriptConnectorHelper(); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java b/client/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java deleted file mode 100644 index c6b814a5c1..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.communication; - -import com.google.gwt.json.client.JSONObject; -import com.google.gwt.json.client.JSONValue; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.metadata.Type; - -/** - * Implementors of this interface knows how to serialize an Object of a given - * type to JSON and how to deserialize the JSON back into an object. - * - * The {@link #serialize(Object, ConnectorMap)} and - * {@link #deserialize(JSONObject, ConnectorMap)} methods must be symmetric so - * they can be chained and produce the original result (or an equal result). - * - * Each {@link JSONSerializer} implementation can handle an object of a single - * type - see {@link SerializerMap}. - * - * @since 7.0 - */ -public interface JSONSerializer<T> { - - /** - * Creates and deserializes an object received from the server. Must be - * compatible with {@link #serialize(Object, ConnectorMap)} and also with - * the server side JsonCodec.encode(Object, - * com.vaadin.terminal.gwt.server.PaintableIdMapper) . - * - * @param jsonValue - * JSON map from property name to property value - * @return A deserialized object - */ - T deserialize(Type type, JSONValue jsonValue, - ApplicationConnection connection); - - /** - * Serialize the given object into JSON. Must be compatible with - * {@link #deserialize(JSONObject, ConnectorMap)} and also with the server - * side JsonCodec.decode(com.vaadin.external.json.JSONArray, - * com.vaadin.terminal.gwt.server.PaintableIdMapper) - * - * @param value - * The object to serialize - * @return A JSON serialized version of the object - */ - JSONValue serialize(T value, ApplicationConnection connection); - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java b/client/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java deleted file mode 100644 index a98d08c368..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.communication; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.google.gwt.json.client.JSONArray; -import com.google.gwt.json.client.JSONObject; -import com.google.gwt.json.client.JSONString; -import com.google.gwt.json.client.JSONValue; -import com.vaadin.shared.Connector; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.metadata.NoDataException; -import com.vaadin.terminal.gwt.client.metadata.Property; -import com.vaadin.terminal.gwt.client.metadata.Type; - -/** - * Client side decoder for decodeing shared state and other values from JSON - * received from the server. - * - * Currently, basic data types as well as Map, String[] and Object[] are - * supported, where maps and Object[] can contain other supported data types. - * - * TODO extensible type support - * - * @since 7.0 - */ -public class JsonDecoder { - - /** - * Decode a JSON array with two elements (type and value) into a client-side - * type, recursively if necessary. - * - * @param jsonValue - * JSON value with encoded data - * @param connection - * reference to the current ApplicationConnection - * @return decoded value (does not contain JSON types) - */ - public static Object decodeValue(Type type, JSONValue jsonValue, - Object target, ApplicationConnection connection) { - - // Null is null, regardless of type - if (jsonValue.isNull() != null) { - return null; - } - - String baseTypeName = type.getBaseTypeName(); - if (Map.class.getName().equals(baseTypeName) - || HashMap.class.getName().equals(baseTypeName)) { - return decodeMap(type, jsonValue, connection); - } else if (List.class.getName().equals(baseTypeName) - || ArrayList.class.getName().equals(baseTypeName)) { - return decodeList(type, (JSONArray) jsonValue, connection); - } else if (Set.class.getName().equals(baseTypeName)) { - return decodeSet(type, (JSONArray) jsonValue, connection); - } else if (String.class.getName().equals(baseTypeName)) { - return ((JSONString) jsonValue).stringValue(); - } else if (Integer.class.getName().equals(baseTypeName)) { - return Integer.valueOf(String.valueOf(jsonValue)); - } else if (Long.class.getName().equals(baseTypeName)) { - // TODO handle properly - return Long.valueOf(String.valueOf(jsonValue)); - } else if (Float.class.getName().equals(baseTypeName)) { - // TODO handle properly - return Float.valueOf(String.valueOf(jsonValue)); - } else if (Double.class.getName().equals(baseTypeName)) { - // TODO handle properly - return Double.valueOf(String.valueOf(jsonValue)); - } else if (Boolean.class.getName().equals(baseTypeName)) { - // TODO handle properly - return Boolean.valueOf(String.valueOf(jsonValue)); - } else if (Byte.class.getName().equals(baseTypeName)) { - // TODO handle properly - return Byte.valueOf(String.valueOf(jsonValue)); - } else if (Character.class.getName().equals(baseTypeName)) { - // TODO handle properly - return Character.valueOf(((JSONString) jsonValue).stringValue() - .charAt(0)); - } else if (Connector.class.getName().equals(baseTypeName)) { - return ConnectorMap.get(connection).getConnector( - ((JSONString) jsonValue).stringValue()); - } else { - return decodeObject(type, jsonValue, target, connection); - } - } - - private static Object decodeObject(Type type, JSONValue jsonValue, - Object target, ApplicationConnection connection) { - JSONSerializer<Object> serializer = (JSONSerializer<Object>) type - .findSerializer(); - if (serializer != null) { - if (target != null && serializer instanceof DiffJSONSerializer<?>) { - DiffJSONSerializer<Object> diffSerializer = (DiffJSONSerializer<Object>) serializer; - diffSerializer.update(target, type, jsonValue, connection); - return target; - } else { - Object object = serializer.deserialize(type, jsonValue, - connection); - return object; - } - } else { - try { - Collection<Property> properties = type.getProperties(); - if (target == null) { - target = type.createInstance(); - } - JSONObject jsonObject = jsonValue.isObject(); - - for (Property property : properties) { - JSONValue encodedPropertyValue = jsonObject.get(property - .getName()); - if (encodedPropertyValue == null) { - continue; - } - Object propertyReference = property.getValue(target); - Object decodedValue = decodeValue(property.getType(), - encodedPropertyValue, propertyReference, connection); - property.setValue(target, decodedValue); - } - return target; - } catch (NoDataException e) { - throw new RuntimeException("Can not deserialize " - + type.getSignature(), e); - } - } - } - - private static Map<Object, Object> decodeMap(Type type, JSONValue jsonMap, - ApplicationConnection connection) { - // Client -> server encodes empty map as an empty array because of - // #8906. Do the same for server -> client to maintain symmetry. - if (jsonMap instanceof JSONArray) { - JSONArray array = (JSONArray) jsonMap; - if (array.size() == 0) { - return new HashMap<Object, Object>(); - } - } - - Type keyType = type.getParameterTypes()[0]; - Type valueType = type.getParameterTypes()[1]; - - if (keyType.getBaseTypeName().equals(String.class.getName())) { - return decodeStringMap(valueType, jsonMap, connection); - } else if (keyType.getBaseTypeName().equals(Connector.class.getName())) { - return decodeConnectorMap(valueType, jsonMap, connection); - } else { - return decodeObjectMap(keyType, valueType, jsonMap, connection); - } - } - - private static Map<Object, Object> decodeObjectMap(Type keyType, - Type valueType, JSONValue jsonValue, - ApplicationConnection connection) { - Map<Object, Object> map = new HashMap<Object, Object>(); - - JSONArray mapArray = (JSONArray) jsonValue; - JSONArray keys = (JSONArray) mapArray.get(0); - JSONArray values = (JSONArray) mapArray.get(1); - - assert (keys.size() == values.size()); - - for (int i = 0; i < keys.size(); i++) { - Object decodedKey = decodeValue(keyType, keys.get(i), null, - connection); - Object decodedValue = decodeValue(valueType, values.get(i), null, - connection); - - map.put(decodedKey, decodedValue); - } - - return map; - } - - private static Map<Object, Object> decodeConnectorMap(Type valueType, - JSONValue jsonValue, ApplicationConnection connection) { - Map<Object, Object> map = new HashMap<Object, Object>(); - - JSONObject jsonMap = (JSONObject) jsonValue; - ConnectorMap connectorMap = ConnectorMap.get(connection); - - for (String connectorId : jsonMap.keySet()) { - Object value = decodeValue(valueType, jsonMap.get(connectorId), - null, connection); - map.put(connectorMap.getConnector(connectorId), value); - } - - return map; - } - - private static Map<Object, Object> decodeStringMap(Type valueType, - JSONValue jsonValue, ApplicationConnection connection) { - Map<Object, Object> map = new HashMap<Object, Object>(); - - JSONObject jsonMap = (JSONObject) jsonValue; - - for (String key : jsonMap.keySet()) { - Object value = decodeValue(valueType, jsonMap.get(key), null, - connection); - map.put(key, value); - } - - return map; - } - - private static List<Object> decodeList(Type type, JSONArray jsonArray, - ApplicationConnection connection) { - List<Object> tokens = new ArrayList<Object>(); - decodeIntoCollection(type.getParameterTypes()[0], jsonArray, - connection, tokens); - return tokens; - } - - private static Set<Object> decodeSet(Type type, JSONArray jsonArray, - ApplicationConnection connection) { - Set<Object> tokens = new HashSet<Object>(); - decodeIntoCollection(type.getParameterTypes()[0], jsonArray, - connection, tokens); - return tokens; - } - - private static void decodeIntoCollection(Type childType, - JSONArray jsonArray, ApplicationConnection connection, - Collection<Object> tokens) { - for (int i = 0; i < jsonArray.size(); ++i) { - // each entry always has two elements: type and value - JSONValue entryValue = jsonArray.get(i); - tokens.add(decodeValue(childType, entryValue, null, connection)); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java b/client/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java deleted file mode 100644 index 9b28da8b34..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.communication; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import com.google.gwt.json.client.JSONArray; -import com.google.gwt.json.client.JSONBoolean; -import com.google.gwt.json.client.JSONNull; -import com.google.gwt.json.client.JSONNumber; -import com.google.gwt.json.client.JSONObject; -import com.google.gwt.json.client.JSONString; -import com.google.gwt.json.client.JSONValue; -import com.vaadin.shared.Connector; -import com.vaadin.shared.JsonConstants; -import com.vaadin.shared.communication.UidlValue; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.metadata.NoDataException; -import com.vaadin.terminal.gwt.client.metadata.Property; -import com.vaadin.terminal.gwt.client.metadata.Type; - -/** - * Encoder for converting RPC parameters and other values to JSON for transfer - * between the client and the server. - * - * Currently, basic data types as well as Map, String[] and Object[] are - * supported, where maps and Object[] can contain other supported data types. - * - * TODO extensible type support - * - * @since 7.0 - */ -public class JsonEncoder { - - /** - * Encode a value to a JSON representation for transport from the client to - * the server. - * - * @param value - * value to convert - * @param connection - * @return JSON representation of the value - */ - public static JSONValue encode(Object value, - boolean restrictToInternalTypes, ApplicationConnection connection) { - if (null == value) { - return JSONNull.getInstance(); - } else if (value instanceof JSONValue) { - return (JSONValue) value; - } else if (value instanceof String[]) { - String[] array = (String[]) value; - JSONArray jsonArray = new JSONArray(); - for (int i = 0; i < array.length; ++i) { - jsonArray.set(i, new JSONString(array[i])); - } - return jsonArray; - } else if (value instanceof String) { - return new JSONString((String) value); - } else if (value instanceof Boolean) { - return JSONBoolean.getInstance((Boolean) value); - } else if (value instanceof Byte) { - return new JSONNumber((Byte) value); - } else if (value instanceof Character) { - return new JSONString(String.valueOf(value)); - } else if (value instanceof Object[]) { - return encodeObjectArray((Object[]) value, restrictToInternalTypes, - connection); - } else if (value instanceof Enum) { - return encodeEnum((Enum<?>) value, connection); - } else if (value instanceof Map) { - return encodeMap((Map) value, restrictToInternalTypes, connection); - } else if (value instanceof Connector) { - Connector connector = (Connector) value; - return new JSONString(connector.getConnectorId()); - } else if (value instanceof Collection) { - return encodeCollection((Collection) value, - restrictToInternalTypes, connection); - } else if (value instanceof UidlValue) { - return encodeVariableChange((UidlValue) value, connection); - } else { - String transportType = getTransportType(value); - if (transportType != null) { - return new JSONString(String.valueOf(value)); - } else { - // Try to find a generated serializer object, class name is the - // type - Type type = new Type(value.getClass()); - - JSONSerializer<Object> serializer = (JSONSerializer<Object>) type - .findSerializer(); - if (serializer != null) { - return serializer.serialize(value, connection); - } else { - try { - Collection<Property> properties = type.getProperties(); - - JSONObject jsonObject = new JSONObject(); - for (Property property : properties) { - Object propertyValue = property.getValue(value); - JSONValue encodedPropertyValue = encode( - propertyValue, restrictToInternalTypes, - connection); - jsonObject.put(property.getName(), - encodedPropertyValue); - } - return jsonObject; - - } catch (NoDataException e) { - throw new RuntimeException("Can not encode " - + type.getSignature(), e); - } - } - - } - } - } - - private static JSONValue encodeVariableChange(UidlValue uidlValue, - ApplicationConnection connection) { - Object value = uidlValue.getValue(); - - JSONArray jsonArray = new JSONArray(); - jsonArray.set(0, new JSONString(getTransportType(value))); - jsonArray.set(1, encode(value, true, connection)); - - return jsonArray; - } - - private static JSONValue encodeMap(Map<Object, Object> map, - boolean restrictToInternalTypes, ApplicationConnection connection) { - /* - * As we have no info about declared types, we instead select encoding - * scheme based on actual type of first key. We can't do this if there's - * no first key, so instead we send some special value that the - * server-side decoding must check for. (see #8906) - */ - if (map.isEmpty()) { - return new JSONArray(); - } - - Object firstKey = map.keySet().iterator().next(); - if (firstKey instanceof String) { - return encodeStringMap(map, restrictToInternalTypes, connection); - } else if (restrictToInternalTypes) { - throw new IllegalStateException( - "Only string keys supported for legacy maps"); - } else if (firstKey instanceof Connector) { - return encodeConenctorMap(map, connection); - } else { - return encodeObjectMap(map, connection); - } - } - - private static JSONValue encodeObjectMap(Map<Object, Object> map, - ApplicationConnection connection) { - JSONArray keys = new JSONArray(); - JSONArray values = new JSONArray(); - for (Entry<?, ?> entry : map.entrySet()) { - // restrictToInternalTypes always false if we end up here - keys.set(keys.size(), encode(entry.getKey(), false, connection)); - values.set(values.size(), - encode(entry.getValue(), false, connection)); - } - - JSONArray keysAndValues = new JSONArray(); - keysAndValues.set(0, keys); - keysAndValues.set(1, values); - - return keysAndValues; - } - - private static JSONValue encodeConenctorMap(Map<Object, Object> map, - ApplicationConnection connection) { - JSONObject jsonMap = new JSONObject(); - - for (Entry<?, ?> entry : map.entrySet()) { - Connector connector = (Connector) entry.getKey(); - - // restrictToInternalTypes always false if we end up here - JSONValue encodedValue = encode(entry.getValue(), false, connection); - - jsonMap.put(connector.getConnectorId(), encodedValue); - } - - return jsonMap; - } - - private static JSONValue encodeStringMap(Map<Object, Object> map, - boolean restrictToInternalTypes, ApplicationConnection connection) { - JSONObject jsonMap = new JSONObject(); - - for (Entry<?, ?> entry : map.entrySet()) { - String key = (String) entry.getKey(); - Object value = entry.getValue(); - - if (restrictToInternalTypes) { - value = new UidlValue(value); - } - - JSONValue encodedValue = encode(value, restrictToInternalTypes, - connection); - - jsonMap.put(key, encodedValue); - } - - return jsonMap; - } - - private static JSONValue encodeEnum(Enum<?> e, - ApplicationConnection connection) { - return new JSONString(e.toString()); - } - - private static JSONValue encodeObjectArray(Object[] array, - boolean restrictToInternalTypes, ApplicationConnection connection) { - JSONArray jsonArray = new JSONArray(); - for (int i = 0; i < array.length; ++i) { - // TODO handle object graph loops? - Object value = array[i]; - if (restrictToInternalTypes) { - value = new UidlValue(value); - } - jsonArray - .set(i, encode(value, restrictToInternalTypes, connection)); - } - return jsonArray; - } - - private static JSONValue encodeCollection(Collection collection, - boolean restrictToInternalTypes, ApplicationConnection connection) { - JSONArray jsonArray = new JSONArray(); - int idx = 0; - for (Object o : collection) { - JSONValue encodedObject = encode(o, restrictToInternalTypes, - connection); - jsonArray.set(idx++, encodedObject); - } - if (collection instanceof Set) { - return jsonArray; - } else if (collection instanceof List) { - return jsonArray; - } else { - throw new RuntimeException("Unsupport collection type: " - + collection.getClass().getName()); - } - - } - - /** - * Returns the transport type for the given value. Only returns a transport - * type for internally handled values. - * - * @param value - * The value that should be transported - * @return One of the JsonEncode.VTYPE_ constants or null if the value - * cannot be transported using an internally handled type. - */ - private static String getTransportType(Object value) { - if (value == null) { - return JsonConstants.VTYPE_NULL; - } else if (value instanceof String) { - return JsonConstants.VTYPE_STRING; - } else if (value instanceof Connector) { - return JsonConstants.VTYPE_CONNECTOR; - } else if (value instanceof Boolean) { - return JsonConstants.VTYPE_BOOLEAN; - } else if (value instanceof Integer) { - return JsonConstants.VTYPE_INTEGER; - } else if (value instanceof Float) { - return JsonConstants.VTYPE_FLOAT; - } else if (value instanceof Double) { - return JsonConstants.VTYPE_DOUBLE; - } else if (value instanceof Long) { - return JsonConstants.VTYPE_LONG; - } else if (value instanceof List) { - return JsonConstants.VTYPE_LIST; - } else if (value instanceof Set) { - return JsonConstants.VTYPE_SET; - } else if (value instanceof String[]) { - return JsonConstants.VTYPE_STRINGARRAY; - } else if (value instanceof Object[]) { - return JsonConstants.VTYPE_ARRAY; - } else if (value instanceof Map) { - return JsonConstants.VTYPE_MAP; - } else if (value instanceof Enum<?>) { - // Enum value is processed as a string - return JsonConstants.VTYPE_STRING; - } - return null; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java b/client/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java deleted file mode 100644 index 5b9bcff6a4..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.communication; - -import java.util.Collection; - -import com.google.gwt.json.client.JSONArray; -import com.google.gwt.json.client.JSONString; -import com.vaadin.shared.communication.ClientRpc; -import com.vaadin.shared.communication.MethodInvocation; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.ServerConnector; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.metadata.Method; -import com.vaadin.terminal.gwt.client.metadata.NoDataException; -import com.vaadin.terminal.gwt.client.metadata.Type; - -/** - * Client side RPC manager that can invoke methods based on RPC calls received - * from the server. - * - * A GWT generator is used to create an implementation of this class at - * run-time. - * - * @since 7.0 - */ -public class RpcManager { - - /** - * Perform server to client RPC invocation. - * - * @param invocation - * method to invoke - */ - public void applyInvocation(MethodInvocation invocation, - ServerConnector connector) { - Method method = getMethod(invocation); - - Collection<ClientRpc> implementations = connector - .getRpcImplementations(invocation.getInterfaceName()); - try { - for (ClientRpc clientRpc : implementations) { - method.invoke(clientRpc, invocation.getParameters()); - } - } catch (NoDataException e) { - throw new IllegalStateException("There is no information about " - + method.getSignature() - + ". Did you remember to compile the right widgetset?", e); - } - } - - private Method getMethod(MethodInvocation invocation) { - Type type = new Type(invocation.getInterfaceName(), null); - Method method = type.getMethod(invocation.getMethodName()); - return method; - } - - private static String getSignature(MethodInvocation invocation) { - return invocation.getInterfaceName() + "." + invocation.getMethodName(); - } - - public Type[] getParameterTypes(MethodInvocation invocation) { - Method method = getMethod(invocation); - try { - Type[] parameterTypes = method.getParameterTypes(); - return parameterTypes; - } catch (NoDataException e) { - throw new IllegalStateException("There is no information about " - + method.getSignature() - + ". Did you remember to compile the right widgetset?", e); - } - } - - public void parseAndApplyInvocation(JSONArray rpcCall, - ApplicationConnection connection) { - ConnectorMap connectorMap = ConnectorMap.get(connection); - - String connectorId = ((JSONString) rpcCall.get(0)).stringValue(); - String interfaceName = ((JSONString) rpcCall.get(1)).stringValue(); - String methodName = ((JSONString) rpcCall.get(2)).stringValue(); - JSONArray parametersJson = (JSONArray) rpcCall.get(3); - - ServerConnector connector = connectorMap.getConnector(connectorId); - - MethodInvocation invocation = new MethodInvocation(connectorId, - interfaceName, methodName); - if (connector instanceof HasJavaScriptConnectorHelper) { - ((HasJavaScriptConnectorHelper) connector) - .getJavascriptConnectorHelper().invokeJsRpc(invocation, - parametersJson); - } else { - if (connector == null) { - throw new IllegalStateException("Target connector (" - + connector + ") not found for RCC to " - + getSignature(invocation)); - } - - parseMethodParameters(invocation, parametersJson, connection); - VConsole.log("Server to client RPC call: " + invocation); - applyInvocation(invocation, connector); - } - } - - private void parseMethodParameters(MethodInvocation methodInvocation, - JSONArray parametersJson, ApplicationConnection connection) { - Type[] parameterTypes = getParameterTypes(methodInvocation); - - Object[] parameters = new Object[parametersJson.size()]; - for (int j = 0; j < parametersJson.size(); ++j) { - parameters[j] = JsonDecoder.decodeValue(parameterTypes[j], - parametersJson.get(j), null, connection); - } - - methodInvocation.setParameters(parameters); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/RpcProxy.java b/client/src/com/vaadin/terminal/gwt/client/communication/RpcProxy.java deleted file mode 100644 index e9dc6ab7fd..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/communication/RpcProxy.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.communication; - -import com.vaadin.shared.communication.MethodInvocation; -import com.vaadin.shared.communication.ServerRpc; -import com.vaadin.terminal.gwt.client.ServerConnector; -import com.vaadin.terminal.gwt.client.metadata.InvokationHandler; -import com.vaadin.terminal.gwt.client.metadata.Method; -import com.vaadin.terminal.gwt.client.metadata.NoDataException; -import com.vaadin.terminal.gwt.client.metadata.TypeData; - -/** - * Class for creating proxy instances for Client to Server RPC. - * - * @since 7.0 - */ -public class RpcProxy { - - public static <T extends ServerRpc> T create(Class<T> rpcInterface, - ServerConnector connector) { - try { - return (T) TypeData.getType(rpcInterface).createProxy( - new RpcInvokationHandler(rpcInterface, connector)); - } catch (NoDataException e) { - throw new IllegalStateException("There is no information about " - + rpcInterface - + ". Did you forget to compile the widgetset?"); - } - } - - private static final class RpcInvokationHandler implements - InvokationHandler { - private final Class<?> rpcInterface; - private final ServerConnector connector; - - private RpcInvokationHandler(Class<?> rpcInterface, - ServerConnector connector) { - this.rpcInterface = rpcInterface; - this.connector = connector; - } - - @Override - public Object invoke(Object target, Method method, Object[] params) { - MethodInvocation invocation = new MethodInvocation( - connector.getConnectorId(), rpcInterface.getName(), - method.getName(), params); - connector.getConnection().addMethodInvocationToQueue(invocation, - method.isDelayed(), method.isLastonly()); - // No RPC iface should have a return value - return null; - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/StateChangeEvent.java b/client/src/com/vaadin/terminal/gwt/client/communication/StateChangeEvent.java deleted file mode 100644 index 8ed32bc94b..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/communication/StateChangeEvent.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.communication; - -import java.io.Serializable; -import java.util.Collections; -import java.util.Set; - -import com.google.gwt.event.shared.EventHandler; -import com.vaadin.terminal.gwt.client.ServerConnector; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler; - -public class StateChangeEvent extends - AbstractServerConnectorEvent<StateChangeHandler> { - /** - * Type of this event, used by the event bus. - */ - public static final Type<StateChangeHandler> TYPE = new Type<StateChangeHandler>(); - - private Set<String> changedProperties; - - @Override - public Type<StateChangeHandler> getAssociatedType() { - return TYPE; - } - - /** - * Creates a new state change event. - * - * @param connector - * the event whose state has changed - * @param changedProperties - * a set of names of the changed properties - */ - public StateChangeEvent(ServerConnector connector, - Set<String> changedProperties) { - setConnector(connector); - this.changedProperties = changedProperties; - } - - @Override - public void dispatch(StateChangeHandler listener) { - listener.onStateChanged(this); - } - - /** - * Event handler that gets notified whenever any part of the state has been - * updated by the server. - * - * @author Vaadin Ltd - * @version @VERSION@ - * @since 7.0.0 - */ - public interface StateChangeHandler extends Serializable, EventHandler { - /** - * Notifies the event handler that the state has changed. - * - * @param stateChangeEvent - * the state change event with details about the change - */ - public void onStateChanged(StateChangeEvent stateChangeEvent); - } - - /** - * Gets the properties that have changed. - * - * @return a set of names of the changed properties - */ - public Set<String> getChangedProperties() { - return Collections.unmodifiableSet(changedProperties); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java b/client/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java deleted file mode 100644 index 3d2e4f3804..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.communication; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.json.client.JSONObject; -import com.google.gwt.json.client.JSONValue; -import com.vaadin.shared.communication.URLReference; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.metadata.Type; - -public class URLReference_Serializer implements JSONSerializer<URLReference> { - - // setURL() -> uRL as first char becomes lower case... - private static final String URL_FIELD = "uRL"; - - @Override - public URLReference deserialize(Type type, JSONValue jsonValue, - ApplicationConnection connection) { - URLReference reference = GWT.create(URLReference.class); - JSONObject json = (JSONObject) jsonValue; - if (json.containsKey(URL_FIELD)) { - JSONValue jsonURL = json.get(URL_FIELD); - String URL = (String) JsonDecoder.decodeValue( - new Type(String.class.getName(), null), jsonURL, null, - connection); - reference.setURL(connection.translateVaadinUri(URL)); - } - return reference; - } - - @Override - public JSONValue serialize(URLReference value, - ApplicationConnection connection) { - JSONObject json = new JSONObject(); - json.put(URL_FIELD, - JsonEncoder.encode(value.getURL(), true, connection)); - return json; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/extensions/AbstractExtensionConnector.java b/client/src/com/vaadin/terminal/gwt/client/extensions/AbstractExtensionConnector.java deleted file mode 100644 index dabbfe22f0..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/extensions/AbstractExtensionConnector.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.extensions; - -import com.vaadin.terminal.gwt.client.ServerConnector; -import com.vaadin.terminal.gwt.client.ui.AbstractConnector; - -public abstract class AbstractExtensionConnector extends AbstractConnector { - boolean hasBeenAttached = false; - - @Override - public void setParent(ServerConnector parent) { - ServerConnector oldParent = getParent(); - if (oldParent == parent) { - // Nothing to do - return; - } - if (hasBeenAttached && parent != null) { - throw new IllegalStateException( - "An extension can not be moved from one parent to another."); - } - - super.setParent(parent); - - if (parent != null) { - extend(parent); - hasBeenAttached = true; - } - } - - protected void extend(ServerConnector target) { - // Default does nothing - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerConnector.java b/client/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerConnector.java deleted file mode 100644 index 46578b0641..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerConnector.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.extensions.javascriptmanager; - -import java.util.HashSet; -import java.util.Set; - -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.JsArray; -import com.google.gwt.json.client.JSONArray; -import com.vaadin.shared.communication.MethodInvocation; -import com.vaadin.shared.extension.javascriptmanager.ExecuteJavaScriptRpc; -import com.vaadin.shared.extension.javascriptmanager.JavaScriptManagerState; -import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.extensions.AbstractExtensionConnector; -import com.vaadin.ui.JavaScript; - -@Connect(JavaScript.class) -public class JavaScriptManagerConnector extends AbstractExtensionConnector { - private Set<String> currentNames = new HashSet<String>(); - - @Override - protected void init() { - registerRpc(ExecuteJavaScriptRpc.class, new ExecuteJavaScriptRpc() { - @Override - public void executeJavaScript(String Script) { - eval(Script); - } - }); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - Set<String> newNames = getState().getNames(); - - // Current names now only contains orphan callbacks - currentNames.removeAll(newNames); - - for (String name : currentNames) { - removeCallback(name); - } - - currentNames = new HashSet<String>(newNames); - for (String name : newNames) { - addCallback(name); - } - } - - // TODO Ensure we don't overwrite anything (important) in $wnd - private native void addCallback(String name) - /*-{ - var m = this; - var target = $wnd; - var parts = name.split('.'); - - for(var i = 0; i < parts.length - 1; i++) { - var part = parts[i]; - if (target[part] === undefined) { - target[part] = {}; - } - target = target[part]; - } - - target[parts[parts.length - 1]] = $entry(function() { - //Must make a copy because arguments is an array-like object (not instanceof Array), causing suboptimal JSON encoding - var args = Array.prototype.slice.call(arguments, 0); - m.@com.vaadin.terminal.gwt.client.extensions.javascriptmanager.JavaScriptManagerConnector::sendRpc(Ljava/lang/String;Lcom/google/gwt/core/client/JsArray;)(name, args); - }); - }-*/; - - // TODO only remove what we actually added - // TODO We might leave empty objects behind, but there's no good way of - // knowing whether they are unused - private native void removeCallback(String name) - /*-{ - var target = $wnd; - var parts = name.split('.'); - - for(var i = 0; i < parts.length - 1; i++) { - var part = parts[i]; - if (target[part] === undefined) { - $wnd.console.log(part,'not defined in',target); - // No longer attached -> nothing more to do - return; - } - target = target[part]; - } - - $wnd.console.log('removing',parts[parts.length - 1],'from',target); - delete target[parts[parts.length - 1]]; - }-*/; - - private static native void eval(String script) - /*-{ - if(script) { - (new $wnd.Function(script)).apply($wnd); - } - }-*/; - - public void sendRpc(String name, JsArray<JavaScriptObject> arguments) { - Object[] parameters = new Object[] { name, new JSONArray(arguments) }; - - /* - * Must invoke manually as the RPC interface can't be used in GWT - * because of the JSONArray parameter - */ - getConnection().addMethodInvocationToQueue( - new MethodInvocation(getConnectorId(), - "com.vaadin.ui.JavaScript$JavaScriptCallbackRpc", - "call", parameters), false, false); - } - - @Override - public JavaScriptManagerState getState() { - return (JavaScriptManagerState) super.getState(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/AsyncBundleLoader.java b/client/src/com/vaadin/terminal/gwt/client/metadata/AsyncBundleLoader.java deleted file mode 100644 index e92e51b40d..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/AsyncBundleLoader.java +++ /dev/null @@ -1,86 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.client.metadata; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public abstract class AsyncBundleLoader { - public enum State { - NOT_STARTED, LOADING, LOADED, ERROR; - } - - private State state = State.NOT_STARTED; - - private Throwable error = null; - - private List<BundleLoadCallback> callbacks = new ArrayList<BundleLoadCallback>(); - - private final String packageName; - - private final String[] indentifiers; - - public AsyncBundleLoader(String packageName, String[] indentifiers) { - this.packageName = packageName; - this.indentifiers = indentifiers; - } - - protected abstract void load(TypeDataStore store); - - public List<BundleLoadCallback> setError(Throwable error) { - assert state == State.LOADING; - state = State.ERROR; - this.error = error; - - return clearCallbacks(); - } - - public Throwable getError() { - return error; - } - - public State getState() { - return state; - } - - public List<BundleLoadCallback> getCallback() { - return Collections.unmodifiableList(callbacks); - } - - public void load(BundleLoadCallback callback, TypeDataStore store) { - assert state == State.NOT_STARTED; - state = State.LOADING; - callbacks.add(callback); - load(store); - } - - public void addCallback(BundleLoadCallback callback) { - assert state == State.LOADING; - callbacks.add(callback); - } - - public List<BundleLoadCallback> setLoaded() { - assert state == State.LOADING; - state = State.LOADED; - - return clearCallbacks(); - } - - private List<BundleLoadCallback> clearCallbacks() { - List<BundleLoadCallback> callbacks = this.callbacks; - this.callbacks = null; - return callbacks; - } - - public String getName() { - return packageName; - } - - public String[] getIndentifiers() { - return indentifiers; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/BundleLoadCallback.java b/client/src/com/vaadin/terminal/gwt/client/metadata/BundleLoadCallback.java deleted file mode 100644 index c7fc735829..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/BundleLoadCallback.java +++ /dev/null @@ -1,11 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.client.metadata; - -public interface BundleLoadCallback { - public void loaded(); - - public void failed(Throwable reason); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/ConnectorBundleLoader.java b/client/src/com/vaadin/terminal/gwt/client/metadata/ConnectorBundleLoader.java deleted file mode 100644 index ab1462efc1..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/ConnectorBundleLoader.java +++ /dev/null @@ -1,99 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.client.metadata; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.google.gwt.core.shared.GWT; -import com.vaadin.terminal.gwt.client.metadata.AsyncBundleLoader.State; - -public abstract class ConnectorBundleLoader { - public static final String EAGER_BUNDLE_NAME = "__eager"; - public static final String DEFERRED_BUNDLE_NAME = "__deferred"; - - private static ConnectorBundleLoader impl; - - private Map<String, AsyncBundleLoader> asyncBlockLoaders = new HashMap<String, AsyncBundleLoader>(); - private Map<String, String> identifierToBundle = new HashMap<String, String>(); - - private final TypeDataStore datStore = new TypeDataStore(); - - public ConnectorBundleLoader() { - init(); - } - - public TypeDataStore getTypeDataStore() { - return datStore; - } - - public static ConnectorBundleLoader get() { - if (impl == null) { - impl = GWT.create(ConnectorBundleLoader.class); - } - return impl; - } - - public void loadBundle(String packageName, BundleLoadCallback callback) { - AsyncBundleLoader loader = asyncBlockLoaders.get(packageName); - switch (loader.getState()) { - case NOT_STARTED: - loader.load(callback, getTypeDataStore()); - break; - case LOADING: - loader.addCallback(callback); - break; - case LOADED: - callback.loaded(); - break; - case ERROR: - callback.failed(loader.getError()); - } - } - - public boolean isBundleLoaded(String bundleName) { - AsyncBundleLoader loader = asyncBlockLoaders.get(bundleName); - if (loader == null) { - throw new IllegalArgumentException("Bundle " + bundleName - + " not recognized"); - } - return loader.getState() == State.LOADED; - } - - public void setLoaded(String packageName) { - List<BundleLoadCallback> callbacks = asyncBlockLoaders.get(packageName) - .setLoaded(); - for (BundleLoadCallback callback : callbacks) { - if (callback != null) { - callback.loaded(); - } - } - } - - public void setLoadFailure(String bundleName, Throwable reason) { - List<BundleLoadCallback> callbacks = asyncBlockLoaders.get(bundleName) - .setError(reason); - for (BundleLoadCallback callback : callbacks) { - callback.failed(reason); - } - } - - public String getBundleForIdentifier(String identifier) { - return identifierToBundle.get(identifier); - } - - protected void addAsyncBlockLoader(AsyncBundleLoader loader) { - String name = loader.getName(); - asyncBlockLoaders.put(name, loader); - String[] indentifiers = loader.getIndentifiers(); - for (String identifier : indentifiers) { - identifierToBundle.put(identifier, name); - } - } - - public abstract void init(); - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/InvokationHandler.java b/client/src/com/vaadin/terminal/gwt/client/metadata/InvokationHandler.java deleted file mode 100644 index 2b1153ad97..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/InvokationHandler.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.metadata; - -public interface InvokationHandler { - public Object invoke(Object target, Method method, Object[] params); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/Invoker.java b/client/src/com/vaadin/terminal/gwt/client/metadata/Invoker.java deleted file mode 100644 index 33e8776429..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/Invoker.java +++ /dev/null @@ -1,9 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.client.metadata; - -public interface Invoker { - public Object invoke(Object target, Object... params); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/Method.java b/client/src/com/vaadin/terminal/gwt/client/metadata/Method.java deleted file mode 100644 index 527e8a29d2..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/Method.java +++ /dev/null @@ -1,71 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.client.metadata; - -public class Method { - - private final Type type; - private final String name; - - public Method(Type type, String name) { - this.type = type; - this.name = name; - } - - public Type getType() { - return type; - } - - public String getName() { - return name; - } - - public Type getReturnType() throws NoDataException { - return TypeDataStore.getReturnType(this); - } - - public void invoke(Object target, Object... params) throws NoDataException { - TypeDataStore.getInvoker(this).invoke(target, params); - } - - public String getSignature() { - return type.toString() + "." + name; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (obj instanceof Method) { - Method other = (Method) obj; - return other.getSignature().equals(getSignature()); - } else { - return false; - } - } - - @Override - public String toString() { - return getSignature(); - } - - @Override - public int hashCode() { - return getSignature().hashCode(); - } - - public Type[] getParameterTypes() throws NoDataException { - return TypeDataStore.getParamTypes(this); - } - - public boolean isDelayed() { - return TypeDataStore.isDelayed(this); - } - - public boolean isLastonly() { - return TypeDataStore.isLastonly(this); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/NoDataException.java b/client/src/com/vaadin/terminal/gwt/client/metadata/NoDataException.java deleted file mode 100644 index 717b92edaf..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/NoDataException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.metadata; - -public class NoDataException extends Exception { - - public NoDataException(String message) { - super(message); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/Property.java b/client/src/com/vaadin/terminal/gwt/client/metadata/Property.java deleted file mode 100644 index 69e41ce75d..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/Property.java +++ /dev/null @@ -1,69 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.client.metadata; - -import com.vaadin.shared.annotations.DelegateToWidget; - -public class Property { - private final Type bean; - private final String name; - - public Property(Type bean, String name) { - this.bean = bean; - this.name = name; - } - - public Object getValue(Object bean) throws NoDataException { - return TypeDataStore.getGetter(this).invoke(bean); - } - - public void setValue(Object bean, Object value) throws NoDataException { - TypeDataStore.getSetter(this).invoke(bean, value); - } - - public String getDelegateToWidgetMethodName() { - String value = TypeDataStore.getDelegateToWidget(this); - if (value == null) { - return null; - } else { - return DelegateToWidget.Helper.getDelegateTarget(getName(), value); - } - } - - public Type getType() throws NoDataException { - return TypeDataStore.getType(this); - } - - public String getSignature() { - return bean.toString() + "." + name; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } else if (obj instanceof Property) { - Property other = (Property) obj; - return getSignature().equals(other.getSignature()); - } else { - return false; - } - } - - @Override - public int hashCode() { - return getSignature().hashCode(); - } - - public String getName() { - return name; - } - - @Override - public String toString() { - return getSignature(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/ProxyHandler.java b/client/src/com/vaadin/terminal/gwt/client/metadata/ProxyHandler.java deleted file mode 100644 index cc8168a8ff..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/ProxyHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.metadata; - -public interface ProxyHandler { - - Object createProxy(InvokationHandler invokationHandler); - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/Type.java b/client/src/com/vaadin/terminal/gwt/client/metadata/Type.java deleted file mode 100644 index d019ff27e0..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/Type.java +++ /dev/null @@ -1,101 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.terminal.gwt.client.metadata; - -import java.util.Collection; - -import com.vaadin.terminal.gwt.client.communication.JSONSerializer; - -public class Type { - private final String name; - private final Type[] parameterTypes; - - public Type(Class<?> clazz) { - name = clazz.getName(); - parameterTypes = null; - } - - public Type(String baseTypeName, Type[] parameterTypes) { - name = baseTypeName; - this.parameterTypes = parameterTypes; - } - - public String getBaseTypeName() { - return name; - } - - public Type[] getParameterTypes() { - return parameterTypes; - } - - public Object createInstance() throws NoDataException { - Invoker invoker = TypeDataStore.getConstructor(this); - return invoker.invoke(null); - } - - public Method getMethod(String name) { - return new Method(this, name); - } - - public Collection<Property> getProperties() throws NoDataException { - return TypeDataStore.getProperties(this); - } - - public Property getProperty(String propertyName) { - return new Property(this, propertyName); - } - - public String getSignature() { - String string = name; - if (parameterTypes != null && parameterTypes.length != 0) { - string += '<'; - for (int i = 0; i < parameterTypes.length; i++) { - if (i != 0) { - string += ','; - } - string += parameterTypes[i].toString(); - } - string += '>'; - } - - return string; - } - - @Override - public String toString() { - return getSignature(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (obj instanceof Type) { - Type other = (Type) obj; - return other.getSignature().equals(getSignature()); - } else { - return false; - } - } - - @Override - public int hashCode() { - return getSignature().hashCode(); - } - - public Object createProxy(InvokationHandler invokationHandler) - throws NoDataException { - return TypeDataStore.get().getProxyHandler(this) - .createProxy(invokationHandler); - } - - public JSONSerializer<?> findSerializer() { - return TypeDataStore.findSerializer(this); - } - - public boolean hasProperties() { - return TypeDataStore.hasProperties(this); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/TypeData.java b/client/src/com/vaadin/terminal/gwt/client/metadata/TypeData.java deleted file mode 100644 index ec2a8f191c..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/TypeData.java +++ /dev/null @@ -1,20 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.client.metadata; - -public class TypeData { - - public static Type getType(Class<?> type) { - return TypeDataStore.getType(type); - } - - public static Class<?> getClass(String identifier) throws NoDataException { - return TypeDataStore.getClass(identifier); - } - - public static boolean hasIdentifier(String identifier) { - return TypeDataStore.hasIdentifier(identifier); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataBundle.java b/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataBundle.java deleted file mode 100644 index cbde338ff2..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataBundle.java +++ /dev/null @@ -1,33 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.client.metadata; - -import com.google.gwt.core.client.RunAsyncCallback; - -public abstract class TypeDataBundle implements RunAsyncCallback { - private final String name; - - public TypeDataBundle(String name) { - this.name = name; - } - - @Override - public void onSuccess() { - ConnectorBundleLoader loader = ConnectorBundleLoader.get(); - load(); - loader.setLoaded(getName()); - } - - @Override - public void onFailure(Throwable reason) { - ConnectorBundleLoader.get().setLoadFailure(getName(), reason); - } - - public abstract void load(); - - public String getName() { - return name; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java b/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java deleted file mode 100644 index 0fc8f3b3bf..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java +++ /dev/null @@ -1,230 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.client.metadata; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import com.vaadin.terminal.gwt.client.communication.JSONSerializer; - -public class TypeDataStore { - private static final String CONSTRUCTOR_NAME = "!new"; - - private final Map<String, Class<?>> identifiers = new HashMap<String, Class<?>>(); - - private final Map<Type, Invoker> serializerFactories = new HashMap<Type, Invoker>(); - private final Map<Type, ProxyHandler> proxyHandlers = new HashMap<Type, ProxyHandler>(); - private final Map<Type, Collection<Property>> properties = new HashMap<Type, Collection<Property>>(); - - private final Set<Method> delayedMethods = new HashSet<Method>(); - private final Set<Method> lastonlyMethods = new HashSet<Method>(); - - private final Map<Method, Type> returnTypes = new HashMap<Method, Type>(); - private final Map<Method, Invoker> invokers = new HashMap<Method, Invoker>(); - private final Map<Method, Type[]> paramTypes = new HashMap<Method, Type[]>(); - - private final Map<Property, Type> propertyTypes = new HashMap<Property, Type>(); - private final Map<Property, Invoker> setters = new HashMap<Property, Invoker>(); - private final Map<Property, Invoker> getters = new HashMap<Property, Invoker>(); - private final Map<Property, String> delegateToWidget = new HashMap<Property, String>(); - - public static TypeDataStore get() { - return ConnectorBundleLoader.get().getTypeDataStore(); - } - - public void setClass(String identifier, Class<?> type) { - identifiers.put(identifier, type); - } - - public static Class<?> getClass(String identifier) throws NoDataException { - Class<?> class1 = get().identifiers.get(identifier); - if (class1 == null) { - throw new NoDataException("There is not class for identifier " - + identifier); - } - return class1; - } - - public static Type getType(Class<?> clazz) { - return new Type(clazz); - } - - public static Type getReturnType(Method method) throws NoDataException { - Type type = get().returnTypes.get(method); - if (type == null) { - throw new NoDataException("There is return type for " - + method.getSignature()); - } - return type; - } - - public static Invoker getInvoker(Method method) throws NoDataException { - Invoker invoker = get().invokers.get(method); - if (invoker == null) { - throw new NoDataException("There is invoker for " - + method.getSignature()); - } - return invoker; - } - - public static Invoker getConstructor(Type type) throws NoDataException { - Invoker invoker = get().invokers - .get(new Method(type, CONSTRUCTOR_NAME)); - if (invoker == null) { - throw new NoDataException("There is constructor for " - + type.getSignature()); - } - return invoker; - } - - public static Invoker getGetter(Property property) throws NoDataException { - Invoker getter = get().getters.get(property); - if (getter == null) { - throw new NoDataException("There is getter for " - + property.getSignature()); - } - - return getter; - } - - public void setGetter(Class<?> clazz, String propertyName, Invoker invoker) { - getters.put(new Property(getType(clazz), propertyName), invoker); - } - - public static String getDelegateToWidget(Property property) { - return get().delegateToWidget.get(property); - } - - public void setDelegateToWidget(Class<?> clazz, String propertyName, - String delegateValue) { - delegateToWidget.put(new Property(getType(clazz), propertyName), - delegateValue); - } - - public void setReturnType(Class<?> type, String methodName, Type returnType) { - returnTypes.put(new Method(getType(type), methodName), returnType); - } - - public void setConstructor(Class<?> type, Invoker constructor) { - setInvoker(type, CONSTRUCTOR_NAME, constructor); - } - - public void setInvoker(Class<?> type, String methodName, Invoker invoker) { - invokers.put(new Method(getType(type), methodName), invoker); - } - - public static Type[] getParamTypes(Method method) throws NoDataException { - Type[] types = get().paramTypes.get(method); - if (types == null) { - throw new NoDataException("There are no parameter type data for " - + method.getSignature()); - } - return types; - } - - public void setParamTypes(Class<?> type, String methodName, - Type[] paramTypes) { - this.paramTypes.put(new Method(getType(type), methodName), paramTypes); - } - - public static boolean hasIdentifier(String identifier) { - return get().identifiers.containsKey(identifier); - } - - public static ProxyHandler getProxyHandler(Type type) - throws NoDataException { - ProxyHandler proxyHandler = get().proxyHandlers.get(type); - if (proxyHandler == null) { - throw new NoDataException("No proxy handler for " - + type.getSignature()); - } - return proxyHandler; - } - - public void setProxyHandler(Class<?> type, ProxyHandler proxyHandler) { - proxyHandlers.put(getType(type), proxyHandler); - } - - public static boolean isDelayed(Method method) { - return get().delayedMethods.contains(method); - } - - public void setDelayed(Class<?> type, String methodName) { - delayedMethods.add(getType(type).getMethod(methodName)); - } - - public static boolean isLastonly(Method method) { - return get().lastonlyMethods.contains(method); - } - - public void setLastonly(Class<?> clazz, String methodName) { - lastonlyMethods.add(getType(clazz).getMethod(methodName)); - } - - public static Collection<Property> getProperties(Type type) - throws NoDataException { - Collection<Property> properties = get().properties.get(type); - if (properties == null) { - throw new NoDataException("No property list for " - + type.getSignature()); - } - return properties; - } - - public void setProperties(Class<?> clazz, String[] propertyNames) { - Set<Property> properties = new HashSet<Property>(); - Type type = getType(clazz); - for (String name : propertyNames) { - properties.add(new Property(type, name)); - } - this.properties.put(type, Collections.unmodifiableSet(properties)); - } - - public static Type getType(Property property) throws NoDataException { - Type type = get().propertyTypes.get(property); - if (type == null) { - throw new NoDataException("No return type for " - + property.getSignature()); - } - return type; - } - - public void setPropertyType(Class<?> clazz, String propertName, Type type) { - propertyTypes.put(new Property(getType(clazz), propertName), type); - } - - public static Invoker getSetter(Property property) throws NoDataException { - Invoker setter = get().setters.get(property); - if (setter == null) { - throw new NoDataException("No setter for " - + property.getSignature()); - } - return setter; - } - - public void setSetter(Class<?> clazz, String propertyName, Invoker setter) { - setters.put(new Property(getType(clazz), propertyName), setter); - } - - public void setSerializerFactory(Class<?> clazz, Invoker factory) { - serializerFactories.put(getType(clazz), factory); - } - - public static JSONSerializer<?> findSerializer(Type type) { - Invoker factoryCreator = get().serializerFactories.get(type); - if (factoryCreator == null) { - return null; - } - return (JSONSerializer<?>) factoryCreator.invoke(null); - } - - public static boolean hasProperties(Type type) { - return get().properties.containsKey(type); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractClickEventHandler.java b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractClickEventHandler.java deleted file mode 100644 index e7060f1c6d..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractClickEventHandler.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.event.dom.client.ContextMenuEvent; -import com.google.gwt.event.dom.client.ContextMenuHandler; -import com.google.gwt.event.dom.client.DomEvent; -import com.google.gwt.event.dom.client.DoubleClickEvent; -import com.google.gwt.event.dom.client.DoubleClickHandler; -import com.google.gwt.event.dom.client.MouseDownEvent; -import com.google.gwt.event.dom.client.MouseDownHandler; -import com.google.gwt.event.dom.client.MouseUpEvent; -import com.google.gwt.event.dom.client.MouseUpHandler; -import com.google.gwt.event.shared.EventHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Event.NativePreviewEvent; -import com.google.gwt.user.client.Event.NativePreviewHandler; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.Util; - -public abstract class AbstractClickEventHandler implements MouseDownHandler, - MouseUpHandler, DoubleClickHandler, ContextMenuHandler { - - private HandlerRegistration mouseDownHandlerRegistration; - private HandlerRegistration mouseUpHandlerRegistration; - private HandlerRegistration doubleClickHandlerRegistration; - private HandlerRegistration contextMenuHandlerRegistration; - - protected ComponentConnector connector; - private String clickEventIdentifier; - - /** - * The element where the last mouse down event was registered. - */ - private JavaScriptObject lastMouseDownTarget; - - /** - * Set to true by {@link #mouseUpPreviewHandler} if it gets a mouseup at the - * same element as {@link #lastMouseDownTarget}. - */ - private boolean mouseUpPreviewMatched = false; - - private HandlerRegistration mouseUpEventPreviewRegistration; - - /** - * Previews events after a mousedown to detect where the following mouseup - * hits. - */ - private final NativePreviewHandler mouseUpPreviewHandler = new NativePreviewHandler() { - - @Override - public void onPreviewNativeEvent(NativePreviewEvent event) { - if (event.getTypeInt() == Event.ONMOUSEUP) { - mouseUpEventPreviewRegistration.removeHandler(); - - // Event's reported target not always correct if event - // capture is in use - Element elementUnderMouse = Util.getElementUnderMouse(event - .getNativeEvent()); - if (lastMouseDownTarget != null - && elementUnderMouse.cast() == lastMouseDownTarget) { - mouseUpPreviewMatched = true; - } else { - System.out.println("Ignoring mouseup from " - + elementUnderMouse + " when mousedown was on " - + lastMouseDownTarget); - } - } - } - }; - - public AbstractClickEventHandler(ComponentConnector connector, - String clickEventIdentifier) { - this.connector = connector; - this.clickEventIdentifier = clickEventIdentifier; - } - - public void handleEventHandlerRegistration() { - // Handle registering/unregistering of click handler depending on if - // server side listeners have been added or removed. - if (hasEventListener()) { - if (mouseDownHandlerRegistration == null) { - mouseDownHandlerRegistration = registerHandler(this, - MouseDownEvent.getType()); - mouseUpHandlerRegistration = registerHandler(this, - MouseUpEvent.getType()); - doubleClickHandlerRegistration = registerHandler(this, - DoubleClickEvent.getType()); - contextMenuHandlerRegistration = registerHandler(this, - ContextMenuEvent.getType()); - } - } else { - if (mouseDownHandlerRegistration != null) { - // Remove existing handlers - mouseDownHandlerRegistration.removeHandler(); - mouseUpHandlerRegistration.removeHandler(); - doubleClickHandlerRegistration.removeHandler(); - contextMenuHandlerRegistration.removeHandler(); - - mouseDownHandlerRegistration = null; - mouseUpHandlerRegistration = null; - doubleClickHandlerRegistration = null; - contextMenuHandlerRegistration = null; - } - } - - } - - /** - * Registers the given handler to the widget so that the necessary events - * are passed to this {@link ClickEventHandler}. - * <p> - * By default registers the handler with the connector root widget. - * </p> - * - * @param <H> - * @param handler - * The handler to register - * @param type - * The type of the handler. - * @return A reference for the registration of the handler. - */ - protected <H extends EventHandler> HandlerRegistration registerHandler( - final H handler, DomEvent.Type<H> type) { - return connector.getWidget().addDomHandler(handler, type); - } - - /** - * Checks if there is a server side event listener registered for clicks - * - * @return true if there is a server side event listener registered, false - * otherwise - */ - public boolean hasEventListener() { - return connector.hasEventListener(clickEventIdentifier); - } - - /** - * Event handler for context menu. Prevents the browser context menu from - * popping up if there is a listener for right clicks. - */ - - @Override - public void onContextMenu(ContextMenuEvent event) { - if (hasEventListener() && shouldFireEvent(event)) { - // Prevent showing the browser's context menu when there is a right - // click listener. - event.preventDefault(); - } - } - - @Override - public void onMouseDown(MouseDownEvent event) { - /* - * When getting a mousedown event, we must detect where the - * corresponding mouseup event if it's on a different part of the page. - */ - lastMouseDownTarget = event.getNativeEvent().getEventTarget(); - mouseUpPreviewMatched = false; - mouseUpEventPreviewRegistration = Event - .addNativePreviewHandler(mouseUpPreviewHandler); - } - - @Override - public void onMouseUp(MouseUpEvent event) { - /* - * Only fire a click if the mouseup hits the same element as the - * corresponding mousedown. This is first checked in the event preview - * but we can't fire the even there as the event might get canceled - * before it gets here. - */ - if (hasEventListener() - && mouseUpPreviewMatched - && lastMouseDownTarget != null - && Util.getElementUnderMouse(event.getNativeEvent()) == lastMouseDownTarget - && shouldFireEvent(event)) { - // "Click" with left, right or middle button - fireClick(event.getNativeEvent()); - } - mouseUpPreviewMatched = false; - lastMouseDownTarget = null; - } - - /** - * Sends the click event based on the given native event. - * - * @param event - * The native event that caused this click event - */ - protected abstract void fireClick(NativeEvent event); - - /** - * Called before firing a click event. Allows sub classes to decide if this - * in an event that should cause an event or not. - * - * @param event - * The user event - * @return true if the event should be fired, false otherwise - */ - protected boolean shouldFireEvent(DomEvent<?> event) { - return true; - } - - /** - * Event handler for double clicks. Used to fire double click events. Note - * that browsers typically fail to prevent the second click event so a - * double click will result in two click events and one double click event. - */ - - @Override - public void onDoubleClick(DoubleClickEvent event) { - if (hasEventListener() && shouldFireEvent(event)) { - fireClick(event.getNativeEvent()); - } - } - - /** - * Click event calculates and returns coordinates relative to the element - * returned by this method. Default implementation uses the root element of - * the widget. Override to provide a different relative element. - * - * @return The Element used for calculating relative coordinates for a click - * or null if no relative coordinates can be calculated. - */ - protected Element getRelativeToElement() { - return connector.getWidget().getElement(); - } - -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java deleted file mode 100644 index 5741111716..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -import com.google.gwt.dom.client.Element; -import com.google.gwt.user.client.ui.Focusable; -import com.google.gwt.user.client.ui.HasEnabled; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ComponentState; -import com.vaadin.shared.Connector; -import com.vaadin.shared.ui.TabIndexState; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ComponentContainerConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.LayoutManager; -import com.vaadin.terminal.gwt.client.ServerConnector; -import com.vaadin.terminal.gwt.client.TooltipInfo; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.metadata.NoDataException; -import com.vaadin.terminal.gwt.client.metadata.Type; -import com.vaadin.terminal.gwt.client.metadata.TypeData; -import com.vaadin.terminal.gwt.client.ui.UI.UIConnector; -import com.vaadin.terminal.gwt.client.ui.datefield.PopupDateFieldConnector; - -public abstract class AbstractComponentConnector extends AbstractConnector - implements ComponentConnector { - - private Widget widget; - - private String lastKnownWidth = ""; - private String lastKnownHeight = ""; - - /** - * The style names from getState().getStyles() which are currently applied - * to the widget. - */ - protected List<String> styleNames = new ArrayList<String>(); - - /** - * Default constructor - */ - public AbstractComponentConnector() { - } - - @Override - protected void init() { - super.init(); - - getConnection().getVTooltip().connectHandlersToWidget(getWidget()); - - // Set v-connector style names for the widget - getWidget().setStyleName("v-connector", true); - } - - /** - * Creates and returns the widget for this VPaintableWidget. This method - * should only be called once when initializing the paintable. - * - * @return - */ - protected Widget createWidget() { - Type type = TypeData.getType(getClass()); - try { - Type widgetType = type.getMethod("getWidget").getReturnType(); - Object instance = widgetType.createInstance(); - return (Widget) instance; - } catch (NoDataException e) { - throw new IllegalStateException( - "There is no information about the widget for " - + Util.getSimpleName(this) - + ". Did you remember to compile the right widgetset?", - e); - } - } - - /** - * Returns the widget associated with this paintable. The widget returned by - * this method must not changed during the life time of the paintable. - * - * @return The widget associated with this paintable - */ - @Override - public Widget getWidget() { - if (widget == null) { - widget = createWidget(); - } - - return widget; - } - - @Deprecated - public static boolean isRealUpdate(UIDL uidl) { - return !uidl.hasAttribute("cached"); - } - - @Override - public ComponentState getState() { - return (ComponentState) super.getState(); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - ConnectorMap paintableMap = ConnectorMap.get(getConnection()); - - if (getState().getId() != null) { - getWidget().getElement().setId(getState().getId()); - } else { - getWidget().getElement().removeAttribute("id"); - - } - - /* - * Disabled state may affect (override) tabindex so the order must be - * first setting tabindex, then enabled state (through super - * implementation). - */ - if (getState() instanceof TabIndexState - && getWidget() instanceof Focusable) { - ((Focusable) getWidget()).setTabIndex(((TabIndexState) getState()) - .getTabIndex()); - } - - super.onStateChanged(stateChangeEvent); - - // Style names - updateWidgetStyleNames(); - - // Set captions - if (delegateCaptionHandling()) { - ServerConnector parent = getParent(); - if (parent instanceof ComponentContainerConnector) { - ((ComponentContainerConnector) parent).updateCaption(this); - } else if (parent == null && !(this instanceof UIConnector)) { - VConsole.error("Parent of connector " - + Util.getConnectorString(this) - + " is null. This is typically an indication of a broken component hierarchy"); - } - } - - /* - * updateComponentSize need to be after caption update so caption can be - * taken into account - */ - - updateComponentSize(); - } - - @Override - public void setWidgetEnabled(boolean widgetEnabled) { - // add or remove v-disabled style name from the widget - setWidgetStyleName(ApplicationConnection.DISABLED_CLASSNAME, - !widgetEnabled); - - if (getWidget() instanceof HasEnabled) { - // set widget specific enabled state - ((HasEnabled) getWidget()).setEnabled(widgetEnabled); - - // make sure the caption has or has not v-disabled style - if (delegateCaptionHandling()) { - ServerConnector parent = getParent(); - if (parent instanceof ComponentContainerConnector) { - ((ComponentContainerConnector) parent).updateCaption(this); - } else if (parent == null && !(this instanceof UIConnector)) { - VConsole.error("Parent of connector " - + Util.getConnectorString(this) - + " is null. This is typically an indication of a broken component hierarchy"); - } - } - } - } - - private void updateComponentSize() { - String newWidth = getState().getWidth(); - String newHeight = getState().getHeight(); - - // Parent should be updated if either dimension changed between relative - // and non-relative - if (newWidth.endsWith("%") != lastKnownWidth.endsWith("%")) { - Connector parent = getParent(); - if (parent instanceof ManagedLayout) { - getLayoutManager().setNeedsHorizontalLayout( - (ManagedLayout) parent); - } - } - - if (newHeight.endsWith("%") != lastKnownHeight.endsWith("%")) { - Connector parent = getParent(); - if (parent instanceof ManagedLayout) { - getLayoutManager().setNeedsVerticalLayout( - (ManagedLayout) parent); - } - } - - lastKnownWidth = newWidth; - lastKnownHeight = newHeight; - - // Set defined sizes - Widget widget = getWidget(); - - widget.setStyleName("v-has-width", !isUndefinedWidth()); - widget.setStyleName("v-has-height", !isUndefinedHeight()); - - widget.setHeight(newHeight); - widget.setWidth(newWidth); - } - - @Override - public boolean isRelativeHeight() { - return getState().getHeight().endsWith("%"); - } - - @Override - public boolean isRelativeWidth() { - return getState().getWidth().endsWith("%"); - } - - @Override - public boolean isUndefinedHeight() { - return getState().getHeight().length() == 0; - } - - @Override - public boolean isUndefinedWidth() { - return getState().getWidth().length() == 0; - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ComponentConnector#delegateCaptionHandling - * () - */ - @Override - public boolean delegateCaptionHandling() { - return true; - } - - /** - * Updates the user defined, read-only and error style names for the widget - * based the shared state. User defined style names are prefixed with the - * primary style name of the widget returned by {@link #getWidget()} - * <p> - * This method can be overridden to provide additional style names for the - * component, for example see - * {@link AbstractFieldConnector#updateWidgetStyleNames()} - * </p> - */ - protected void updateWidgetStyleNames() { - ComponentState state = getState(); - - String primaryStyleName = getWidget().getStylePrimaryName(); - - // should be in AbstractFieldConnector ? - // add / remove read-only style name - setWidgetStyleName("v-readonly", isReadOnly()); - - // add / remove error style name - setWidgetStyleNameWithPrefix(primaryStyleName, - ApplicationConnection.ERROR_CLASSNAME_EXT, - null != state.getErrorMessage()); - - // add additional user defined style names as class names, prefixed with - // component default class name. remove nonexistent style names. - if (state.hasStyles()) { - // add new style names - List<String> newStyles = new ArrayList<String>(); - newStyles.addAll(state.getStyles()); - newStyles.removeAll(styleNames); - for (String newStyle : newStyles) { - setWidgetStyleName(newStyle, true); - setWidgetStyleNameWithPrefix(primaryStyleName + "-", newStyle, - true); - } - // remove nonexistent style names - styleNames.removeAll(state.getStyles()); - for (String oldStyle : styleNames) { - setWidgetStyleName(oldStyle, false); - setWidgetStyleNameWithPrefix(primaryStyleName + "-", oldStyle, - false); - } - styleNames.clear(); - styleNames.addAll(state.getStyles()); - } else { - // remove all old style names - for (String oldStyle : styleNames) { - setWidgetStyleName(oldStyle, false); - setWidgetStyleNameWithPrefix(primaryStyleName + "-", oldStyle, - false); - } - styleNames.clear(); - } - - } - - /** - * This is used to add / remove state related style names from the widget. - * <p> - * Override this method for example if the style name given here should be - * updated in another widget in addition to the one returned by the - * {@link #getWidget()}. - * </p> - * - * @param styleName - * the style name to be added or removed - * @param add - * <code>true</code> to add the given style, <code>false</code> - * to remove it - */ - protected void setWidgetStyleName(String styleName, boolean add) { - getWidget().setStyleName(styleName, add); - } - - /** - * This is used to add / remove state related prefixed style names from the - * widget. - * <p> - * Override this method if the prefixed style name given here should be - * updated in another widget in addition to the one returned by the - * <code>Connector</code>'s {@link #getWidget()}, or if the prefix should be - * different. For example see - * {@link PopupDateFieldConnector#setWidgetStyleNameWithPrefix(String, String, boolean)} - * </p> - * - * @param styleName - * the style name to be added or removed - * @param add - * <code>true</code> to add the given style, <code>false</code> - * to remove it - * @deprecated This will be removed once styles are no longer added with - * prefixes. - */ - @Deprecated - protected void setWidgetStyleNameWithPrefix(String prefix, - String styleName, boolean add) { - if (!styleName.startsWith("-")) { - if (!prefix.endsWith("-")) { - prefix += "-"; - } - } else { - if (prefix.endsWith("-")) { - styleName.replaceFirst("-", ""); - } - } - getWidget().setStyleName(prefix + styleName, add); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.ComponentConnector#isReadOnly() - */ - @Override - @Deprecated - public boolean isReadOnly() { - return getState().isReadOnly(); - } - - @Override - public LayoutManager getLayoutManager() { - return LayoutManager.get(getConnection()); - } - - /** - * Checks if there is a registered server side listener for the given event - * identifier. - * - * @param eventIdentifier - * The identifier to check for - * @return true if an event listener has been registered with the given - * event identifier on the server side, false otherwise - */ - @Override - public boolean hasEventListener(String eventIdentifier) { - Set<String> reg = getState().getRegisteredEventListeners(); - return (reg != null && reg.contains(eventIdentifier)); - } - - @Override - public void updateEnabledState(boolean enabledState) { - super.updateEnabledState(enabledState); - - setWidgetEnabled(isEnabled()); - } - - @Override - public void onUnregister() { - super.onUnregister(); - - // Show an error if widget is still attached to DOM. It should never be - // at this point. - if (getWidget() != null && getWidget().isAttached()) { - getWidget().removeFromParent(); - VConsole.error("Widget is still attached to the DOM after the connector (" - + Util.getConnectorString(this) - + ") has been unregistered. Widget was removed."); - } - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ComponentConnector#getTooltipInfo(com. - * google.gwt.dom.client.Element) - */ - @Override - public TooltipInfo getTooltipInfo(Element element) { - return new TooltipInfo(getState().getDescription(), getState() - .getErrorMessage()); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentContainerConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentContainerConnector.java deleted file mode 100644 index 16eab60a75..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentContainerConnector.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import java.util.Collections; -import java.util.List; - -import com.google.gwt.event.shared.HandlerRegistration; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ComponentContainerConnector; -import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; -import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent.ConnectorHierarchyChangeHandler; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VConsole; - -public abstract class AbstractComponentContainerConnector extends - AbstractComponentConnector implements ComponentContainerConnector, - ConnectorHierarchyChangeHandler { - - List<ComponentConnector> childComponents; - - private final boolean debugLogging = false; - - /** - * Default constructor - */ - public AbstractComponentContainerConnector() { - addConnectorHierarchyChangeHandler(this); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ComponentContainerConnector#getChildren() - */ - @Override - public List<ComponentConnector> getChildComponents() { - if (childComponents == null) { - return Collections.emptyList(); - } - - return childComponents; - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ComponentContainerConnector#setChildren - * (java.util.Collection) - */ - @Override - public void setChildComponents(List<ComponentConnector> childComponents) { - this.childComponents = childComponents; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.ComponentContainerConnector# - * connectorHierarchyChanged - * (com.vaadin.terminal.gwt.client.ConnectorHierarchyChangedEvent) - */ - @Override - public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { - if (debugLogging) { - VConsole.log("Hierarchy changed for " - + Util.getConnectorString(this)); - String oldChildren = "* Old children: "; - for (ComponentConnector child : event.getOldChildren()) { - oldChildren += Util.getConnectorString(child) + " "; - } - VConsole.log(oldChildren); - - String newChildren = "* New children: "; - for (ComponentConnector child : getChildComponents()) { - newChildren += Util.getConnectorString(child) + " "; - } - VConsole.log(newChildren); - } - } - - @Override - public HandlerRegistration addConnectorHierarchyChangeHandler( - ConnectorHierarchyChangeHandler handler) { - return ensureHandlerManager().addHandler( - ConnectorHierarchyChangeEvent.TYPE, handler); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java deleted file mode 100644 index 3a50f0a91e..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.google.gwt.event.shared.GwtEvent; -import com.google.gwt.event.shared.HandlerManager; -import com.google.web.bindery.event.shared.HandlerRegistration; -import com.vaadin.shared.communication.ClientRpc; -import com.vaadin.shared.communication.SharedState; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ServerConnector; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler; -import com.vaadin.terminal.gwt.client.metadata.NoDataException; -import com.vaadin.terminal.gwt.client.metadata.Type; -import com.vaadin.terminal.gwt.client.metadata.TypeData; - -/** - * An abstract implementation of Connector. - * - * @author Vaadin Ltd - * @since 7.0.0 - * - */ -public abstract class AbstractConnector implements ServerConnector, - StateChangeHandler { - - private ApplicationConnection connection; - private String id; - - private HandlerManager handlerManager; - private Map<String, HandlerManager> statePropertyHandlerManagers; - private Map<String, Collection<ClientRpc>> rpcImplementations; - private final boolean debugLogging = false; - - private SharedState state; - private ServerConnector parent; - - /** - * Temporary storage for last enabled state to be able to see if it has - * changed. Can be removed once we are able to listen specifically for - * enabled changes in the state. Widget.isEnabled() cannot be used as all - * Widgets do not implement HasEnabled - */ - private boolean lastEnabledState = true; - private List<ServerConnector> children; - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.VPaintable#getConnection() - */ - @Override - public final ApplicationConnection getConnection() { - return connection; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.Connector#getId() - */ - @Override - public String getConnectorId() { - return id; - } - - /** - * Called once by the framework to initialize the connector. - * <p> - * Note that the shared state is not yet available when this method is - * called. - * <p> - * Connector classes should override {@link #init()} instead of this method. - */ - @Override - public final void doInit(String connectorId, - ApplicationConnection connection) { - this.connection = connection; - id = connectorId; - - addStateChangeHandler(this); - init(); - } - - /** - * Called when the connector has been initialized. Override this method to - * perform initialization of the connector. - */ - // FIXME: It might make sense to make this abstract to force users to - // use init instead of constructor, where connection and id has not yet been - // set. - protected void init() { - - } - - /** - * Registers an implementation for a server to client RPC interface. - * - * Multiple registrations can be made for a single interface, in which case - * all of them receive corresponding RPC calls. - * - * @param rpcInterface - * RPC interface - * @param implementation - * implementation that should receive RPC calls - * @param <T> - * The type of the RPC interface that is being registered - */ - protected <T extends ClientRpc> void registerRpc(Class<T> rpcInterface, - T implementation) { - String rpcInterfaceId = rpcInterface.getName().replaceAll("\\$", "."); - if (null == rpcImplementations) { - rpcImplementations = new HashMap<String, Collection<ClientRpc>>(); - } - if (null == rpcImplementations.get(rpcInterfaceId)) { - rpcImplementations.put(rpcInterfaceId, new ArrayList<ClientRpc>()); - } - rpcImplementations.get(rpcInterfaceId).add(implementation); - } - - /** - * Unregisters an implementation for a server to client RPC interface. - * - * @param rpcInterface - * RPC interface - * @param implementation - * implementation to unregister - */ - protected <T extends ClientRpc> void unregisterRpc(Class<T> rpcInterface, - T implementation) { - String rpcInterfaceId = rpcInterface.getName().replaceAll("\\$", "."); - if (null != rpcImplementations - && null != rpcImplementations.get(rpcInterfaceId)) { - rpcImplementations.get(rpcInterfaceId).remove(implementation); - } - } - - @Override - public <T extends ClientRpc> Collection<T> getRpcImplementations( - String rpcInterfaceId) { - if (null == rpcImplementations) { - return Collections.emptyList(); - } - return (Collection<T>) rpcImplementations.get(rpcInterfaceId); - } - - @Override - public void fireEvent(GwtEvent<?> event) { - if (handlerManager != null) { - handlerManager.fireEvent(event); - } - if (statePropertyHandlerManagers != null - && event instanceof StateChangeEvent) { - for (String property : ((StateChangeEvent) event) - .getChangedProperties()) { - HandlerManager manager = statePropertyHandlerManagers - .get(property); - if (manager != null) { - manager.fireEvent(event); - } - } - } - } - - protected HandlerManager ensureHandlerManager() { - if (handlerManager == null) { - handlerManager = new HandlerManager(this); - } - - return handlerManager; - } - - @Override - public HandlerRegistration addStateChangeHandler(StateChangeHandler handler) { - return ensureHandlerManager() - .addHandler(StateChangeEvent.TYPE, handler); - } - - @Override - public HandlerRegistration addStateChangeHandler(String propertyName, - StateChangeHandler handler) { - return ensureHandlerManager(propertyName).addHandler( - StateChangeEvent.TYPE, handler); - } - - private HandlerManager ensureHandlerManager(String propertyName) { - if (statePropertyHandlerManagers == null) { - statePropertyHandlerManagers = new HashMap<String, HandlerManager>(); - } - HandlerManager manager = statePropertyHandlerManagers.get(propertyName); - if (manager == null) { - manager = new HandlerManager(this); - statePropertyHandlerManagers.put(propertyName, manager); - } - return manager; - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - if (debugLogging) { - VConsole.log("State change event for " - + Util.getConnectorString(stateChangeEvent.getConnector()) - + " received by " + Util.getConnectorString(this)); - } - - updateEnabledState(isEnabled()); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.ServerConnector#onUnregister() - */ - @Override - public void onUnregister() { - if (debugLogging) { - VConsole.log("Unregistered connector " - + Util.getConnectorString(this)); - } - - } - - /** - * Returns the shared state object for this connector. - * - * Override this method to define the shared state type for your connector. - * - * @return the current shared state (never null) - */ - @Override - public SharedState getState() { - if (state == null) { - state = createState(); - } - - return state; - } - - /** - * Creates a state object with default values for this connector. The - * created state object must be compatible with the return type of - * {@link #getState()}. The default implementation creates a state object - * using GWT.create() using the defined return type of {@link #getState()}. - * - * @return A new state object - */ - protected SharedState createState() { - try { - Type stateType = getStateType(this); - Object stateInstance = stateType.createInstance(); - return (SharedState) stateInstance; - } catch (NoDataException e) { - throw new IllegalStateException( - "There is no information about the state for " - + Util.getSimpleName(this) - + ". Did you remember to compile the right widgetset?", - e); - } - - } - - public static Type getStateType(ServerConnector connector) { - try { - return TypeData.getType(connector.getClass()).getMethod("getState") - .getReturnType(); - } catch (NoDataException e) { - throw new IllegalStateException( - "There is no information about the state for " - + Util.getSimpleName(connector) - + ". Did you remember to compile the right widgetset?", - e); - } - } - - @Override - public ServerConnector getParent() { - return parent; - } - - @Override - public void setParent(ServerConnector parent) { - this.parent = parent; - } - - @Override - public List<ServerConnector> getChildren() { - if (children == null) { - return Collections.emptyList(); - } - return children; - } - - @Override - public void setChildren(List<ServerConnector> children) { - this.children = children; - } - - @Override - public boolean isEnabled() { - if (!getState().isEnabled()) { - return false; - } - - if (getParent() == null) { - return true; - } else { - return getParent().isEnabled(); - } - } - - @Override - public void updateEnabledState(boolean enabledState) { - if (lastEnabledState == enabledState) { - return; - } - lastEnabledState = enabledState; - - for (ServerConnector c : getChildren()) { - // Update children as they might be affected by the enabled state of - // their parent - c.updateEnabledState(c.isEnabled()); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractFieldConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractFieldConnector.java deleted file mode 100644 index c007eb8529..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractFieldConnector.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.vaadin.shared.AbstractFieldState; -import com.vaadin.terminal.gwt.client.ApplicationConnection; - -public abstract class AbstractFieldConnector extends AbstractComponentConnector { - - @Override - public AbstractFieldState getState() { - return (AbstractFieldState) super.getState(); - } - - @Override - public boolean isReadOnly() { - return super.isReadOnly() || getState().isPropertyReadOnly(); - } - - public boolean isModified() { - return getState().isModified(); - } - - /** - * Checks whether the required indicator should be shown for the field. - * - * Required indicators are hidden if the field or its data source is - * read-only. - * - * @return true if required indicator should be shown - */ - public boolean isRequired() { - return getState().isRequired() && !isReadOnly(); - } - - @Override - protected void updateWidgetStyleNames() { - super.updateWidgetStyleNames(); - - // add / remove modified style name to Fields - setWidgetStyleName(ApplicationConnection.MODIFIED_CLASSNAME, - isModified()); - - // add / remove error style name to Fields - setWidgetStyleNameWithPrefix(getWidget().getStylePrimaryName(), - ApplicationConnection.REQUIRED_CLASSNAME_EXT, isRequired()); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractLayoutConnector.java deleted file mode 100644 index b8a16d697d..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractLayoutConnector.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.vaadin.shared.ui.AbstractLayoutState; - -public abstract class AbstractLayoutConnector extends - AbstractComponentContainerConnector { - - @Override - public AbstractLayoutState getState() { - return (AbstractLayoutState) super.getState(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/Action.java b/client/src/com/vaadin/terminal/gwt/client/ui/Action.java deleted file mode 100644 index b97599c872..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/Action.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.user.client.Command; -import com.vaadin.terminal.gwt.client.Util; - -/** - * - */ -public abstract class Action implements Command { - - protected ActionOwner owner; - - protected String iconUrl = null; - - protected String caption = ""; - - public Action(ActionOwner owner) { - this.owner = owner; - } - - /** - * Executed when action fired - */ - @Override - public abstract void execute(); - - public String getHTML() { - final StringBuffer sb = new StringBuffer(); - sb.append("<div>"); - if (getIconUrl() != null) { - sb.append("<img src=\"" + Util.escapeAttribute(getIconUrl()) - + "\" alt=\"icon\" />"); - } - sb.append(getCaption()); - sb.append("</div>"); - return sb.toString(); - } - - public String getCaption() { - return caption; - } - - public void setCaption(String caption) { - this.caption = caption; - } - - public String getIconUrl() { - return iconUrl; - } - - public void setIconUrl(String url) { - iconUrl = url; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/ActionOwner.java b/client/src/com/vaadin/terminal/gwt/client/ui/ActionOwner.java deleted file mode 100644 index bb714d1081..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/ActionOwner.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.vaadin.terminal.gwt.client.ApplicationConnection; - -public interface ActionOwner { - - /** - * @return Array of IActions - */ - public Action[] getActions(); - - public ApplicationConnection getClient(); - - public String getPaintableId(); - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/CalendarEntry.java b/client/src/com/vaadin/terminal/gwt/client/ui/CalendarEntry.java deleted file mode 100644 index 72c7bea806..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/CalendarEntry.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui; - -import java.util.Date; - -import com.vaadin.terminal.gwt.client.DateTimeService; - -public class CalendarEntry { - private final String styleName; - private Date start; - private Date end; - private String title; - private String description; - private boolean notime; - - @SuppressWarnings("deprecation") - public CalendarEntry(String styleName, Date start, Date end, String title, - String description, boolean notime) { - this.styleName = styleName; - if (notime) { - Date d = new Date(start.getTime()); - d.setSeconds(0); - d.setMinutes(0); - this.start = d; - if (end != null) { - d = new Date(end.getTime()); - d.setSeconds(0); - d.setMinutes(0); - this.end = d; - } else { - end = start; - } - } else { - this.start = start; - this.end = end; - } - this.title = title; - this.description = description; - this.notime = notime; - } - - public CalendarEntry(String styleName, Date start, Date end, String title, - String description) { - this(styleName, start, end, title, description, false); - } - - public String getStyleName() { - return styleName; - } - - public Date getStart() { - return start; - } - - public void setStart(Date start) { - this.start = start; - } - - public Date getEnd() { - return end; - } - - public void setEnd(Date end) { - this.end = end; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public boolean isNotime() { - return notime; - } - - public void setNotime(boolean notime) { - this.notime = notime; - } - - @SuppressWarnings("deprecation") - public String getStringForDate(Date d) { - // TODO format from DateTimeService - String s = ""; - if (!notime) { - if (!DateTimeService.isSameDay(d, start)) { - s += (start.getYear() + 1900) + "." + (start.getMonth() + 1) - + "." + start.getDate() + " "; - } - int i = start.getHours(); - s += (i < 10 ? "0" : "") + i; - s += ":"; - i = start.getMinutes(); - s += (i < 10 ? "0" : "") + i; - if (!start.equals(end)) { - s += " - "; - if (!DateTimeService.isSameDay(start, end)) { - s += (end.getYear() + 1900) + "." + (end.getMonth() + 1) - + "." + end.getDate() + " "; - } - i = end.getHours(); - s += (i < 10 ? "0" : "") + i; - s += ":"; - i = end.getMinutes(); - s += (i < 10 ? "0" : "") + i; - } - s += " "; - } - if (title != null) { - s += title; - } - return s; - } - -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java b/client/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java deleted file mode 100644 index 5614837615..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.dom.client.NativeEvent; -import com.vaadin.shared.EventId; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder; - -public abstract class ClickEventHandler extends AbstractClickEventHandler { - - public ClickEventHandler(ComponentConnector connector) { - this(connector, EventId.CLICK_EVENT_IDENTIFIER); - } - - public ClickEventHandler(ComponentConnector connector, - String clickEventIdentifier) { - super(connector, clickEventIdentifier); - } - - /** - * Sends the click event based on the given native event. Delegates actual - * sending to {@link #fireClick(MouseEventDetails)}. - * - * @param event - * The native event that caused this click event - */ - @Override - protected void fireClick(NativeEvent event) { - MouseEventDetails mouseDetails = MouseEventDetailsBuilder - .buildMouseEventDetails(event, getRelativeToElement()); - fireClick(event, mouseDetails); - } - - /** - * Sends the click event to the server. Must be implemented by sub classes, - * typically by calling an RPC method. - * - * @param event - * The event that caused this click to be fired - * - * @param mouseDetails - * The mouse details for the event - */ - protected abstract void fireClick(NativeEvent event, - MouseEventDetails mouseDetails); - -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/Field.java b/client/src/com/vaadin/terminal/gwt/client/ui/Field.java deleted file mode 100644 index b81e365608..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/Field.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client.ui; - -/** - * This interface indicates that the component is a Field (serverside), and - * wants (for instance) to automatically get the v-modified classname. - * - */ -public interface Field { - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/FocusElementPanel.java b/client/src/com/vaadin/terminal/gwt/client/ui/FocusElementPanel.java deleted file mode 100644 index 6a86ab5679..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/FocusElementPanel.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.dom.client.DivElement; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Position; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.Widget; -import com.google.gwt.user.client.ui.impl.FocusImpl; - -/** - * A panel that contains an always visible 0x0 size element that holds the focus - */ -public class FocusElementPanel extends SimpleFocusablePanel { - - private DivElement focusElement; - - public FocusElementPanel() { - focusElement = Document.get().createDivElement(); - } - - @Override - public void setWidget(Widget w) { - super.setWidget(w); - if (focusElement.getParentElement() == null) { - Style style = focusElement.getStyle(); - style.setPosition(Position.FIXED); - style.setTop(0, Unit.PX); - style.setLeft(0, Unit.PX); - getElement().appendChild(focusElement); - /* Sink from focusElement too as focus and blur don't bubble */ - DOM.sinkEvents( - (com.google.gwt.user.client.Element) focusElement.cast(), - Event.FOCUSEVENTS); - // revert to original, not focusable - getElement().setPropertyObject("tabIndex", null); - } else { - moveFocusElementAfterWidget(); - } - } - - /** - * Helper to keep focus element always in domChild[1]. Aids testing. - */ - private void moveFocusElementAfterWidget() { - getElement().insertAfter(focusElement, getWidget().getElement()); - } - - @Override - public void setFocus(boolean focus) { - if (focus) { - FocusImpl.getFocusImplForPanel().focus( - (Element) focusElement.cast()); - } else { - FocusImpl.getFocusImplForPanel() - .blur((Element) focusElement.cast()); - } - } - - @Override - public void setTabIndex(int tabIndex) { - getElement().setTabIndex(-1); - if (focusElement != null) { - focusElement.setTabIndex(tabIndex); - } - } - - /** - * @return the focus element - */ - public Element getFocusElement() { - return focusElement.cast(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/FocusableFlexTable.java b/client/src/com/vaadin/terminal/gwt/client/ui/FocusableFlexTable.java deleted file mode 100644 index 8ad7002a79..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/FocusableFlexTable.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.HasBlurHandlers; -import com.google.gwt.event.dom.client.HasFocusHandlers; -import com.google.gwt.event.dom.client.HasKeyDownHandlers; -import com.google.gwt.event.dom.client.HasKeyPressHandlers; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.ui.FlexTable; -import com.google.gwt.user.client.ui.impl.FocusImpl; -import com.vaadin.terminal.gwt.client.Focusable; - -/** - * Adds keyboard focus to {@link FlexPanel}. - */ -public class FocusableFlexTable extends FlexTable implements HasFocusHandlers, - HasBlurHandlers, HasKeyDownHandlers, HasKeyPressHandlers, Focusable { - - /** - * Default constructor. - */ - public FocusableFlexTable() { - // make focusable, as we don't need access key magic we don't need to - // use FocusImpl.createFocusable - getElement().setTabIndex(0); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasFocusHandlers#addFocusHandler(com. - * google.gwt.event.dom.client.FocusHandler) - */ - @Override - public HandlerRegistration addFocusHandler(FocusHandler handler) { - return addDomHandler(handler, FocusEvent.getType()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasBlurHandlers#addBlurHandler(com.google - * .gwt.event.dom.client.BlurHandler) - */ - @Override - public HandlerRegistration addBlurHandler(BlurHandler handler) { - return addDomHandler(handler, BlurEvent.getType()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasKeyDownHandlers#addKeyDownHandler( - * com.google.gwt.event.dom.client.KeyDownHandler) - */ - @Override - public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) { - return addDomHandler(handler, KeyDownEvent.getType()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasKeyPressHandlers#addKeyPressHandler - * (com.google.gwt.event.dom.client.KeyPressHandler) - */ - @Override - public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) { - return addDomHandler(handler, KeyPressEvent.getType()); - } - - /** - * Sets the keyboard focus to the panel - * - * @param focus - * Should the panel have keyboard focus. If true the keyboard - * focus will be moved to the - */ - public void setFocus(boolean focus) { - if (focus) { - FocusImpl.getFocusImplForPanel().focus(getElement()); - } else { - FocusImpl.getFocusImplForPanel().blur(getElement()); - } - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.Focusable#focus() - */ - @Override - public void focus() { - setFocus(true); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/FocusableFlowPanel.java b/client/src/com/vaadin/terminal/gwt/client/ui/FocusableFlowPanel.java deleted file mode 100644 index c162a750ce..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/FocusableFlowPanel.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.HasBlurHandlers; -import com.google.gwt.event.dom.client.HasFocusHandlers; -import com.google.gwt.event.dom.client.HasKeyDownHandlers; -import com.google.gwt.event.dom.client.HasKeyPressHandlers; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.impl.FocusImpl; -import com.vaadin.terminal.gwt.client.Focusable; - -public class FocusableFlowPanel extends FlowPanel implements HasFocusHandlers, - HasBlurHandlers, HasKeyDownHandlers, HasKeyPressHandlers, Focusable { - - /** - * Constructor - */ - public FocusableFlowPanel() { - // make focusable, as we don't need access key magic we don't need to - // use FocusImpl.createFocusable - getElement().setTabIndex(0); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasFocusHandlers#addFocusHandler(com. - * google.gwt.event.dom.client.FocusHandler) - */ - @Override - public HandlerRegistration addFocusHandler(FocusHandler handler) { - return addDomHandler(handler, FocusEvent.getType()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasBlurHandlers#addBlurHandler(com.google - * .gwt.event.dom.client.BlurHandler) - */ - @Override - public HandlerRegistration addBlurHandler(BlurHandler handler) { - return addDomHandler(handler, BlurEvent.getType()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasKeyDownHandlers#addKeyDownHandler( - * com.google.gwt.event.dom.client.KeyDownHandler) - */ - @Override - public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) { - return addDomHandler(handler, KeyDownEvent.getType()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasKeyPressHandlers#addKeyPressHandler - * (com.google.gwt.event.dom.client.KeyPressHandler) - */ - @Override - public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) { - return addDomHandler(handler, KeyPressEvent.getType()); - } - - /** - * Sets/Removes the keyboard focus to the panel. - * - * @param focus - * If set to true then the focus is moved to the panel, if set to - * false the focus is removed - */ - public void setFocus(boolean focus) { - if (focus) { - FocusImpl.getFocusImplForPanel().focus(getElement()); - } else { - FocusImpl.getFocusImplForPanel().blur(getElement()); - } - } - - /** - * Focus the panel - */ - @Override - public void focus() { - setFocus(true); - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java b/client/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java deleted file mode 100644 index d20b3e9e65..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import java.util.ArrayList; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.dom.client.DivElement; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Overflow; -import com.google.gwt.dom.client.Style.Position; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.event.dom.client.HasScrollHandlers; -import com.google.gwt.event.dom.client.ScrollEvent; -import com.google.gwt.event.dom.client.ScrollHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.ScrollPanel; -import com.google.gwt.user.client.ui.Widget; -import com.google.gwt.user.client.ui.impl.FocusImpl; -import com.vaadin.terminal.gwt.client.BrowserInfo; - -/** - * A scrollhandlers similar to {@link ScrollPanel}. - * - */ -public class FocusableScrollPanel extends SimpleFocusablePanel implements - HasScrollHandlers, ScrollHandler { - - public FocusableScrollPanel() { - // Prevent IE standard mode bug when a AbsolutePanel is contained. - TouchScrollDelegate.enableTouchScrolling(this, getElement()); - Style style = getElement().getStyle(); - style.setProperty("zoom", "1"); - style.setPosition(Position.RELATIVE); - } - - private DivElement focusElement; - - public FocusableScrollPanel(boolean useFakeFocusElement) { - this(); - if (useFakeFocusElement) { - focusElement = Document.get().createDivElement(); - } - } - - private boolean useFakeFocusElement() { - return focusElement != null; - } - - @Override - public void setWidget(Widget w) { - super.setWidget(w); - if (useFakeFocusElement()) { - if (focusElement.getParentElement() == null) { - Style style = focusElement.getStyle(); - style.setPosition(Position.FIXED); - style.setTop(0, Unit.PX); - style.setLeft(0, Unit.PX); - getElement().appendChild(focusElement); - /* Sink from focusElemet too as focusa and blur don't bubble */ - DOM.sinkEvents( - (com.google.gwt.user.client.Element) focusElement - .cast(), Event.FOCUSEVENTS); - // revert to original, not focusable - getElement().setPropertyObject("tabIndex", null); - - } else { - moveFocusElementAfterWidget(); - } - } - } - - /** - * Helper to keep focus element always in domChild[1]. Aids testing. - */ - private void moveFocusElementAfterWidget() { - getElement().insertAfter(focusElement, getWidget().getElement()); - } - - @Override - public void setFocus(boolean focus) { - if (useFakeFocusElement()) { - if (focus) { - FocusImpl.getFocusImplForPanel().focus( - (Element) focusElement.cast()); - } else { - FocusImpl.getFocusImplForPanel().blur( - (Element) focusElement.cast()); - } - } else { - super.setFocus(focus); - } - } - - @Override - public void setTabIndex(int tabIndex) { - if (useFakeFocusElement()) { - getElement().setTabIndex(-1); - if (focusElement != null) { - focusElement.setTabIndex(tabIndex); - } - } else { - super.setTabIndex(tabIndex); - } - } - - @Override - public HandlerRegistration addScrollHandler(ScrollHandler handler) { - return addDomHandler(handler, ScrollEvent.getType()); - } - - /** - * Gets the horizontal scroll position. - * - * @return the horizontal scroll position, in pixels - */ - public int getHorizontalScrollPosition() { - return getElement().getScrollLeft(); - } - - /** - * Gets the vertical scroll position. - * - * @return the vertical scroll position, in pixels - */ - public int getScrollPosition() { - if (getElement().getPropertyJSO("_vScrollTop") != null) { - return getElement().getPropertyInt("_vScrollTop"); - } else { - return getElement().getScrollTop(); - } - } - - /** - * Sets the horizontal scroll position. - * - * @param position - * the new horizontal scroll position, in pixels - */ - public void setHorizontalScrollPosition(int position) { - getElement().setScrollLeft(position); - } - - /** - * Sets the vertical scroll position. - * - * @param position - * the new vertical scroll position, in pixels - */ - public void setScrollPosition(int position) { - if (BrowserInfo.get().isAndroidWithBrokenScrollTop() - && BrowserInfo.get().requiresTouchScrollDelegate()) { - ArrayList<com.google.gwt.dom.client.Element> elements = TouchScrollDelegate - .getElements(getElement()); - for (com.google.gwt.dom.client.Element el : elements) { - final Style style = el.getStyle(); - style.setProperty("webkitTransform", "translate3d(0px," - + -position + "px,0px)"); - } - getElement().setPropertyInt("_vScrollTop", position); - } else { - getElement().setScrollTop(position); - } - } - - @Override - public void onScroll(ScrollEvent event) { - Scheduler.get().scheduleDeferred(new ScheduledCommand() { - @Override - public void execute() { - focusElement.getStyle().setTop(getScrollPosition(), Unit.PX); - focusElement.getStyle().setLeft(getHorizontalScrollPosition(), - Unit.PX); - } - }); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/Icon.java b/client/src/com/vaadin/terminal/gwt/client/ui/Icon.java deleted file mode 100644 index 21ee5bea93..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/Icon.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.UIObject; -import com.vaadin.terminal.gwt.client.ApplicationConnection; - -public class Icon extends UIObject { - public static final String CLASSNAME = "v-icon"; - private final ApplicationConnection client; - private String myUri; - - public Icon(ApplicationConnection client) { - setElement(DOM.createImg()); - DOM.setElementProperty(getElement(), "alt", ""); - setStyleName(CLASSNAME); - this.client = client; - } - - public Icon(ApplicationConnection client, String uidlUri) { - this(client); - setUri(uidlUri); - } - - public void setUri(String uidlUri) { - if (!uidlUri.equals(myUri)) { - /* - * Start sinking onload events, widgets responsibility to react. We - * must do this BEFORE we set src as IE fires the event immediately - * if the image is found in cache (#2592). - */ - sinkEvents(Event.ONLOAD); - - String uri = client.translateVaadinUri(uidlUri); - DOM.setElementProperty(getElement(), "src", uri); - myUri = uidlUri; - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java deleted file mode 100644 index 4ab7c45161..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.JavaScriptComponentState; -import com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper; -import com.vaadin.terminal.gwt.client.communication.HasJavaScriptConnectorHelper; -import com.vaadin.ui.AbstractJavaScriptComponent; - -@Connect(AbstractJavaScriptComponent.class) -public final class JavaScriptComponentConnector extends - AbstractComponentConnector implements HasJavaScriptConnectorHelper { - - private final JavaScriptConnectorHelper helper = new JavaScriptConnectorHelper( - this) { - @Override - protected void showInitProblem( - java.util.ArrayList<String> attemptedNames) { - getWidget().showNoInitFound(attemptedNames); - } - }; - - @Override - public JavaScriptWidget getWidget() { - return (JavaScriptWidget) super.getWidget(); - } - - @Override - protected void init() { - super.init(); - helper.init(); - } - - @Override - public JavaScriptConnectorHelper getJavascriptConnectorHelper() { - return helper; - } - - @Override - public JavaScriptComponentState getState() { - return (JavaScriptComponentState) super.getState(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/JavaScriptWidget.java b/client/src/com/vaadin/terminal/gwt/client/ui/JavaScriptWidget.java deleted file mode 100644 index 8e59115671..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/JavaScriptWidget.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import java.util.ArrayList; - -import com.google.gwt.dom.client.Document; -import com.google.gwt.user.client.ui.Widget; - -public class JavaScriptWidget extends Widget { - public JavaScriptWidget() { - setElement(Document.get().createDivElement()); - } - - public void showNoInitFound(ArrayList<String> attemptedNames) { - String message = "Could not initialize JavaScriptConnector because no JavaScript init function was found. Make sure one of these functions are defined: <ul>"; - for (String name : attemptedNames) { - message += "<li>" + name + "</li>"; - } - message += "</ul>"; - - getElement().setInnerHTML(message); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/LayoutClickEventHandler.java b/client/src/com/vaadin/terminal/gwt/client/ui/LayoutClickEventHandler.java deleted file mode 100644 index 63c3c84ce4..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/LayoutClickEventHandler.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.user.client.Element; -import com.vaadin.shared.EventId; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.LayoutClickRpc; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder; - -public abstract class LayoutClickEventHandler extends AbstractClickEventHandler { - - public LayoutClickEventHandler(ComponentConnector connector) { - this(connector, EventId.LAYOUT_CLICK_EVENT_IDENTIFIER); - } - - public LayoutClickEventHandler(ComponentConnector connector, - String clickEventIdentifier) { - super(connector, clickEventIdentifier); - } - - protected abstract ComponentConnector getChildComponent(Element element); - - protected ComponentConnector getChildComponent(NativeEvent event) { - return getChildComponent((Element) event.getEventTarget().cast()); - } - - @Override - protected void fireClick(NativeEvent event) { - MouseEventDetails mouseDetails = MouseEventDetailsBuilder - .buildMouseEventDetails(event, getRelativeToElement()); - getLayoutClickRPC().layoutClick(mouseDetails, getChildComponent(event)); - } - - protected abstract LayoutClickRpc getLayoutClickRPC(); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/ManagedLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/ManagedLayout.java deleted file mode 100644 index bdb01113d6..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/ManagedLayout.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.vaadin.terminal.gwt.client.ComponentConnector; - -public interface ManagedLayout extends ComponentConnector { - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/MediaBaseConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/MediaBaseConnector.java deleted file mode 100644 index 33d97f4ed8..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/MediaBaseConnector.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.vaadin.shared.communication.URLReference; -import com.vaadin.shared.ui.AbstractMediaState; -import com.vaadin.shared.ui.MediaControl; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; - -public abstract class MediaBaseConnector extends AbstractComponentConnector { - - @Override - protected void init() { - super.init(); - - registerRpc(MediaControl.class, new MediaControl() { - @Override - public void play() { - getWidget().play(); - } - - @Override - public void pause() { - getWidget().pause(); - } - }); - } - - @Override - public AbstractMediaState getState() { - return (AbstractMediaState) super.getState(); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - for (int i = 0; i < getState().getSources().size(); i++) { - URLReference source = getState().getSources().get(i); - String sourceType = getState().getSourceTypes().get(i); - getWidget().addSource(source.getURL(), sourceType); - } - setAltText(getState().getAltText()); - } - - @Override - public VMediaBase getWidget() { - return (VMediaBase) super.getWidget(); - } - - private void setAltText(String altText) { - - if (altText == null || "".equals(altText)) { - altText = getDefaultAltHtml(); - } else if (!getState().isHtmlContentAllowed()) { - altText = Util.escapeHTML(altText); - } - getWidget().setAltText(altText); - } - - /** - * @return the default HTML to show users with browsers that do not support - * HTML5 media markup. - */ - protected abstract String getDefaultAltHtml(); - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/PostLayoutListener.java b/client/src/com/vaadin/terminal/gwt/client/ui/PostLayoutListener.java deleted file mode 100644 index a56c464ad2..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/PostLayoutListener.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -public interface PostLayoutListener { - public void postLayout(); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/ShortcutActionHandler.java b/client/src/com/vaadin/terminal/gwt/client/ui/ShortcutActionHandler.java deleted file mode 100644 index 65ea7579fd..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/ShortcutActionHandler.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui; - -import java.util.ArrayList; -import java.util.Iterator; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.HasWidgets; -import com.google.gwt.user.client.ui.KeyboardListener; -import com.google.gwt.user.client.ui.KeyboardListenerCollection; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.richtextarea.VRichTextArea; - -/** - * A helper class to implement keyboard shorcut handling. Keeps a list of owners - * actions and fires actions to server. User class needs to delegate keyboard - * events to handleKeyboardEvents function. - * - * @author Vaadin Ltd - */ -public class ShortcutActionHandler { - - /** - * An interface implemented by those users of this helper class that want to - * support special components like {@link VRichTextArea} that don't properly - * propagate key down events. Those components can build support for - * shortcut actions by traversing the closest - * {@link ShortcutActionHandlerOwner} from the component hierarchy an - * passing keydown events to {@link ShortcutActionHandler}. - */ - public interface ShortcutActionHandlerOwner extends HasWidgets { - - /** - * Returns the ShortCutActionHandler currently used or null if there is - * currently no shortcutactionhandler - */ - ShortcutActionHandler getShortcutActionHandler(); - } - - /** - * A focusable {@link ComponentConnector} implementing this interface will - * be notified before shortcut actions are handled if it will be the target - * of the action (most commonly means it is the focused component during the - * keyboard combination is triggered by the user). - */ - public interface BeforeShortcutActionListener extends ComponentConnector { - /** - * This method is called by ShortcutActionHandler before firing the - * shortcut if the Paintable is currently focused (aka the target of the - * shortcut action). Eg. a field can update its possibly changed value - * to the server before shortcut action is fired. - * - * @param e - * the event that triggered the shortcut action - */ - public void onBeforeShortcutAction(Event e); - } - - private final ArrayList<ShortcutAction> actions = new ArrayList<ShortcutAction>(); - private ApplicationConnection client; - private String paintableId; - - /** - * - * @param pid - * Paintable id - * @param c - * reference to application connections - */ - public ShortcutActionHandler(String pid, ApplicationConnection c) { - paintableId = pid; - client = c; - } - - /** - * Updates list of actions this handler listens to. - * - * @param c - * UIDL snippet containing actions - */ - public void updateActionMap(UIDL c) { - actions.clear(); - final Iterator<?> it = c.getChildIterator(); - while (it.hasNext()) { - final UIDL action = (UIDL) it.next(); - - int[] modifiers = null; - if (action.hasAttribute("mk")) { - modifiers = action.getIntArrayAttribute("mk"); - } - - final ShortcutKeyCombination kc = new ShortcutKeyCombination( - action.getIntAttribute("kc"), modifiers); - final String key = action.getStringAttribute("key"); - final String caption = action.getStringAttribute("caption"); - actions.add(new ShortcutAction(key, kc, caption)); - } - } - - public void handleKeyboardEvent(final Event event, ComponentConnector target) { - final int modifiers = KeyboardListenerCollection - .getKeyboardModifiers(event); - final char keyCode = (char) DOM.eventGetKeyCode(event); - final ShortcutKeyCombination kc = new ShortcutKeyCombination(keyCode, - modifiers); - final Iterator<ShortcutAction> it = actions.iterator(); - while (it.hasNext()) { - final ShortcutAction a = it.next(); - if (a.getShortcutCombination().equals(kc)) { - fireAction(event, a, target); - break; - } - } - - } - - public void handleKeyboardEvent(final Event event) { - handleKeyboardEvent(event, null); - } - - private void fireAction(final Event event, final ShortcutAction a, - ComponentConnector target) { - final Element et = DOM.eventGetTarget(event); - if (target == null) { - target = Util.findPaintable(client, et); - } - final ComponentConnector finalTarget = target; - - event.preventDefault(); - - /* - * The target component might have unpublished changes, try to - * synchronize them before firing shortcut action. - */ - if (finalTarget instanceof BeforeShortcutActionListener) { - ((BeforeShortcutActionListener) finalTarget) - .onBeforeShortcutAction(event); - } else { - shakeTarget(et); - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - shakeTarget(et); - } - }); - } - - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - if (finalTarget != null) { - client.updateVariable(paintableId, "actiontarget", - finalTarget, false); - } - client.updateVariable(paintableId, "action", a.getKey(), true); - } - }); - } - - /** - * We try to fire value change in the component the key combination was - * typed. Eg. textfield may contain newly typed text that is expected to be - * sent to server. This is done by removing focus and then returning it - * immediately back to target element. - * <p> - * This is practically a hack and should be replaced with an interface - * {@link BeforeShortcutActionListener} via widgets could be notified when - * they should fire value change. Big task for TextFields, DateFields and - * various selects. - * - * <p> - * TODO separate opera impl with generator - */ - private static void shakeTarget(final Element e) { - blur(e); - if (BrowserInfo.get().isOpera()) { - // will mess up with focus and blur event if the focus is not - // deferred. Will cause a small flickering, so not doing it for all - // browsers. - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - focus(e); - } - }); - } else { - focus(e); - } - } - - private static native void blur(Element e) - /*-{ - if(e.blur) { - e.blur(); - } - }-*/; - - private static native void focus(Element e) - /*-{ - if(e.blur) { - e.focus(); - } - }-*/; - -} - -class ShortcutKeyCombination { - - public static final int SHIFT = 16; - public static final int CTRL = 17; - public static final int ALT = 18; - public static final int META = 91; - - char keyCode = 0; - private int modifiersMask; - - public ShortcutKeyCombination() { - } - - ShortcutKeyCombination(char kc, int modifierMask) { - keyCode = kc; - modifiersMask = modifierMask; - } - - ShortcutKeyCombination(int kc, int[] modifiers) { - keyCode = (char) kc; - - modifiersMask = 0; - if (modifiers != null) { - for (int i = 0; i < modifiers.length; i++) { - switch (modifiers[i]) { - case ALT: - modifiersMask = modifiersMask - | KeyboardListener.MODIFIER_ALT; - break; - case CTRL: - modifiersMask = modifiersMask - | KeyboardListener.MODIFIER_CTRL; - break; - case SHIFT: - modifiersMask = modifiersMask - | KeyboardListener.MODIFIER_SHIFT; - break; - case META: - modifiersMask = modifiersMask - | KeyboardListener.MODIFIER_META; - break; - default: - break; - } - } - } - } - - public boolean equals(ShortcutKeyCombination other) { - if (keyCode == other.keyCode && modifiersMask == other.modifiersMask) { - return true; - } - return false; - } -} - -class ShortcutAction { - - private final ShortcutKeyCombination sc; - private final String caption; - private final String key; - - public ShortcutAction(String key, ShortcutKeyCombination sc, String caption) { - this.sc = sc; - this.key = key; - this.caption = caption; - } - - public ShortcutKeyCombination getShortcutCombination() { - return sc; - } - - public String getCaption() { - return caption; - } - - public String getKey() { - return key; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/SimpleFocusablePanel.java b/client/src/com/vaadin/terminal/gwt/client/ui/SimpleFocusablePanel.java deleted file mode 100644 index d76d6c14f3..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/SimpleFocusablePanel.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.HasBlurHandlers; -import com.google.gwt.event.dom.client.HasFocusHandlers; -import com.google.gwt.event.dom.client.HasKeyDownHandlers; -import com.google.gwt.event.dom.client.HasKeyPressHandlers; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.event.dom.client.KeyUpEvent; -import com.google.gwt.event.dom.client.KeyUpHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.ui.SimplePanel; -import com.google.gwt.user.client.ui.impl.FocusImpl; -import com.vaadin.terminal.gwt.client.Focusable; - -/** - * Compared to FocusPanel in GWT this panel does not support eg. accesskeys, but - * is simpler by its dom hierarchy nor supports focusing via java api. - */ -public class SimpleFocusablePanel extends SimplePanel implements - HasFocusHandlers, HasBlurHandlers, HasKeyDownHandlers, - HasKeyPressHandlers, Focusable { - - public SimpleFocusablePanel() { - // make focusable, as we don't need access key magic we don't need to - // use FocusImpl.createFocusable - setTabIndex(0); - } - - @Override - public HandlerRegistration addFocusHandler(FocusHandler handler) { - return addDomHandler(handler, FocusEvent.getType()); - } - - @Override - public HandlerRegistration addBlurHandler(BlurHandler handler) { - return addDomHandler(handler, BlurEvent.getType()); - } - - @Override - public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) { - return addDomHandler(handler, KeyDownEvent.getType()); - } - - @Override - public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) { - return addDomHandler(handler, KeyPressEvent.getType()); - } - - public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) { - return addDomHandler(handler, KeyUpEvent.getType()); - } - - public void setFocus(boolean focus) { - if (focus) { - FocusImpl.getFocusImplForPanel().focus(getElement()); - } else { - FocusImpl.getFocusImplForPanel().blur(getElement()); - } - } - - @Override - public void focus() { - setFocus(true); - } - - public void setTabIndex(int tabIndex) { - getElement().setTabIndex(tabIndex); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/SimpleManagedLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/SimpleManagedLayout.java deleted file mode 100644 index 1b404b5fb0..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/SimpleManagedLayout.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -public interface SimpleManagedLayout extends ManagedLayout { - public void layout(); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/SubPartAware.java b/client/src/com/vaadin/terminal/gwt/client/ui/SubPartAware.java deleted file mode 100644 index 145d03287f..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/SubPartAware.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ComponentLocator; - -/** - * Interface implemented by {@link Widget}s which can provide identifiers for at - * least one element inside the component. Used by {@link ComponentLocator}. - * - */ -public interface SubPartAware { - - /** - * Locates an element inside a component using the identifier provided in - * {@code subPart}. The {@code subPart} identifier is component specific and - * may be any string of characters, numbers, space characters and brackets. - * - * @param subPart - * The identifier for the element inside the component - * @return The element identified by subPart or null if the element could - * not be found. - */ - Element getSubPartElement(String subPart); - - /** - * Provides an identifier that identifies the element within the component. - * The {@code subElement} is a part of the component and must never be null. - * <p> - * <b>Note!</b> - * {@code getSubPartElement(getSubPartName(element)) == element} is <i>not - * always</i> true. A component can choose to provide a more generic - * identifier for any given element if the results of all interactions with - * {@code subElement} are the same as interactions with the element - * identified by the return value. For example a button can return an - * identifier for the root element even though a DIV inside the button was - * passed as {@code subElement} because interactions with the DIV and the - * root button element produce the same result. - * - * @param subElement - * The element the identifier string should uniquely identify - * @return An identifier that uniquely identifies {@code subElement} or null - * if no identifier could be provided. - */ - String getSubPartName(Element subElement); - -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java b/client/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java deleted file mode 100644 index 4838576c41..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java +++ /dev/null @@ -1,669 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; - -import com.google.gwt.animation.client.Animation; -import com.google.gwt.core.client.Duration; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.dom.client.Node; -import com.google.gwt.dom.client.NodeList; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Touch; -import com.google.gwt.event.dom.client.ScrollHandler; -import com.google.gwt.event.dom.client.TouchStartEvent; -import com.google.gwt.event.dom.client.TouchStartHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Event.NativePreviewEvent; -import com.google.gwt.user.client.Event.NativePreviewHandler; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.VConsole; - -/** - * Provides one finger touch scrolling for elements with once scrollable - * elements inside. One widget can have several of these scrollable elements. - * Scrollable elements are provided in the constructor. Users must pass - * touchStart events to this delegate, from there on the delegate takes over - * with an event preview. Other touch events needs to be sunken though. - * <p> - * This is bit similar as Scroller class in GWT expenses example, but ideas - * drawn from iscroll.js project: - * <ul> - * <li>uses GWT event mechanism. - * <li>uses modern CSS trick during scrolling for smoother experience: - * translate3d and transitions - * </ul> - * <p> - * Scroll event should only happen when the "touch scrolling actually ends". - * Later we might also tune this so that a scroll event happens if user stalls - * her finger long enought. - * - * TODO static getter for active touch scroll delegate. Components might need to - * prevent scrolling in some cases. Consider Table with drag and drop, or drag - * and drop in scrollable area. Optimal implementation might be to start the - * drag and drop only if user keeps finger down for a moment, otherwise do the - * scroll. In this case, the draggable component would need to cancel scrolling - * in a timer after touchstart event and take over from there. - * - * TODO support scrolling horizontally - * - * TODO cancel if user add second finger to the screen (user expects a gesture). - * - * TODO "scrollbars", see e.g. iscroll.js - * - * TODO write an email to sjobs ät apple dot com and beg for this feature to be - * built into webkit. Seriously, we should try to lobbying this to webkit folks. - * This sure ain't our business to implement this with javascript. - * - * TODO collect all general touch related constant to better place. - * - * @author Matti Tahvonen, Vaadin Ltd - */ -public class TouchScrollDelegate implements NativePreviewHandler { - - private static final double FRICTION = 0.002; - private static final double DECELERATION = 0.002; - private static final int MAX_DURATION = 1500; - private int origY; - private HashSet<Element> scrollableElements; - private Element scrolledElement; - private int origScrollTop; - private HandlerRegistration handlerRegistration; - private double lastAnimatedTranslateY; - private int lastClientY; - private int deltaScrollPos; - private boolean transitionOn = false; - private int finalScrollTop; - private ArrayList<Element> layers; - private boolean moved; - private ScrollHandler scrollHandler; - - private static TouchScrollDelegate activeScrollDelegate; - - private static final boolean androidWithBrokenScrollTop = BrowserInfo.get() - .isAndroidWithBrokenScrollTop(); - - /** - * A helper class for making a widget scrollable. Uses native scrolling if - * supported by the browser, otherwise registers a touch start handler - * delegating to a TouchScrollDelegate instance. - */ - public static class TouchScrollHandler implements TouchStartHandler { - - private static final String SCROLLABLE_CLASSNAME = "v-scrollable"; - - private final TouchScrollDelegate delegate; - private final boolean requiresDelegate = BrowserInfo.get() - .requiresTouchScrollDelegate(); - - /** - * Constructs a scroll handler for the given widget. - * - * @param widget - * The widget that contains scrollable elements - * @param scrollables - * The elements of the widget that should be scrollable. - */ - public TouchScrollHandler(Widget widget, Element... scrollables) { - if (requiresDelegate) { - delegate = new TouchScrollDelegate(); - widget.addDomHandler(this, TouchStartEvent.getType()); - } else { - delegate = null; - } - setElements(scrollables); - } - - @Override - public void onTouchStart(TouchStartEvent event) { - assert delegate != null; - delegate.onTouchStart(event); - } - - public void debug(Element e) { - VConsole.log("Classes: " + e.getClassName() + " overflow: " - + e.getStyle().getProperty("overflow") + " w-o-s: " - + e.getStyle().getProperty("WebkitOverflowScrolling")); - } - - /** - * Registers the given element as scrollable. - */ - public void addElement(Element scrollable) { - scrollable.addClassName(SCROLLABLE_CLASSNAME); - if (requiresDelegate) { - delegate.scrollableElements.add(scrollable); - } - } - - /** - * Unregisters the given element as scrollable. Should be called when a - * previously-registered element is removed from the DOM to prevent - * memory leaks. - */ - public void removeElement(Element scrollable) { - scrollable.removeClassName(SCROLLABLE_CLASSNAME); - if (requiresDelegate) { - delegate.scrollableElements.remove(scrollable); - } - } - - /** - * Registers the given elements as scrollable, removing previously - * registered scrollables from this handler. - * - * @param scrollables - * The elements that should be scrollable - */ - public void setElements(Element... scrollables) { - if (requiresDelegate) { - for (Element e : delegate.scrollableElements) { - e.removeClassName(SCROLLABLE_CLASSNAME); - } - delegate.scrollableElements.clear(); - } - for (Element e : scrollables) { - addElement(e); - } - } - } - - /** - * Makes the given elements scrollable, either natively or by using a - * TouchScrollDelegate, depending on platform capabilities. - * - * @param widget - * The widget that contains scrollable elements - * @param scrollables - * The elements inside the widget that should be scrollable - * @return A scroll handler for the given widget. - */ - public static TouchScrollHandler enableTouchScrolling(Widget widget, - Element... scrollables) { - return new TouchScrollHandler(widget, scrollables); - } - - public TouchScrollDelegate(Element... elements) { - setElements(elements); - } - - public void setScrollHandler(ScrollHandler scrollHandler) { - this.scrollHandler = scrollHandler; - } - - public static TouchScrollDelegate getActiveScrollDelegate() { - return activeScrollDelegate; - } - - /** - * Has user moved the touch. - * - * @return - */ - public boolean isMoved() { - return moved; - } - - /** - * Forces the scroll delegate to cancels scrolling process. Can be called by - * users if they e.g. decide to handle touch event by themselves after all - * (e.g. a pause after touch start before moving touch -> interpreted as - * long touch/click or drag start). - */ - public void stopScrolling() { - handlerRegistration.removeHandler(); - handlerRegistration = null; - if (moved) { - moveTransformationToScrolloffset(); - } else { - activeScrollDelegate = null; - } - } - - public void onTouchStart(TouchStartEvent event) { - if (activeScrollDelegate == null && event.getTouches().length() == 1) { - NativeEvent nativeEvent = event.getNativeEvent(); - doTouchStart(nativeEvent); - } else { - /* - * Touch scroll is currenly on (possibly bouncing). Ignore. - */ - } - } - - private void doTouchStart(NativeEvent nativeEvent) { - if (transitionOn) { - momentum.cancel(); - } - Touch touch = nativeEvent.getTouches().get(0); - if (detectScrolledElement(touch)) { - VConsole.log("TouchDelegate takes over"); - nativeEvent.stopPropagation(); - handlerRegistration = Event.addNativePreviewHandler(this); - activeScrollDelegate = this; - origY = touch.getClientY(); - yPositions[0] = origY; - eventTimeStamps[0] = getTimeStamp(); - nextEvent = 1; - - origScrollTop = getScrollTop(); - VConsole.log("ST" + origScrollTop); - - moved = false; - // event.preventDefault(); - // event.stopPropagation(); - } - } - - private int getScrollTop() { - if (androidWithBrokenScrollTop) { - if (scrolledElement.getPropertyJSO("_vScrollTop") != null) { - return scrolledElement.getPropertyInt("_vScrollTop"); - } - return 0; - } - return scrolledElement.getScrollTop(); - } - - private void onTransitionEnd() { - if (finalScrollTop < 0) { - animateToScrollPosition(0, finalScrollTop); - finalScrollTop = 0; - } else if (finalScrollTop > getMaxFinalY()) { - animateToScrollPosition(getMaxFinalY(), finalScrollTop); - finalScrollTop = getMaxFinalY(); - } else { - moveTransformationToScrolloffset(); - } - } - - private void animateToScrollPosition(int to, int from) { - int dist = Math.abs(to - from); - int time = getAnimationTimeForDistance(dist); - if (time <= 0) { - time = 1; // get animation and transition end event - } - VConsole.log("Animate " + time + " " + from + " " + to); - int translateTo = -to + origScrollTop; - int fromY = -from + origScrollTop; - if (androidWithBrokenScrollTop) { - fromY -= origScrollTop; - translateTo -= origScrollTop; - } - translateTo(time, fromY, translateTo); - } - - private int getAnimationTimeForDistance(int dist) { - return 350; // 350ms seems to work quite fine for all distances - // if (dist < 0) { - // dist = -dist; - // } - // return MAX_DURATION * dist / (scrolledElement.getClientHeight() * 3); - } - - /** - * Called at the end of scrolling. Moves possible translate values to - * scrolltop, causing onscroll event. - */ - private void moveTransformationToScrolloffset() { - if (androidWithBrokenScrollTop) { - scrolledElement.setPropertyInt("_vScrollTop", finalScrollTop); - if (scrollHandler != null) { - scrollHandler.onScroll(null); - } - } else { - for (Element el : layers) { - Style style = el.getStyle(); - style.setProperty("webkitTransform", "translate3d(0,0,0)"); - } - scrolledElement.setScrollTop(finalScrollTop); - } - activeScrollDelegate = null; - handlerRegistration.removeHandler(); - handlerRegistration = null; - } - - /** - * Detects if a touch happens on a predefined element and the element has - * something to scroll. - * - * @param touch - * @return - */ - private boolean detectScrolledElement(Touch touch) { - Element target = touch.getTarget().cast(); - for (Element el : scrollableElements) { - if (el.isOrHasChild(target) - && el.getScrollHeight() > el.getClientHeight()) { - scrolledElement = el; - layers = getElements(scrolledElement); - return true; - - } - } - return false; - } - - public static ArrayList<Element> getElements(Element scrolledElement2) { - NodeList<Node> childNodes = scrolledElement2.getChildNodes(); - ArrayList<Element> l = new ArrayList<Element>(); - for (int i = 0; i < childNodes.getLength(); i++) { - Node item = childNodes.getItem(i); - if (item.getNodeType() == Node.ELEMENT_NODE) { - l.add((Element) item); - } - } - return l; - } - - private void onTouchMove(NativeEvent event) { - if (!moved) { - double l = (getTimeStamp() - eventTimeStamps[0]); - VConsole.log(l + " ms from start to move"); - } - boolean handleMove = readPositionAndSpeed(event); - if (handleMove) { - int deltaScrollTop = origY - lastClientY; - int finalPos = origScrollTop + deltaScrollTop; - if (finalPos > getMaxFinalY()) { - // spring effect at the end - int overscroll = (deltaScrollTop + origScrollTop) - - getMaxFinalY(); - overscroll = overscroll / 2; - if (overscroll > getMaxOverScroll()) { - overscroll = getMaxOverScroll(); - } - deltaScrollTop = getMaxFinalY() + overscroll - origScrollTop; - } else if (finalPos < 0) { - // spring effect at the beginning - int overscroll = finalPos / 2; - if (-overscroll > getMaxOverScroll()) { - overscroll = -getMaxOverScroll(); - } - deltaScrollTop = overscroll - origScrollTop; - } - quickSetScrollPosition(0, deltaScrollTop); - moved = true; - event.preventDefault(); - event.stopPropagation(); - } - } - - private void quickSetScrollPosition(int deltaX, int deltaY) { - deltaScrollPos = deltaY; - if (androidWithBrokenScrollTop) { - deltaY += origScrollTop; - translateTo(-deltaY); - } else { - translateTo(-deltaScrollPos); - } - } - - private static final int EVENTS_FOR_SPEED_CALC = 3; - public static final int SIGNIFICANT_MOVE_THRESHOLD = 3; - private int[] yPositions = new int[EVENTS_FOR_SPEED_CALC]; - private double[] eventTimeStamps = new double[EVENTS_FOR_SPEED_CALC]; - private int nextEvent = 0; - private Animation momentum; - - /** - * - * @param event - * @return - */ - private boolean readPositionAndSpeed(NativeEvent event) { - Touch touch = event.getChangedTouches().get(0); - lastClientY = touch.getClientY(); - int eventIndx = nextEvent++; - eventIndx = eventIndx % EVENTS_FOR_SPEED_CALC; - eventTimeStamps[eventIndx] = getTimeStamp(); - yPositions[eventIndx] = lastClientY; - return isMovedSignificantly(); - } - - private boolean isMovedSignificantly() { - return moved ? moved - : Math.abs(origY - lastClientY) >= SIGNIFICANT_MOVE_THRESHOLD; - } - - private void onTouchEnd(NativeEvent event) { - if (!moved) { - activeScrollDelegate = null; - handlerRegistration.removeHandler(); - handlerRegistration = null; - return; - } - - int currentY = origScrollTop + deltaScrollPos; - - int maxFinalY = getMaxFinalY(); - - int pixelsToMove; - int finalY; - int duration = -1; - if (currentY > maxFinalY) { - // we are over the max final pos, animate to end - pixelsToMove = maxFinalY - currentY; - finalY = maxFinalY; - } else if (currentY < 0) { - // we are below the max final pos, animate to beginning - pixelsToMove = -currentY; - finalY = 0; - } else { - double pixelsPerMs = calculateSpeed(); - // we are currently within scrollable area, calculate pixels that - // we'll move due to momentum - VConsole.log("pxPerMs" + pixelsPerMs); - pixelsToMove = (int) (0.5 * pixelsPerMs * pixelsPerMs / FRICTION); - if (pixelsPerMs < 0) { - pixelsToMove = -pixelsToMove; - } - // VConsole.log("pixels to move" + pixelsToMove); - - finalY = currentY + pixelsToMove; - - if (finalY > maxFinalY + getMaxOverScroll()) { - // VConsole.log("To max overscroll"); - finalY = getMaxFinalY() + getMaxOverScroll(); - int fixedPixelsToMove = finalY - currentY; - pixelsToMove = fixedPixelsToMove; - } else if (finalY < 0 - getMaxOverScroll()) { - // VConsole.log("to min overscroll"); - finalY = -getMaxOverScroll(); - int fixedPixelsToMove = finalY - currentY; - pixelsToMove = fixedPixelsToMove; - } else { - duration = (int) (Math.abs(pixelsPerMs / DECELERATION)); - } - } - if (duration == -1) { - // did not keep in side borders or was outside borders, calculate - // a good enough duration based on pixelsToBeMoved. - duration = getAnimationTimeForDistance(pixelsToMove); - } - if (duration > MAX_DURATION) { - VConsole.log("Max animation time. " + duration); - duration = MAX_DURATION; - } - finalScrollTop = finalY; - - if (Math.abs(pixelsToMove) < 3 || duration < 20) { - VConsole.log("Small 'momentum' " + pixelsToMove + " | " + duration - + " Skipping animation,"); - moveTransformationToScrolloffset(); - return; - } - - int translateTo = -finalY + origScrollTop; - int fromY = -currentY + origScrollTop; - if (androidWithBrokenScrollTop) { - fromY -= origScrollTop; - translateTo -= origScrollTop; - } - translateTo(duration, fromY, translateTo); - } - - private double calculateSpeed() { - if (nextEvent < EVENTS_FOR_SPEED_CALC) { - VConsole.log("Not enough data for speed calculation"); - // not enough data for decent speed calculation, no momentum :-( - return 0; - } - int idx = nextEvent % EVENTS_FOR_SPEED_CALC; - final int firstPos = yPositions[idx]; - final double firstTs = eventTimeStamps[idx]; - idx += EVENTS_FOR_SPEED_CALC; - idx--; - idx = idx % EVENTS_FOR_SPEED_CALC; - final int lastPos = yPositions[idx]; - final double lastTs = eventTimeStamps[idx]; - // speed as in change of scrolltop == -speedOfTouchPos - return (firstPos - lastPos) / (lastTs - firstTs); - - } - - /** - * Note positive scrolltop moves layer up, positive translate moves layer - * down. - */ - private void translateTo(double translateY) { - for (Element el : layers) { - Style style = el.getStyle(); - style.setProperty("webkitTransform", "translate3d(0px," - + translateY + "px,0px)"); - } - } - - /** - * Note positive scrolltop moves layer up, positive translate moves layer - * down. - * - * @param duration - */ - private void translateTo(int duration, final int fromY, final int finalY) { - if (duration > 0) { - transitionOn = true; - - momentum = new Animation() { - - @Override - protected void onUpdate(double progress) { - lastAnimatedTranslateY = (fromY + (finalY - fromY) - * progress); - translateTo(lastAnimatedTranslateY); - } - - @Override - protected double interpolate(double progress) { - return 1 + Math.pow(progress - 1, 3); - } - - @Override - protected void onComplete() { - super.onComplete(); - transitionOn = false; - onTransitionEnd(); - } - - @Override - protected void onCancel() { - int delta = (int) (finalY - lastAnimatedTranslateY); - finalScrollTop -= delta; - moveTransformationToScrolloffset(); - transitionOn = false; - } - }; - momentum.run(duration); - } - } - - private int getMaxOverScroll() { - return androidWithBrokenScrollTop ? 0 : scrolledElement - .getClientHeight() / 3; - } - - private int getMaxFinalY() { - return scrolledElement.getScrollHeight() - - scrolledElement.getClientHeight(); - } - - @Override - public void onPreviewNativeEvent(NativePreviewEvent event) { - int typeInt = event.getTypeInt(); - if (transitionOn) { - /* - * TODO allow starting new events. See issue in onTouchStart - */ - event.cancel(); - - if (typeInt == Event.ONTOUCHSTART) { - doTouchStart(event.getNativeEvent()); - } - return; - } - switch (typeInt) { - case Event.ONTOUCHMOVE: - if (!event.isCanceled()) { - onTouchMove(event.getNativeEvent()); - if (moved) { - event.cancel(); - } - } - break; - case Event.ONTOUCHEND: - case Event.ONTOUCHCANCEL: - if (!event.isCanceled()) { - if (moved) { - event.cancel(); - } - onTouchEnd(event.getNativeEvent()); - } - break; - case Event.ONMOUSEMOVE: - if (moved) { - // no debug message, mobile safari generates these for some - // compatibility purposes. - event.cancel(); - } - break; - default: - VConsole.log("Non touch event:" + event.getNativeEvent().getType()); - event.cancel(); - break; - } - } - - public void setElements(Element[] elements) { - scrollableElements = new HashSet<Element>(Arrays.asList(elements)); - } - - /** - * long calcucation are not very efficient in GWT, so this helper method - * returns timestamp in double. - * - * @return - */ - public static double getTimeStamp() { - return Duration.currentTimeMillis(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/TreeAction.java b/client/src/com/vaadin/terminal/gwt/client/ui/TreeAction.java deleted file mode 100644 index 9cf63a609c..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/TreeAction.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui; - -/** - * This class is used for "row actions" in VTree and ITable - */ -public class TreeAction extends Action { - - String targetKey = ""; - String actionKey = ""; - - public TreeAction(ActionOwner owner) { - super(owner); - } - - public TreeAction(ActionOwner owner, String target, String action) { - this(owner); - targetKey = target; - actionKey = action; - } - - /** - * Sends message to server that this action has been fired. Messages are - * "standard" Vaadin messages whose value is comma separated pair of - * targetKey (row, treeNod ...) and actions id. - * - * Variablename is always "action". - * - * Actions are always sent immediatedly to server. - */ - @Override - public void execute() { - owner.getClient().updateVariable(owner.getPaintableId(), "action", - targetKey + "," + actionKey, true); - owner.getClient().getContextMenu().hide(); - } - - public String getActionKey() { - return actionKey; - } - - public void setActionKey(String actionKey) { - this.actionKey = actionKey; - } - - public String getTargetKey() { - return targetKey; - } - - public void setTargetKey(String targetKey) { - this.targetKey = targetKey; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/TreeImages.java b/client/src/com/vaadin/terminal/gwt/client/ui/TreeImages.java deleted file mode 100644 index 9b03c03794..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/TreeImages.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.user.client.ui.AbstractImagePrototype; - -public interface TreeImages extends com.google.gwt.user.client.ui.TreeImages { - - /** - * An image indicating an open branch. - * - * @return a prototype of this image - * @gwt.resource com/vaadin/terminal/gwt/public/default/tree/img/expanded - * .png - */ - @Override - AbstractImagePrototype treeOpen(); - - /** - * An image indicating a closed branch. - * - * @return a prototype of this image - * @gwt.resource com/vaadin/terminal/gwt/public/default/tree/img/collapsed - * .png - */ - @Override - AbstractImagePrototype treeClosed(); - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/UI/UIConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/UI/UIConnector.java deleted file mode 100644 index 4e1bed1aa8..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/UI/UIConnector.java +++ /dev/null @@ -1,456 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.UI; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Position; -import com.google.gwt.event.logical.shared.ResizeEvent; -import com.google.gwt.event.logical.shared.ResizeHandler; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.History; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.Widget; -import com.google.web.bindery.event.shared.HandlerRegistration; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.shared.ui.ui.PageClientRpc; -import com.vaadin.shared.ui.ui.UIConstants; -import com.vaadin.shared.ui.ui.UIServerRpc; -import com.vaadin.shared.ui.ui.UIState; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.Focusable; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.communication.RpcProxy; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector; -import com.vaadin.terminal.gwt.client.ui.ClickEventHandler; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler; -import com.vaadin.terminal.gwt.client.ui.layout.MayScrollChildren; -import com.vaadin.terminal.gwt.client.ui.notification.VNotification; -import com.vaadin.terminal.gwt.client.ui.window.WindowConnector; -import com.vaadin.ui.UI; - -@Connect(value = UI.class, loadStyle = LoadStyle.EAGER) -public class UIConnector extends AbstractComponentContainerConnector - implements Paintable, MayScrollChildren { - - private UIServerRpc rpc = RpcProxy.create(UIServerRpc.class, this); - - private HandlerRegistration childStateChangeHandlerRegistration; - - private final StateChangeHandler childStateChangeHandler = new StateChangeHandler() { - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - // TODO Should use a more specific handler that only reacts to - // size changes - onChildSizeChange(); - } - }; - - @Override - protected void init() { - super.init(); - registerRpc(PageClientRpc.class, new PageClientRpc() { - @Override - public void setTitle(String title) { - com.google.gwt.user.client.Window.setTitle(title); - } - }); - getWidget().addResizeHandler(new ResizeHandler() { - @Override - public void onResize(ResizeEvent event) { - rpc.resize(event.getHeight(), event.getWidth(), - Window.getClientWidth(), Window.getClientHeight()); - if (getState().isImmediate()) { - getConnection().sendPendingVariableChanges(); - } - } - }); - } - - @Override - public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) { - ConnectorMap paintableMap = ConnectorMap.get(getConnection()); - getWidget().rendering = true; - getWidget().id = getConnectorId(); - boolean firstPaint = getWidget().connection == null; - getWidget().connection = client; - - getWidget().immediate = getState().isImmediate(); - getWidget().resizeLazy = uidl.hasAttribute(UIConstants.RESIZE_LAZY); - String newTheme = uidl.getStringAttribute("theme"); - if (getWidget().theme != null && !newTheme.equals(getWidget().theme)) { - // Complete page refresh is needed due css can affect layout - // calculations etc - getWidget().reloadHostPage(); - } else { - getWidget().theme = newTheme; - } - // this also implicitly removes old styles - String styles = ""; - styles += getWidget().getStylePrimaryName() + " "; - if (getState().hasStyles()) { - for (String style : getState().getStyles()) { - styles += style + " "; - } - } - if (!client.getConfiguration().isStandalone()) { - styles += getWidget().getStylePrimaryName() + "-embedded"; - } - getWidget().setStyleName(styles.trim()); - - getWidget().makeScrollable(); - - clickEventHandler.handleEventHandlerRegistration(); - - // Process children - int childIndex = 0; - - // Open URL:s - boolean isClosed = false; // was this window closed? - while (childIndex < uidl.getChildCount() - && "open".equals(uidl.getChildUIDL(childIndex).getTag())) { - final UIDL open = uidl.getChildUIDL(childIndex); - final String url = client.translateVaadinUri(open - .getStringAttribute("src")); - final String target = open.getStringAttribute("name"); - if (target == null) { - // source will be opened to this browser window, but we may have - // to finish rendering this window in case this is a download - // (and window stays open). - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - VUI.goTo(url); - } - }); - } else if ("_self".equals(target)) { - // This window is closing (for sure). Only other opens are - // relevant in this change. See #3558, #2144 - isClosed = true; - VUI.goTo(url); - } else { - String options; - if (open.hasAttribute("border")) { - if (open.getStringAttribute("border").equals("minimal")) { - options = "menubar=yes,location=no,status=no"; - } else { - options = "menubar=no,location=no,status=no"; - } - - } else { - options = "resizable=yes,menubar=yes,toolbar=yes,directories=yes,location=yes,scrollbars=yes,status=yes"; - } - - if (open.hasAttribute("width")) { - int w = open.getIntAttribute("width"); - options += ",width=" + w; - } - if (open.hasAttribute("height")) { - int h = open.getIntAttribute("height"); - options += ",height=" + h; - } - - Window.open(url, target, options); - } - childIndex++; - } - if (isClosed) { - // don't render the content, something else will be opened to this - // browser view - getWidget().rendering = false; - return; - } - - // Handle other UIDL children - UIDL childUidl; - while ((childUidl = uidl.getChildUIDL(childIndex++)) != null) { - String tag = childUidl.getTag().intern(); - if (tag == "actions") { - if (getWidget().actionHandler == null) { - getWidget().actionHandler = new ShortcutActionHandler( - getWidget().id, client); - } - getWidget().actionHandler.updateActionMap(childUidl); - } else if (tag == "notifications") { - for (final Iterator<?> it = childUidl.getChildIterator(); it - .hasNext();) { - final UIDL notification = (UIDL) it.next(); - VNotification.showNotification(client, notification); - } - } - } - - if (uidl.hasAttribute("focused")) { - // set focused component when render phase is finished - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - ComponentConnector paintable = (ComponentConnector) uidl - .getPaintableAttribute("focused", getConnection()); - - final Widget toBeFocused = paintable.getWidget(); - /* - * Two types of Widgets can be focused, either implementing - * GWT HasFocus of a thinner Vaadin specific Focusable - * interface. - */ - if (toBeFocused instanceof com.google.gwt.user.client.ui.Focusable) { - final com.google.gwt.user.client.ui.Focusable toBeFocusedWidget = (com.google.gwt.user.client.ui.Focusable) toBeFocused; - toBeFocusedWidget.setFocus(true); - } else if (toBeFocused instanceof Focusable) { - ((Focusable) toBeFocused).focus(); - } else { - VConsole.log("Could not focus component"); - } - } - }); - } - - // Add window listeners on first paint, to prevent premature - // variablechanges - if (firstPaint) { - Window.addWindowClosingHandler(getWidget()); - Window.addResizeHandler(getWidget()); - } - - // finally set scroll position from UIDL - if (uidl.hasVariable("scrollTop")) { - getWidget().scrollable = true; - getWidget().scrollTop = uidl.getIntVariable("scrollTop"); - DOM.setElementPropertyInt(getWidget().getElement(), "scrollTop", - getWidget().scrollTop); - getWidget().scrollLeft = uidl.getIntVariable("scrollLeft"); - DOM.setElementPropertyInt(getWidget().getElement(), "scrollLeft", - getWidget().scrollLeft); - } else { - getWidget().scrollable = false; - } - - if (uidl.hasAttribute("scrollTo")) { - final ComponentConnector connector = (ComponentConnector) uidl - .getPaintableAttribute("scrollTo", getConnection()); - scrollIntoView(connector); - } - - if (uidl.hasAttribute(UIConstants.FRAGMENT_VARIABLE)) { - getWidget().currentFragment = uidl - .getStringAttribute(UIConstants.FRAGMENT_VARIABLE); - if (!getWidget().currentFragment.equals(History.getToken())) { - History.newItem(getWidget().currentFragment, true); - } - } else { - // Initial request for which the server doesn't yet have a fragment - // (and haven't shown any interest in getting one) - getWidget().currentFragment = History.getToken(); - - // Include current fragment in the next request - client.updateVariable(getWidget().id, - UIConstants.FRAGMENT_VARIABLE, - getWidget().currentFragment, false); - } - - if (firstPaint) { - // Queue the initial window size to be sent with the following - // request. - getWidget().sendClientResized(); - } - getWidget().rendering = false; - } - - public void init(String rootPanelId, - ApplicationConnection applicationConnection) { - DOM.sinkEvents(getWidget().getElement(), Event.ONKEYDOWN - | Event.ONSCROLL); - - // iview is focused when created so element needs tabIndex - // 1 due 0 is at the end of natural tabbing order - DOM.setElementProperty(getWidget().getElement(), "tabIndex", "1"); - - RootPanel root = RootPanel.get(rootPanelId); - - // Remove the v-app-loading or any splash screen added inside the div by - // the user - root.getElement().setInnerHTML(""); - - root.addStyleName("v-theme-" - + applicationConnection.getConfiguration().getThemeName()); - - root.add(getWidget()); - - if (applicationConnection.getConfiguration().isStandalone()) { - // set focus to iview element by default to listen possible keyboard - // shortcuts. For embedded applications this is unacceptable as we - // don't want to steal focus from the main page nor we don't want - // side-effects from focusing (scrollIntoView). - getWidget().getElement().focus(); - } - } - - private ClickEventHandler clickEventHandler = new ClickEventHandler(this) { - - @Override - protected void fireClick(NativeEvent event, - MouseEventDetails mouseDetails) { - rpc.click(mouseDetails); - } - - }; - - @Override - public void updateCaption(ComponentConnector component) { - // NOP The main view never draws caption for its layout - } - - @Override - public VUI getWidget() { - return (VUI) super.getWidget(); - } - - protected ComponentConnector getContent() { - return (ComponentConnector) getState().getContent(); - } - - protected void onChildSizeChange() { - ComponentConnector child = getContent(); - Style childStyle = child.getWidget().getElement().getStyle(); - /* - * Must set absolute position if the child has relative height and - * there's a chance of horizontal scrolling as some browsers will - * otherwise not take the scrollbar into account when calculating the - * height. Assuming v-view does not have an undefined width for now, see - * #8460. - */ - if (child.isRelativeHeight() && !BrowserInfo.get().isIE9()) { - childStyle.setPosition(Position.ABSOLUTE); - } else { - childStyle.clearPosition(); - } - } - - /** - * Checks if the given sub window is a child of this UI Connector - * - * @deprecated Should be replaced by a more generic mechanism for getting - * non-ComponentConnector children - * @param wc - * @return - */ - @Deprecated - public boolean hasSubWindow(WindowConnector wc) { - return getChildComponents().contains(wc); - } - - /** - * Return an iterator for current subwindows. This method is meant for - * testing purposes only. - * - * @return - */ - public List<WindowConnector> getSubWindows() { - ArrayList<WindowConnector> windows = new ArrayList<WindowConnector>(); - for (ComponentConnector child : getChildComponents()) { - if (child instanceof WindowConnector) { - windows.add((WindowConnector) child); - } - } - return windows; - } - - @Override - public UIState getState() { - return (UIState) super.getState(); - } - - @Override - public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { - super.onConnectorHierarchyChange(event); - - ComponentConnector oldChild = null; - ComponentConnector newChild = getContent(); - - for (ComponentConnector c : event.getOldChildren()) { - if (!(c instanceof WindowConnector)) { - oldChild = c; - break; - } - } - - if (oldChild != newChild) { - if (childStateChangeHandlerRegistration != null) { - childStateChangeHandlerRegistration.removeHandler(); - childStateChangeHandlerRegistration = null; - } - getWidget().setWidget(newChild.getWidget()); - childStateChangeHandlerRegistration = newChild - .addStateChangeHandler(childStateChangeHandler); - // Must handle new child here as state change events are already - // fired - onChildSizeChange(); - } - - for (ComponentConnector c : getChildComponents()) { - if (c instanceof WindowConnector) { - WindowConnector wc = (WindowConnector) c; - wc.setWindowOrderAndPosition(); - } - } - - // Close removed sub windows - for (ComponentConnector c : event.getOldChildren()) { - if (c.getParent() != this && c instanceof WindowConnector) { - ((WindowConnector) c).getWidget().hide(); - } - } - } - - /** - * Tries to scroll the viewport so that the given connector is in view. - * - * @param componentConnector - * The connector which should be visible - * - */ - public void scrollIntoView(final ComponentConnector componentConnector) { - if (componentConnector == null) { - return; - } - - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - componentConnector.getWidget().getElement().scrollIntoView(); - } - }); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/UI/VUI.java b/client/src/com/vaadin/terminal/gwt/client/ui/UI/VUI.java deleted file mode 100644 index 1c4b69a3b9..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/UI/VUI.java +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.UI; - -import java.util.ArrayList; - -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.dom.client.Element; -import com.google.gwt.event.logical.shared.HasResizeHandlers; -import com.google.gwt.event.logical.shared.ResizeEvent; -import com.google.gwt.event.logical.shared.ResizeHandler; -import com.google.gwt.event.logical.shared.ValueChangeEvent; -import com.google.gwt.event.logical.shared.ValueChangeHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.History; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.SimplePanel; -import com.vaadin.shared.ApplicationConstants; -import com.vaadin.shared.ui.ui.UIConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.Focusable; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner; -import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate; -import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate.TouchScrollHandler; -import com.vaadin.terminal.gwt.client.ui.VLazyExecutor; -import com.vaadin.terminal.gwt.client.ui.textfield.VTextField; - -/** - * - */ -public class VUI extends SimplePanel implements ResizeHandler, - Window.ClosingHandler, ShortcutActionHandlerOwner, Focusable, - HasResizeHandlers { - - private static final String CLASSNAME = "v-view"; - - private static int MONITOR_PARENT_TIMER_INTERVAL = 1000; - - String theme; - - String id; - - ShortcutActionHandler actionHandler; - - /* - * Last known window size used to detect whether VView should be layouted - * again. Detection must check window size, because the VView size might be - * fixed and thus not automatically adapt to changed window sizes. - */ - private int windowWidth; - private int windowHeight; - - /* - * Last know view size used to detect whether new dimensions should be sent - * to the server. - */ - private int viewWidth; - private int viewHeight; - - ApplicationConnection connection; - - /** - * Keep track of possible parent size changes when an embedded application. - * - * Uses {@link #parentWidth} and {@link #parentHeight} as an optimization to - * keep track of when there is a real change. - */ - private Timer resizeTimer; - - /** stored width of parent for embedded application auto-resize */ - private int parentWidth; - - /** stored height of parent for embedded application auto-resize */ - private int parentHeight; - - int scrollTop; - - int scrollLeft; - - boolean rendering; - - boolean scrollable; - - boolean immediate; - - boolean resizeLazy = false; - - private HandlerRegistration historyHandlerRegistration; - - private TouchScrollHandler touchScrollHandler; - - /** - * The current URI fragment, used to avoid sending updates if nothing has - * changed. - */ - String currentFragment; - - /** - * Listener for URI fragment changes. Notifies the server of the new value - * whenever the value changes. - */ - private final ValueChangeHandler<String> historyChangeHandler = new ValueChangeHandler<String>() { - - @Override - public void onValueChange(ValueChangeEvent<String> event) { - String newFragment = event.getValue(); - - // Send the new fragment to the server if it has changed - if (!newFragment.equals(currentFragment) && connection != null) { - currentFragment = newFragment; - connection.updateVariable(id, UIConstants.FRAGMENT_VARIABLE, - newFragment, true); - } - } - }; - - private VLazyExecutor delayedResizeExecutor = new VLazyExecutor(200, - new ScheduledCommand() { - - @Override - public void execute() { - performSizeCheck(); - } - - }); - - public VUI() { - super(); - setStyleName(CLASSNAME); - - // Allow focusing the view by using the focus() method, the view - // should not be in the document focus flow - getElement().setTabIndex(-1); - makeScrollable(); - } - - /** - * Start to periodically monitor for parent element resizes if embedded - * application (e.g. portlet). - */ - @Override - protected void onLoad() { - super.onLoad(); - if (isMonitoringParentSize()) { - resizeTimer = new Timer() { - - @Override - public void run() { - // trigger check to see if parent size has changed, - // recalculate layouts - performSizeCheck(); - resizeTimer.schedule(MONITOR_PARENT_TIMER_INTERVAL); - } - }; - resizeTimer.schedule(MONITOR_PARENT_TIMER_INTERVAL); - } - } - - @Override - protected void onAttach() { - super.onAttach(); - historyHandlerRegistration = History - .addValueChangeHandler(historyChangeHandler); - currentFragment = History.getToken(); - } - - @Override - protected void onDetach() { - super.onDetach(); - historyHandlerRegistration.removeHandler(); - historyHandlerRegistration = null; - } - - /** - * Stop monitoring for parent element resizes. - */ - - @Override - protected void onUnload() { - if (resizeTimer != null) { - resizeTimer.cancel(); - resizeTimer = null; - } - super.onUnload(); - } - - /** - * Called when the window or parent div might have been resized. - * - * This immediately checks the sizes of the window and the parent div (if - * monitoring it) and triggers layout recalculation if they have changed. - */ - protected void performSizeCheck() { - windowSizeMaybeChanged(Window.getClientWidth(), - Window.getClientHeight()); - } - - /** - * Called when the window or parent div might have been resized. - * - * This immediately checks the sizes of the window and the parent div (if - * monitoring it) and triggers layout recalculation if they have changed. - * - * @param newWindowWidth - * The new width of the window - * @param newWindowHeight - * The new height of the window - * - * @deprecated use {@link #performSizeCheck()} - */ - @Deprecated - protected void windowSizeMaybeChanged(int newWindowWidth, - int newWindowHeight) { - boolean changed = false; - ComponentConnector connector = ConnectorMap.get(connection) - .getConnector(this); - if (windowWidth != newWindowWidth) { - windowWidth = newWindowWidth; - changed = true; - connector.getLayoutManager().reportOuterWidth(connector, - newWindowWidth); - VConsole.log("New window width: " + windowWidth); - } - if (windowHeight != newWindowHeight) { - windowHeight = newWindowHeight; - changed = true; - connector.getLayoutManager().reportOuterHeight(connector, - newWindowHeight); - VConsole.log("New window height: " + windowHeight); - } - Element parentElement = getElement().getParentElement(); - if (isMonitoringParentSize() && parentElement != null) { - // check also for parent size changes - int newParentWidth = parentElement.getClientWidth(); - int newParentHeight = parentElement.getClientHeight(); - if (parentWidth != newParentWidth) { - parentWidth = newParentWidth; - changed = true; - VConsole.log("New parent width: " + parentWidth); - } - if (parentHeight != newParentHeight) { - parentHeight = newParentHeight; - changed = true; - VConsole.log("New parent height: " + parentHeight); - } - } - if (changed) { - /* - * If the window size has changed, layout the VView again and send - * new size to the server if the size changed. (Just checking VView - * size would cause us to ignore cases when a relatively sized VView - * should shrink as the content's size is fixed and would thus not - * automatically shrink.) - */ - VConsole.log("Running layout functions due to window or parent resize"); - - // update size to avoid (most) redundant re-layout passes - // there can still be an extra layout recalculation if webkit - // overflow fix updates the size in a deferred block - if (isMonitoringParentSize() && parentElement != null) { - parentWidth = parentElement.getClientWidth(); - parentHeight = parentElement.getClientHeight(); - } - - sendClientResized(); - - connector.getLayoutManager().layoutNow(); - } - } - - public String getTheme() { - return theme; - } - - /** - * Used to reload host page on theme changes. - */ - static native void reloadHostPage() - /*-{ - $wnd.location.reload(); - }-*/; - - /** - * Returns true if the body is NOT generated, i.e if someone else has made - * the page that we're running in. Otherwise we're in charge of the whole - * page. - * - * @return true if we're running embedded - */ - public boolean isEmbedded() { - return !getElement().getOwnerDocument().getBody().getClassName() - .contains(ApplicationConstants.GENERATED_BODY_CLASSNAME); - } - - /** - * Returns true if the size of the parent should be checked periodically and - * the application should react to its changes. - * - * @return true if size of parent should be tracked - */ - protected boolean isMonitoringParentSize() { - // could also perform a more specific check (Liferay portlet) - return isEmbedded(); - } - - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - int type = DOM.eventGetType(event); - if (type == Event.ONKEYDOWN && actionHandler != null) { - actionHandler.handleKeyboardEvent(event); - return; - } else if (scrollable && type == Event.ONSCROLL) { - updateScrollPosition(); - } - } - - /** - * Updates scroll position from DOM and saves variables to server. - */ - private void updateScrollPosition() { - int oldTop = scrollTop; - int oldLeft = scrollLeft; - scrollTop = DOM.getElementPropertyInt(getElement(), "scrollTop"); - scrollLeft = DOM.getElementPropertyInt(getElement(), "scrollLeft"); - if (connection != null && !rendering) { - if (oldTop != scrollTop) { - connection.updateVariable(id, "scrollTop", scrollTop, false); - } - if (oldLeft != scrollLeft) { - connection.updateVariable(id, "scrollLeft", scrollLeft, false); - } - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.logical.shared.ResizeHandler#onResize(com.google - * .gwt.event.logical.shared.ResizeEvent) - */ - - @Override - public void onResize(ResizeEvent event) { - triggerSizeChangeCheck(); - } - - /** - * Called when a resize event is received. - * - * This may trigger a lazy refresh or perform the size check immediately - * depending on the browser used and whether the server side requests - * resizes to be lazy. - */ - private void triggerSizeChangeCheck() { - /* - * IE (pre IE9 at least) will give us some false resize events due to - * problems with scrollbars. Firefox 3 might also produce some extra - * events. We postpone both the re-layouting and the server side event - * for a while to deal with these issues. - * - * We may also postpone these events to avoid slowness when resizing the - * browser window. Constantly recalculating the layout causes the resize - * operation to be really slow with complex layouts. - */ - boolean lazy = resizeLazy || BrowserInfo.get().isIE8(); - - if (lazy) { - delayedResizeExecutor.trigger(); - } else { - performSizeCheck(); - } - } - - /** - * Send new dimensions to the server. - */ - void sendClientResized() { - Element parentElement = getElement().getParentElement(); - int viewHeight = parentElement.getClientHeight(); - int viewWidth = parentElement.getClientWidth(); - - ResizeEvent.fire(this, viewWidth, viewHeight); - } - - public native static void goTo(String url) - /*-{ - $wnd.location = url; - }-*/; - - @Override - public void onWindowClosing(Window.ClosingEvent event) { - // Change focus on this window in order to ensure that all state is - // collected from textfields - // TODO this is a naive hack, that only works with text fields and may - // cause some odd issues. Should be replaced with a decent solution, see - // also related BeforeShortcutActionListener interface. Same interface - // might be usable here. - VTextField.flushChangesFromFocusedTextField(); - } - - private native static void loadAppIdListFromDOM(ArrayList<String> list) - /*-{ - var j; - for(j in $wnd.vaadin.vaadinConfigurations) { - // $entry not needed as function is not exported - list.@java.util.Collection::add(Ljava/lang/Object;)(j); - } - }-*/; - - @Override - public ShortcutActionHandler getShortcutActionHandler() { - return actionHandler; - } - - @Override - public void focus() { - getElement().focus(); - } - - /** - * Ensures the root is scrollable eg. after style name changes. - */ - void makeScrollable() { - if (touchScrollHandler == null) { - touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this); - } - touchScrollHandler.addElement(getElement()); - } - - @Override - public HandlerRegistration addResizeHandler(ResizeHandler resizeHandler) { - return addHandler(resizeHandler, ResizeEvent.getType()); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/UnknownComponentConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/UnknownComponentConnector.java deleted file mode 100644 index aaf37d0345..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/UnknownComponentConnector.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui; - -public class UnknownComponentConnector extends AbstractComponentConnector { - - @Override - public boolean delegateCaptionHandling() { - return false; - } - - @Override - public VUnknownComponent getWidget() { - return (VUnknownComponent) super.getWidget(); - } - - public void setServerSideClassName(String serverClassName) { - getWidget() - .setCaption( - "Widgetset does not contain implementation for " - + serverClassName - + ". Check its component connector's @Connect mapping, widgetsets " - + "GWT module description file and re-compile your" - + " widgetset. In case you have downloaded a vaadin" - + " add-on package, you might want to refer to " - + "<a href='http://vaadin.com/using-addons'>add-on " - + "instructions</a>."); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/VContextMenu.java b/client/src/com/vaadin/terminal/gwt/client/ui/VContextMenu.java deleted file mode 100644 index cf4f772bc9..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/VContextMenu.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.dom.client.NodeList; -import com.google.gwt.dom.client.TableRowElement; -import com.google.gwt.dom.client.TableSectionElement; -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.HasBlurHandlers; -import com.google.gwt.event.dom.client.HasFocusHandlers; -import com.google.gwt.event.dom.client.HasKeyDownHandlers; -import com.google.gwt.event.dom.client.HasKeyPressHandlers; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.event.dom.client.LoadEvent; -import com.google.gwt.event.dom.client.LoadHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.MenuBar; -import com.google.gwt.user.client.ui.MenuItem; -import com.google.gwt.user.client.ui.PopupPanel; -import com.google.gwt.user.client.ui.impl.FocusImpl; -import com.vaadin.terminal.gwt.client.Focusable; -import com.vaadin.terminal.gwt.client.Util; - -public class VContextMenu extends VOverlay implements SubPartAware { - - private ActionOwner actionOwner; - - private final CMenuBar menu = new CMenuBar(); - - private int left; - - private int top; - - private VLazyExecutor delayedImageLoadExecutioner = new VLazyExecutor(100, - new ScheduledCommand() { - @Override - public void execute() { - imagesLoaded(); - } - }); - - /** - * This method should be used only by Client object as only one per client - * should exists. Request an instance via client.getContextMenu(); - * - * @param cli - * to be set as an owner of menu - */ - public VContextMenu() { - super(true, false, true); - setWidget(menu); - setStyleName("v-contextmenu"); - } - - protected void imagesLoaded() { - if (isVisible()) { - show(); - } - } - - /** - * Sets the element from which to build menu - * - * @param ao - */ - public void setActionOwner(ActionOwner ao) { - actionOwner = ao; - } - - /** - * Shows context menu at given location IF it contain at least one item. - * - * @param left - * @param top - */ - public void showAt(int left, int top) { - final Action[] actions = actionOwner.getActions(); - if (actions == null || actions.length == 0) { - // Only show if there really are actions - return; - } - this.left = left; - this.top = top; - menu.clearItems(); - for (int i = 0; i < actions.length; i++) { - final Action a = actions[i]; - menu.addItem(new MenuItem(a.getHTML(), true, a)); - } - - // Attach onload listeners to all images - Util.sinkOnloadForImages(menu.getElement()); - - setPopupPositionAndShow(new PositionCallback() { - @Override - public void setPosition(int offsetWidth, int offsetHeight) { - // mac FF gets bad width due GWT popups overflow hacks, - // re-determine width - offsetWidth = menu.getOffsetWidth(); - int left = VContextMenu.this.left; - int top = VContextMenu.this.top; - if (offsetWidth + left > Window.getClientWidth()) { - left = left - offsetWidth; - if (left < 0) { - left = 0; - } - } - if (offsetHeight + top > Window.getClientHeight()) { - top = top - offsetHeight; - if (top < 0) { - top = 0; - } - } - setPopupPosition(left, top); - - /* - * Move keyboard focus to menu, deferring the focus setting so - * the focus is certainly moved to the menu in all browser after - * the positioning has been done. - */ - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - // Focus the menu. - menu.setFocus(true); - - // Unselect previously selected items - menu.selectItem(null); - } - }); - - } - }); - } - - public void showAt(ActionOwner ao, int left, int top) { - setActionOwner(ao); - showAt(left, top); - } - - /** - * Extend standard Gwt MenuBar to set proper settings and to override - * onPopupClosed method so that PopupPanel gets closed. - */ - class CMenuBar extends MenuBar implements HasFocusHandlers, - HasBlurHandlers, HasKeyDownHandlers, HasKeyPressHandlers, - Focusable, LoadHandler { - public CMenuBar() { - super(true); - addDomHandler(this, LoadEvent.getType()); - } - - @Override - public void onPopupClosed(PopupPanel sender, boolean autoClosed) { - super.onPopupClosed(sender, autoClosed); - - // make focusable, as we don't need access key magic we don't need - // to - // use FocusImpl.createFocusable - getElement().setTabIndex(0); - - hide(); - } - - /* - * public void onBrowserEvent(Event event) { // Remove current selection - * when mouse leaves if (DOM.eventGetType(event) == Event.ONMOUSEOUT) { - * Element to = DOM.eventGetToElement(event); if - * (!DOM.isOrHasChild(getElement(), to)) { DOM.setElementProperty( - * super.getSelectedItem().getElement(), "className", - * super.getSelectedItem().getStylePrimaryName()); } } - * - * super.onBrowserEvent(event); } - */ - - private MenuItem getItem(int index) { - return super.getItems().get(index); - } - - @Override - public HandlerRegistration addFocusHandler(FocusHandler handler) { - return addDomHandler(handler, FocusEvent.getType()); - } - - @Override - public HandlerRegistration addBlurHandler(BlurHandler handler) { - return addDomHandler(handler, BlurEvent.getType()); - } - - @Override - public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) { - return addDomHandler(handler, KeyDownEvent.getType()); - } - - @Override - public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) { - return addDomHandler(handler, KeyPressEvent.getType()); - } - - public void setFocus(boolean focus) { - if (focus) { - FocusImpl.getFocusImplForPanel().focus(getElement()); - } else { - FocusImpl.getFocusImplForPanel().blur(getElement()); - } - } - - @Override - public void focus() { - setFocus(true); - } - - @Override - public void onLoad(LoadEvent event) { - // Handle icon onload events to ensure shadow is resized correctly - delayedImageLoadExecutioner.trigger(); - } - - } - - @Override - public Element getSubPartElement(String subPart) { - int index = Integer.parseInt(subPart.substring(6)); - // ApplicationConnection.getConsole().log( - // "Searching element for selection index " + index); - MenuItem item = menu.getItem(index); - // ApplicationConnection.getConsole().log("Item: " + item); - // Item refers to the td, which is the parent of the clickable element - return item.getElement().getFirstChildElement().cast(); - } - - @Override - public String getSubPartName(Element subElement) { - if (getElement().isOrHasChild(subElement)) { - com.google.gwt.dom.client.Element e = subElement; - { - while (e != null && !e.getTagName().toLowerCase().equals("tr")) { - e = e.getParentElement(); - // ApplicationConnection.getConsole().log("Found row"); - } - } - com.google.gwt.dom.client.TableSectionElement parentElement = (TableSectionElement) e - .getParentElement(); - NodeList<TableRowElement> rows = parentElement.getRows(); - for (int i = 0; i < rows.getLength(); i++) { - if (rows.getItem(i) == e) { - // ApplicationConnection.getConsole().log( - // "Found index for row" + 1); - return "option" + i; - } - } - return null; - } else { - return null; - } - } - - /** - * Hides context menu if it is currently shown by given action owner. - * - * @param actionOwner - */ - public void ensureHidden(ActionOwner actionOwner) { - if (this.actionOwner == actionOwner) { - hide(); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/VLazyExecutor.java b/client/src/com/vaadin/terminal/gwt/client/ui/VLazyExecutor.java deleted file mode 100644 index 85ee27a36a..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/VLazyExecutor.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.user.client.Timer; - -/** - * Executes the given command {@code delayMs} milliseconds after a call to - * {@link #trigger()}. Calling {@link #trigger()} again before the command has - * been executed causes the execution to be rescheduled to {@code delayMs} after - * the second call. - * - */ -public class VLazyExecutor { - - private Timer timer; - private int delayMs; - private ScheduledCommand cmd; - - /** - * @param delayMs - * Delay in milliseconds to wait before executing the command - * @param cmd - * The command to execute - */ - public VLazyExecutor(int delayMs, ScheduledCommand cmd) { - this.delayMs = delayMs; - this.cmd = cmd; - } - - /** - * Triggers execution of the command. Each call reschedules any existing - * execution to {@link #delayMs} milliseconds from that point in time. - */ - public void trigger() { - if (timer == null) { - timer = new Timer() { - @Override - public void run() { - timer = null; - cmd.execute(); - } - }; - } - // Schedule automatically cancels any old schedule - timer.schedule(delayMs); - - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/VMediaBase.java b/client/src/com/vaadin/terminal/gwt/client/ui/VMediaBase.java deleted file mode 100644 index 9d83dde3d6..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/VMediaBase.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.MediaElement; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.Widget; - -public abstract class VMediaBase extends Widget { - - private MediaElement media; - - /** - * Sets the MediaElement that is to receive all commands and properties. - * - * @param element - */ - public void setMediaElement(MediaElement element) { - setElement(element); - media = element; - } - - public void play() { - media.play(); - } - - public void pause() { - media.pause(); - } - - public void setAltText(String alt) { - media.appendChild(Document.get().createTextNode(alt)); - } - - public void setControls(boolean shouldShowControls) { - media.setControls(shouldShowControls); - } - - public void setAutoplay(boolean shouldAutoplay) { - media.setAutoplay(shouldAutoplay); - } - - public void setMuted(boolean mediaMuted) { - media.setMuted(mediaMuted); - } - - public void addSource(String sourceUrl, String sourceType) { - Element src = Document.get().createElement("source").cast(); - src.setAttribute("src", sourceUrl); - src.setAttribute("type", sourceType); - media.appendChild(src); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/VOverlay.java b/client/src/com/vaadin/terminal/gwt/client/ui/VOverlay.java deleted file mode 100644 index 97201de297..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/VOverlay.java +++ /dev/null @@ -1,595 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.animation.client.Animation; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.IFrameElement; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.BorderStyle; -import com.google.gwt.dom.client.Style.Position; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.event.logical.shared.CloseEvent; -import com.google.gwt.event.logical.shared.CloseHandler; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.PopupPanel; -import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.BrowserInfo; - -/** - * In Vaadin UI this Overlay should always be used for all elements that - * temporary float over other components like context menus etc. This is to deal - * stacking order correctly with VWindow objects. - */ -public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { - - public static class PositionAndSize { - private int left, top, width, height; - - public PositionAndSize(int left, int top, int width, int height) { - super(); - setLeft(left); - setTop(top); - setWidth(width); - setHeight(height); - } - - public int getLeft() { - return left; - } - - public void setLeft(int left) { - this.left = left; - } - - public int getTop() { - return top; - } - - public void setTop(int top) { - this.top = top; - } - - public int getWidth() { - return width; - } - - public void setWidth(int width) { - if (width < 0) { - width = 0; - } - - this.width = width; - } - - public int getHeight() { - return height; - } - - public void setHeight(int height) { - if (height < 0) { - height = 0; - } - - this.height = height; - } - - public void setAnimationFromCenterProgress(double progress) { - left += (int) (width * (1.0 - progress) / 2.0); - top += (int) (height * (1.0 - progress) / 2.0); - width = (int) (width * progress); - height = (int) (height * progress); - } - } - - /* - * The z-index value from where all overlays live. This can be overridden in - * any extending class. - */ - public static int Z_INDEX = 20000; - - private static int leftFix = -1; - - private static int topFix = -1; - - /* - * Shadow element style. If an extending class wishes to use a different - * style of shadow, it can use setShadowStyle(String) to give the shadow - * element a new style name. - */ - public static final String CLASSNAME_SHADOW = "v-shadow"; - - /* - * The shadow element for this overlay. - */ - private Element shadow; - - /* - * Creator of VOverlow (widget that made the instance, not the layout - * parent) - */ - private Widget owner; - - /** - * The shim iframe behind the overlay, allowing PDFs and applets to be - * covered by overlays. - */ - private IFrameElement shimElement; - - /** - * The HTML snippet that is used to render the actual shadow. In consists of - * nine different DIV-elements with the following class names: - * - * <pre> - * .v-shadow[-stylename] - * ---------------------------------------------- - * | .top-left | .top | .top-right | - * |---------------|-----------|----------------| - * | | | | - * | .left | .center | .right | - * | | | | - * |---------------|-----------|----------------| - * | .bottom-left | .bottom | .bottom-right | - * ---------------------------------------------- - * </pre> - * - * See default theme 'shadow.css' for implementation example. - */ - private static final String SHADOW_HTML = "<div class=\"top-left\"></div><div class=\"top\"></div><div class=\"top-right\"></div><div class=\"left\"></div><div class=\"center\"></div><div class=\"right\"></div><div class=\"bottom-left\"></div><div class=\"bottom\"></div><div class=\"bottom-right\"></div>"; - - /** - * Matches {@link PopupPanel}.ANIMATION_DURATION - */ - private static final int POPUP_PANEL_ANIMATION_DURATION = 200; - - private boolean sinkShadowEvents = false; - - public VOverlay() { - super(); - adjustZIndex(); - } - - public VOverlay(boolean autoHide) { - super(autoHide); - adjustZIndex(); - } - - public VOverlay(boolean autoHide, boolean modal) { - super(autoHide, modal); - adjustZIndex(); - } - - public VOverlay(boolean autoHide, boolean modal, boolean showShadow) { - super(autoHide, modal); - setShadowEnabled(showShadow); - adjustZIndex(); - } - - /** - * Method to controle whether DOM elements for shadow are added. With this - * method subclasses can control displaying of shadow also after the - * constructor. - * - * @param enabled - * true if shadow should be displayed - */ - protected void setShadowEnabled(boolean enabled) { - if (enabled != isShadowEnabled()) { - if (enabled) { - shadow = DOM.createDiv(); - shadow.setClassName(CLASSNAME_SHADOW); - shadow.setInnerHTML(SHADOW_HTML); - DOM.setStyleAttribute(shadow, "position", "absolute"); - addCloseHandler(this); - } else { - removeShadowIfPresent(); - shadow = null; - } - } - } - - protected boolean isShadowEnabled() { - return shadow != null; - } - - private void removeShimElement() { - if (shimElement != null) { - shimElement.removeFromParent(); - } - } - - private void removeShadowIfPresent() { - if (isShadowAttached()) { - shadow.removeFromParent(); - - // Remove event listener from the shadow - unsinkShadowEvents(); - } - } - - private boolean isShadowAttached() { - return isShadowEnabled() && shadow.getParentElement() != null; - } - - private boolean isShimElementAttached() { - return shimElement != null && shimElement.hasParentElement(); - } - - private void adjustZIndex() { - setZIndex(Z_INDEX); - } - - /** - * Set the z-index (visual stack position) for this overlay. - * - * @param zIndex - * The new z-index - */ - protected void setZIndex(int zIndex) { - DOM.setStyleAttribute(getElement(), "zIndex", "" + zIndex); - if (isShadowEnabled()) { - DOM.setStyleAttribute(shadow, "zIndex", "" + zIndex); - } - } - - @Override - public void setPopupPosition(int left, int top) { - // TODO, this should in fact be part of - // Document.get().getBodyOffsetLeft/Top(). Would require overriding DOM - // for all permutations. Now adding fix as margin instead of fixing - // left/top because parent class saves the position. - Style style = getElement().getStyle(); - style.setMarginLeft(-adjustByRelativeLeftBodyMargin(), Unit.PX); - style.setMarginTop(-adjustByRelativeTopBodyMargin(), Unit.PX); - super.setPopupPosition(left, top); - positionOrSizeUpdated(isAnimationEnabled() ? 0 : 1); - } - - private IFrameElement getShimElement() { - if (shimElement == null && needsShimElement()) { - shimElement = Document.get().createIFrameElement(); - - // Insert shim iframe before the main overlay element. It does not - // matter if it is in front or behind the shadow as we cannot put a - // shim behind the shadow due to its transparency. - shimElement.getStyle().setPosition(Position.ABSOLUTE); - shimElement.getStyle().setBorderStyle(BorderStyle.NONE); - shimElement.setTabIndex(-1); - shimElement.setFrameBorder(0); - shimElement.setMarginHeight(0); - } - return shimElement; - } - - private int getActualTop() { - int y = getAbsoluteTop(); - - /* This is needed for IE7 at least */ - // Account for the difference between absolute position and the - // body's positioning context. - y -= Document.get().getBodyOffsetTop(); - y -= adjustByRelativeTopBodyMargin(); - - return y; - } - - private int getActualLeft() { - int x = getAbsoluteLeft(); - - /* This is needed for IE7 at least */ - // Account for the difference between absolute position and the - // body's positioning context. - x -= Document.get().getBodyOffsetLeft(); - x -= adjustByRelativeLeftBodyMargin(); - - return x; - } - - private static int adjustByRelativeTopBodyMargin() { - if (topFix == -1) { - topFix = detectRelativeBodyFixes("top"); - } - return topFix; - } - - private native static int detectRelativeBodyFixes(String axis) - /*-{ - try { - var b = $wnd.document.body; - var cstyle = b.currentStyle ? b.currentStyle : getComputedStyle(b); - if(cstyle && cstyle.position == 'relative') { - return b.getBoundingClientRect()[axis]; - } - } catch(e){} - return 0; - }-*/; - - private static int adjustByRelativeLeftBodyMargin() { - if (leftFix == -1) { - leftFix = detectRelativeBodyFixes("left"); - - } - return leftFix; - } - - @Override - public void show() { - super.show(); - if (isAnimationEnabled()) { - new ResizeAnimation().run(POPUP_PANEL_ANIMATION_DURATION); - } else { - positionOrSizeUpdated(1.0); - } - } - - @Override - protected void onDetach() { - super.onDetach(); - - // Always ensure shadow is removed when the overlay is removed. - removeShadowIfPresent(); - removeShimElement(); - } - - @Override - public void setVisible(boolean visible) { - super.setVisible(visible); - if (isShadowEnabled()) { - shadow.getStyle().setProperty("visibility", - visible ? "visible" : "hidden"); - } - } - - @Override - public void setWidth(String width) { - super.setWidth(width); - positionOrSizeUpdated(1.0); - } - - @Override - public void setHeight(String height) { - super.setHeight(height); - positionOrSizeUpdated(1.0); - } - - /** - * Sets the shadow style for this overlay. Will override any previous style - * for the shadow. The default style name is defined by CLASSNAME_SHADOW. - * The given style will be prefixed with CLASSNAME_SHADOW. - * - * @param style - * The new style name for the shadow element. Will be prefixed by - * CLASSNAME_SHADOW, e.g. style=='foobar' -> actual style - * name=='v-shadow-foobar'. - */ - protected void setShadowStyle(String style) { - if (isShadowEnabled()) { - shadow.setClassName(CLASSNAME_SHADOW + "-" + style); - } - } - - /** - * Extending classes should always call this method after they change the - * size of overlay without using normal 'setWidth(String)' and - * 'setHeight(String)' methods (if not calling super.setWidth/Height). - * - */ - public void positionOrSizeUpdated() { - positionOrSizeUpdated(1.0); - } - - /** - * @deprecated Call {@link #positionOrSizeUpdated()} instead. - */ - @Deprecated - protected void updateShadowSizeAndPosition() { - positionOrSizeUpdated(); - } - - /** - * Recalculates proper position and dimensions for the shadow and shim - * elements. Can be used to animate the related elements, using the - * 'progress' parameter (used to animate the shadow in sync with GWT - * PopupPanel's default animation 'PopupPanel.AnimationType.CENTER'). - * - * @param progress - * A value between 0.0 and 1.0, indicating the progress of the - * animation (0=start, 1=end). - */ - private void positionOrSizeUpdated(final double progress) { - // Don't do anything if overlay element is not attached - if (!isAttached()) { - return; - } - // Calculate proper z-index - String zIndex = null; - try { - // Odd behaviour with Windows Hosted Mode forces us to use - // this redundant try/catch block (See dev.vaadin.com #2011) - zIndex = DOM.getStyleAttribute(getElement(), "zIndex"); - } catch (Exception ignore) { - // Ignored, will cause no harm - zIndex = "1000"; - } - if (zIndex == null) { - zIndex = "" + Z_INDEX; - } - // Calculate position and size - if (BrowserInfo.get().isIE()) { - // Shake IE - getOffsetHeight(); - getOffsetWidth(); - } - - PositionAndSize positionAndSize = new PositionAndSize(getActualLeft(), - getActualTop(), getOffsetWidth(), getOffsetHeight()); - - // Animate the size - positionAndSize.setAnimationFromCenterProgress(progress); - - // Opera needs some shaking to get parts of the shadow showing - // properly - // (ticket #2704) - if (BrowserInfo.get().isOpera() && isShadowEnabled()) { - // Clear the height of all middle elements - DOM.getChild(shadow, 3).getStyle().setProperty("height", "auto"); - DOM.getChild(shadow, 4).getStyle().setProperty("height", "auto"); - DOM.getChild(shadow, 5).getStyle().setProperty("height", "auto"); - } - - // Update correct values - if (isShadowEnabled()) { - updatePositionAndSize(shadow, positionAndSize); - DOM.setStyleAttribute(shadow, "zIndex", zIndex); - DOM.setStyleAttribute(shadow, "display", progress < 0.9 ? "none" - : ""); - } - if (needsShimElement()) { - updatePositionAndSize((Element) Element.as(getShimElement()), - positionAndSize); - } - - // Opera fix, part 2 (ticket #2704) - if (BrowserInfo.get().isOpera() && isShadowEnabled()) { - // We'll fix the height of all the middle elements - DOM.getChild(shadow, 3) - .getStyle() - .setPropertyPx("height", - DOM.getChild(shadow, 3).getOffsetHeight()); - DOM.getChild(shadow, 4) - .getStyle() - .setPropertyPx("height", - DOM.getChild(shadow, 4).getOffsetHeight()); - DOM.getChild(shadow, 5) - .getStyle() - .setPropertyPx("height", - DOM.getChild(shadow, 5).getOffsetHeight()); - } - - // Attach to dom if not there already - if (isShadowEnabled() && !isShadowAttached()) { - RootPanel.get().getElement().insertBefore(shadow, getElement()); - sinkShadowEvents(); - } - if (needsShimElement() && !isShimElementAttached()) { - RootPanel.get().getElement() - .insertBefore(getShimElement(), getElement()); - } - - } - - /** - * Returns true if we should add a shim iframe below the overlay to deal - * with zindex issues with PDFs and applets. Can be overriden to disable - * shim iframes if they are not needed. - * - * @return true if a shim iframe should be added, false otherwise - */ - protected boolean needsShimElement() { - BrowserInfo info = BrowserInfo.get(); - return info.isIE() && info.isBrowserVersionNewerOrEqual(8, 0); - } - - private void updatePositionAndSize(Element e, - PositionAndSize positionAndSize) { - e.getStyle().setLeft(positionAndSize.getLeft(), Unit.PX); - e.getStyle().setTop(positionAndSize.getTop(), Unit.PX); - e.getStyle().setWidth(positionAndSize.getWidth(), Unit.PX); - e.getStyle().setHeight(positionAndSize.getHeight(), Unit.PX); - } - - protected class ResizeAnimation extends Animation { - @Override - protected void onUpdate(double progress) { - positionOrSizeUpdated(progress); - } - } - - @Override - public void onClose(CloseEvent<PopupPanel> event) { - removeShadowIfPresent(); - } - - @Override - public void sinkEvents(int eventBitsToAdd) { - super.sinkEvents(eventBitsToAdd); - // Also sink events on the shadow if present - sinkShadowEvents(); - } - - private void sinkShadowEvents() { - if (isSinkShadowEvents() && isShadowAttached()) { - // Sink the same events as the actual overlay has sunk - DOM.sinkEvents(shadow, DOM.getEventsSunk(getElement())); - // Send events to VOverlay.onBrowserEvent - DOM.setEventListener(shadow, this); - } - } - - private void unsinkShadowEvents() { - if (isShadowAttached()) { - DOM.setEventListener(shadow, null); - DOM.sinkEvents(shadow, 0); - } - } - - /** - * Enables or disables sinking the events of the shadow to the same - * onBrowserEvent as events to the actual overlay goes. - * - * Please note, that if you enable this, you can't assume that e.g. - * event.getEventTarget returns an element inside the DOM structure of the - * overlay - * - * @param sinkShadowEvents - */ - protected void setSinkShadowEvents(boolean sinkShadowEvents) { - this.sinkShadowEvents = sinkShadowEvents; - if (sinkShadowEvents) { - sinkShadowEvents(); - } else { - unsinkShadowEvents(); - } - } - - protected boolean isSinkShadowEvents() { - return sinkShadowEvents; - } - - /** - * Get owner (Widget that made this VOverlay, not the layout parent) of - * VOverlay - * - * @return Owner (creator) or null if not defined - */ - public Widget getOwner() { - return owner; - } - - /** - * Set owner (Widget that made this VOverlay, not the layout parent) of - * VOverlay - * - * @param owner - * Owner (creator) of VOverlay - */ - public void setOwner(Widget owner) { - this.owner = owner; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/VUnknownComponent.java b/client/src/com/vaadin/terminal/gwt/client/ui/VUnknownComponent.java deleted file mode 100644 index f4c925a313..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/VUnknownComponent.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui; - -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.VerticalPanel; -import com.vaadin.terminal.gwt.client.SimpleTree; - -public class VUnknownComponent extends Composite { - - com.google.gwt.user.client.ui.Label caption = new com.google.gwt.user.client.ui.Label();; - SimpleTree uidlTree; - protected VerticalPanel panel; - - public VUnknownComponent() { - panel = new VerticalPanel(); - panel.add(caption); - initWidget(panel); - setStyleName("vaadin-unknown"); - caption.setStyleName("vaadin-unknown-caption"); - } - - public void setCaption(String c) { - caption.getElement().setInnerHTML(c); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/Vaadin6Connector.java b/client/src/com/vaadin/terminal/gwt/client/ui/Vaadin6Connector.java deleted file mode 100644 index 8d743bb10b..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/Vaadin6Connector.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui; - -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; - -public abstract class Vaadin6Connector extends AbstractComponentConnector - implements Paintable { - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - ((Paintable) getWidget()).updateFromUIDL(uidl, client); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/absolutelayout/AbsoluteLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/absolutelayout/AbsoluteLayoutConnector.java deleted file mode 100644 index 85de558f98..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/absolutelayout/AbsoluteLayoutConnector.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.absolutelayout; - -import java.util.HashMap; -import java.util.Map; - -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.LayoutClickRpc; -import com.vaadin.shared.ui.absolutelayout.AbsoluteLayoutServerRpc; -import com.vaadin.shared.ui.absolutelayout.AbsoluteLayoutState; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; -import com.vaadin.terminal.gwt.client.DirectionalManagedLayout; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VCaption; -import com.vaadin.terminal.gwt.client.communication.RpcProxy; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector; -import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler; -import com.vaadin.terminal.gwt.client.ui.absolutelayout.VAbsoluteLayout.AbsoluteWrapper; -import com.vaadin.ui.AbsoluteLayout; - -@Connect(AbsoluteLayout.class) -public class AbsoluteLayoutConnector extends - AbstractComponentContainerConnector implements DirectionalManagedLayout { - - private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler( - this) { - - @Override - protected ComponentConnector getChildComponent(Element element) { - return getConnectorForElement(element); - } - - @Override - protected LayoutClickRpc getLayoutClickRPC() { - return rpc; - }; - - }; - - private AbsoluteLayoutServerRpc rpc; - - private Map<String, AbsoluteWrapper> connectorIdToComponentWrapper = new HashMap<String, AbsoluteWrapper>(); - - @Override - protected void init() { - super.init(); - rpc = RpcProxy.create(AbsoluteLayoutServerRpc.class, this); - } - - /** - * Returns the deepest nested child component which contains "element". The - * child component is also returned if "element" is part of its caption. - * - * @param element - * An element that is a nested sub element of the root element in - * this layout - * @return The Paintable which the element is a part of. Null if the element - * belongs to the layout and not to a child. - */ - protected ComponentConnector getConnectorForElement(Element element) { - return Util.getConnectorForElement(getConnection(), getWidget(), - element); - } - - @Override - public void updateCaption(ComponentConnector component) { - VAbsoluteLayout absoluteLayoutWidget = getWidget(); - AbsoluteWrapper componentWrapper = getWrapper(component); - - boolean captionIsNeeded = VCaption.isNeeded(component.getState()); - - VCaption caption = componentWrapper.getCaption(); - - if (captionIsNeeded) { - if (caption == null) { - caption = new VCaption(component, getConnection()); - absoluteLayoutWidget.add(caption); - componentWrapper.setCaption(caption); - } - caption.updateCaption(); - componentWrapper.updateCaptionPosition(); - } else { - if (caption != null) { - caption.removeFromParent(); - } - } - - } - - @Override - public VAbsoluteLayout getWidget() { - return (VAbsoluteLayout) super.getWidget(); - } - - @Override - public AbsoluteLayoutState getState() { - return (AbsoluteLayoutState) super.getState(); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - clickEventHandler.handleEventHandlerRegistration(); - - // TODO Margin handling - - for (ComponentConnector child : getChildComponents()) { - getWrapper(child).setPosition( - getState().getConnectorPosition(child)); - } - }; - - private AbsoluteWrapper getWrapper(ComponentConnector child) { - String childId = child.getConnectorId(); - AbsoluteWrapper wrapper = connectorIdToComponentWrapper.get(childId); - if (wrapper != null) { - return wrapper; - } - - wrapper = new AbsoluteWrapper(child.getWidget()); - connectorIdToComponentWrapper.put(childId, wrapper); - getWidget().add(wrapper); - return wrapper; - - } - - @Override - public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { - super.onConnectorHierarchyChange(event); - - for (ComponentConnector child : getChildComponents()) { - getWrapper(child); - } - - for (ComponentConnector oldChild : event.getOldChildren()) { - if (oldChild.getParent() != this) { - String connectorId = oldChild.getConnectorId(); - AbsoluteWrapper absoluteWrapper = connectorIdToComponentWrapper - .remove(connectorId); - absoluteWrapper.destroy(); - } - } - } - - @Override - public void layoutVertically() { - VAbsoluteLayout layout = getWidget(); - for (ComponentConnector paintable : getChildComponents()) { - Widget widget = paintable.getWidget(); - AbsoluteWrapper wrapper = (AbsoluteWrapper) widget.getParent(); - Style wrapperStyle = wrapper.getElement().getStyle(); - - if (paintable.isRelativeHeight()) { - int h; - if (wrapper.top != null && wrapper.bottom != null) { - h = wrapper.getOffsetHeight(); - } else if (wrapper.bottom != null) { - // top not defined, available space 0... bottom of - // wrapper - h = wrapper.getElement().getOffsetTop() - + wrapper.getOffsetHeight(); - } else { - // top defined or both undefined, available space == - // canvas - top - h = layout.canvas.getOffsetHeight() - - wrapper.getElement().getOffsetTop(); - } - wrapperStyle.setHeight(h, Unit.PX); - getLayoutManager().reportHeightAssignedToRelative(paintable, h); - } else { - wrapperStyle.clearHeight(); - } - - wrapper.updateCaptionPosition(); - } - } - - @Override - public void layoutHorizontally() { - VAbsoluteLayout layout = getWidget(); - for (ComponentConnector paintable : getChildComponents()) { - AbsoluteWrapper wrapper = getWrapper(paintable); - Style wrapperStyle = wrapper.getElement().getStyle(); - - if (paintable.isRelativeWidth()) { - int w; - if (wrapper.left != null && wrapper.right != null) { - w = wrapper.getOffsetWidth(); - } else if (wrapper.right != null) { - // left == null - // available width == right edge == offsetleft + width - w = wrapper.getOffsetWidth() - + wrapper.getElement().getOffsetLeft(); - } else { - // left != null && right == null || left == null && - // right == null - // available width == canvas width - offset left - w = layout.canvas.getOffsetWidth() - - wrapper.getElement().getOffsetLeft(); - } - wrapperStyle.setWidth(w, Unit.PX); - getLayoutManager().reportWidthAssignedToRelative(paintable, w); - } else { - wrapperStyle.clearWidth(); - } - - wrapper.updateCaptionPosition(); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/absolutelayout/VAbsoluteLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/absolutelayout/VAbsoluteLayout.java deleted file mode 100644 index 8c572417df..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/absolutelayout/VAbsoluteLayout.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.absolutelayout; - -import com.google.gwt.dom.client.DivElement; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Style; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.ComplexPanel; -import com.google.gwt.user.client.ui.SimplePanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.VCaption; - -public class VAbsoluteLayout extends ComplexPanel { - - /** Tag name for widget creation */ - public static final String TAGNAME = "absolutelayout"; - - /** Class name, prefix in styling */ - public static final String CLASSNAME = "v-absolutelayout"; - - private DivElement marginElement; - - protected final Element canvas = DOM.createDiv(); - - private Object previousStyleName; - - protected ApplicationConnection client; - - public VAbsoluteLayout() { - setElement(Document.get().createDivElement()); - setStyleName(CLASSNAME); - marginElement = Document.get().createDivElement(); - canvas.getStyle().setProperty("position", "relative"); - canvas.getStyle().setProperty("overflow", "hidden"); - marginElement.appendChild(canvas); - getElement().appendChild(marginElement); - - canvas.setClassName(CLASSNAME + "-canvas"); - canvas.setClassName(CLASSNAME + "-margin"); - } - - @Override - public void add(Widget child) { - super.add(child, canvas); - } - - public static class AbsoluteWrapper extends SimplePanel { - private String css; - String left; - String top; - String right; - String bottom; - private String zIndex; - - private VCaption caption; - - public AbsoluteWrapper(Widget child) { - setWidget(child); - setStyleName(CLASSNAME + "-wrapper"); - } - - public VCaption getCaption() { - return caption; - } - - public void setCaption(VCaption caption) { - this.caption = caption; - } - - public void destroy() { - if (caption != null) { - caption.removeFromParent(); - } - removeFromParent(); - } - - public void setPosition(String stringAttribute) { - if (css == null || !css.equals(stringAttribute)) { - css = stringAttribute; - top = right = bottom = left = zIndex = null; - if (!css.equals("")) { - String[] properties = css.split(";"); - for (int i = 0; i < properties.length; i++) { - String[] keyValue = properties[i].split(":"); - if (keyValue[0].equals("left")) { - left = keyValue[1]; - } else if (keyValue[0].equals("top")) { - top = keyValue[1]; - } else if (keyValue[0].equals("right")) { - right = keyValue[1]; - } else if (keyValue[0].equals("bottom")) { - bottom = keyValue[1]; - } else if (keyValue[0].equals("z-index")) { - zIndex = keyValue[1]; - } - } - } - // ensure ne values - Style style = getElement().getStyle(); - /* - * IE8 dies when nulling zIndex, even in IE7 mode. All other css - * properties (and even in older IE's) accept null values just - * fine. Assign empty string instead of null. - */ - if (zIndex != null) { - style.setProperty("zIndex", zIndex); - } else { - style.setProperty("zIndex", ""); - } - style.setProperty("top", top); - style.setProperty("left", left); - style.setProperty("right", right); - style.setProperty("bottom", bottom); - - } - updateCaptionPosition(); - } - - void updateCaptionPosition() { - if (caption != null) { - Style style = caption.getElement().getStyle(); - style.setProperty("position", "absolute"); - style.setPropertyPx("left", getElement().getOffsetLeft()); - style.setPropertyPx("top", getElement().getOffsetTop() - - caption.getHeight()); - } - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/accordion/AccordionConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/accordion/AccordionConnector.java deleted file mode 100644 index b107f41285..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/accordion/AccordionConnector.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.accordion; - -import java.util.Iterator; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout; -import com.vaadin.terminal.gwt.client.ui.accordion.VAccordion.StackItem; -import com.vaadin.terminal.gwt.client.ui.layout.MayScrollChildren; -import com.vaadin.terminal.gwt.client.ui.tabsheet.TabsheetBaseConnector; -import com.vaadin.ui.Accordion; - -@Connect(Accordion.class) -public class AccordionConnector extends TabsheetBaseConnector implements - SimpleManagedLayout, MayScrollChildren { - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - getWidget().selectedUIDLItemIndex = -1; - super.updateFromUIDL(uidl, client); - /* - * Render content after all tabs have been created and we know how large - * the content area is - */ - if (getWidget().selectedUIDLItemIndex >= 0) { - StackItem selectedItem = getWidget().getStackItem( - getWidget().selectedUIDLItemIndex); - UIDL selectedTabUIDL = getWidget().lazyUpdateMap - .remove(selectedItem); - getWidget().open(getWidget().selectedUIDLItemIndex); - - selectedItem.setContent(selectedTabUIDL); - } else if (isRealUpdate(uidl) && getWidget().openTab != null) { - getWidget().close(getWidget().openTab); - } - - getWidget().iLayout(); - // finally render possible hidden tabs - if (getWidget().lazyUpdateMap.size() > 0) { - for (Iterator iterator = getWidget().lazyUpdateMap.keySet() - .iterator(); iterator.hasNext();) { - StackItem item = (StackItem) iterator.next(); - item.setContent(getWidget().lazyUpdateMap.get(item)); - } - getWidget().lazyUpdateMap.clear(); - } - - } - - @Override - public VAccordion getWidget() { - return (VAccordion) super.getWidget(); - } - - @Override - public void updateCaption(ComponentConnector component) { - /* Accordion does not render its children's captions */ - } - - @Override - public void layout() { - VAccordion accordion = getWidget(); - - accordion.updateOpenTabSize(); - - if (isUndefinedHeight()) { - accordion.openTab.setHeightFromWidget(); - } - accordion.iLayout(); - - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java b/client/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java deleted file mode 100644 index d911dc66f3..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.accordion; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.ComplexPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ui.tabsheet.TabsheetBaseConstants; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VCaption; -import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate; -import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate.TouchScrollHandler; -import com.vaadin.terminal.gwt.client.ui.tabsheet.VTabsheetBase; - -public class VAccordion extends VTabsheetBase { - - public static final String CLASSNAME = "v-accordion"; - - private Set<Widget> widgets = new HashSet<Widget>(); - - HashMap<StackItem, UIDL> lazyUpdateMap = new HashMap<StackItem, UIDL>(); - - StackItem openTab = null; - - int selectedUIDLItemIndex = -1; - - private final TouchScrollHandler touchScrollHandler; - - public VAccordion() { - super(CLASSNAME); - touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this); - } - - @Override - protected void renderTab(UIDL tabUidl, int index, boolean selected, - boolean hidden) { - StackItem item; - int itemIndex; - if (getWidgetCount() <= index) { - // Create stackItem and render caption - item = new StackItem(tabUidl); - if (getWidgetCount() == 0) { - item.addStyleDependentName("first"); - } - itemIndex = getWidgetCount(); - add(item, getElement()); - } else { - item = getStackItem(index); - item = moveStackItemIfNeeded(item, index, tabUidl); - itemIndex = index; - } - item.updateCaption(tabUidl); - - item.setVisible(!hidden); - - if (selected) { - selectedUIDLItemIndex = itemIndex; - } - - if (tabUidl.getChildCount() > 0) { - lazyUpdateMap.put(item, tabUidl.getChildUIDL(0)); - } - } - - /** - * This method tries to find out if a tab has been rendered with a different - * index previously. If this is the case it re-orders the children so the - * same StackItem is used for rendering this time. E.g. if the first tab has - * been removed all tabs which contain cached content must be moved 1 step - * up to preserve the cached content. - * - * @param item - * @param newIndex - * @param tabUidl - * @return - */ - private StackItem moveStackItemIfNeeded(StackItem item, int newIndex, - UIDL tabUidl) { - UIDL tabContentUIDL = null; - ComponentConnector tabContent = null; - if (tabUidl.getChildCount() > 0) { - tabContentUIDL = tabUidl.getChildUIDL(0); - tabContent = client.getPaintable(tabContentUIDL); - } - - Widget itemWidget = item.getComponent(); - if (tabContent != null) { - if (tabContent != itemWidget) { - /* - * This is not the same widget as before, find out if it has - * been moved - */ - int oldIndex = -1; - StackItem oldItem = null; - for (int i = 0; i < getWidgetCount(); i++) { - Widget w = getWidget(i); - oldItem = (StackItem) w; - if (tabContent == oldItem.getComponent()) { - oldIndex = i; - break; - } - } - - if (oldIndex != -1 && oldIndex > newIndex) { - /* - * The tab has previously been rendered in another position - * so we must move the cached content to correct position. - * We move only items with oldIndex > newIndex to prevent - * moving items already rendered in this update. If for - * instance tabs 1,2,3 are removed and added as 3,2,1 we - * cannot re-use "1" when we get to the third tab. - */ - insert(oldItem, getElement(), newIndex, true); - return oldItem; - } - } - } else { - // Tab which has never been loaded. Must assure we use an empty - // StackItem - Widget oldWidget = item.getComponent(); - if (oldWidget != null) { - oldWidget.removeFromParent(); - } - } - return item; - } - - void open(int itemIndex) { - StackItem item = (StackItem) getWidget(itemIndex); - boolean alreadyOpen = false; - if (openTab != null) { - if (openTab.isOpen()) { - if (openTab == item) { - alreadyOpen = true; - } else { - openTab.close(); - } - } - } - if (!alreadyOpen) { - item.open(); - activeTabIndex = itemIndex; - openTab = item; - } - - // Update the size for the open tab - updateOpenTabSize(); - } - - void close(StackItem item) { - if (!item.isOpen()) { - return; - } - - item.close(); - activeTabIndex = -1; - openTab = null; - - } - - @Override - protected void selectTab(final int index, final UIDL contentUidl) { - StackItem item = getStackItem(index); - if (index != activeTabIndex) { - open(index); - iLayout(); - // TODO Check if this is needed - client.runDescendentsLayout(this); - - } - item.setContent(contentUidl); - } - - public void onSelectTab(StackItem item) { - final int index = getWidgetIndex(item); - if (index != activeTabIndex && !disabled && !readonly - && !disabledTabKeys.contains(tabKeys.get(index))) { - addStyleDependentName("loading"); - client.updateVariable(id, "selected", "" + tabKeys.get(index), true); - } - } - - /** - * Sets the size of the open tab - */ - void updateOpenTabSize() { - if (openTab == null) { - return; - } - - // WIDTH - if (!isDynamicWidth()) { - openTab.setWidth("100%"); - } else { - openTab.setWidth(null); - } - - // HEIGHT - if (!isDynamicHeight()) { - int usedPixels = 0; - for (Widget w : getChildren()) { - StackItem item = (StackItem) w; - if (item == openTab) { - usedPixels += item.getCaptionHeight(); - } else { - // This includes the captionNode borders - usedPixels += item.getHeight(); - } - } - - int offsetHeight = getOffsetHeight(); - - int spaceForOpenItem = offsetHeight - usedPixels; - - if (spaceForOpenItem < 0) { - spaceForOpenItem = 0; - } - - openTab.setHeight(spaceForOpenItem); - } else { - openTab.setHeightFromWidget(); - - } - - } - - public void iLayout() { - if (openTab == null) { - return; - } - - if (isDynamicWidth()) { - int maxWidth = 40; - for (Widget w : getChildren()) { - StackItem si = (StackItem) w; - int captionWidth = si.getCaptionWidth(); - if (captionWidth > maxWidth) { - maxWidth = captionWidth; - } - } - int widgetWidth = openTab.getWidgetWidth(); - if (widgetWidth > maxWidth) { - maxWidth = widgetWidth; - } - super.setWidth(maxWidth + "px"); - openTab.setWidth(maxWidth); - } - } - - /** - * A StackItem has always two children, Child 0 is a VCaption, Child 1 is - * the actual child widget. - */ - protected class StackItem extends ComplexPanel implements ClickHandler { - - public void setHeight(int height) { - if (height == -1) { - super.setHeight(""); - DOM.setStyleAttribute(content, "height", "0px"); - } else { - super.setHeight((height + getCaptionHeight()) + "px"); - DOM.setStyleAttribute(content, "height", height + "px"); - DOM.setStyleAttribute(content, "top", getCaptionHeight() + "px"); - - } - } - - public Widget getComponent() { - if (getWidgetCount() < 2) { - return null; - } - return getWidget(1); - } - - @Override - public void setVisible(boolean visible) { - super.setVisible(visible); - } - - public void setHeightFromWidget() { - Widget widget = getChildWidget(); - if (widget == null) { - return; - } - - int paintableHeight = widget.getElement().getOffsetHeight(); - setHeight(paintableHeight); - - } - - /** - * Returns caption width including padding - * - * @return - */ - public int getCaptionWidth() { - if (caption == null) { - return 0; - } - - int captionWidth = caption.getRequiredWidth(); - int padding = Util.measureHorizontalPaddingAndBorder( - caption.getElement(), 18); - return captionWidth + padding; - } - - public void setWidth(int width) { - if (width == -1) { - super.setWidth(""); - } else { - super.setWidth(width + "px"); - } - } - - public int getHeight() { - return getOffsetHeight(); - } - - public int getCaptionHeight() { - return captionNode.getOffsetHeight(); - } - - private VCaption caption; - private boolean open = false; - private Element content = DOM.createDiv(); - private Element captionNode = DOM.createDiv(); - - public StackItem(UIDL tabUidl) { - setElement(DOM.createDiv()); - caption = new VCaption(client); - caption.addClickHandler(this); - super.add(caption, captionNode); - DOM.appendChild(captionNode, caption.getElement()); - DOM.appendChild(getElement(), captionNode); - DOM.appendChild(getElement(), content); - - getElement().addClassName(CLASSNAME + "-item"); - captionNode.addClassName(CLASSNAME + "-item-caption"); - content.addClassName(CLASSNAME + "-item-content"); - - touchScrollHandler.addElement(getContainerElement()); - - close(); - } - - @Override - public void onBrowserEvent(Event event) { - onSelectTab(this); - } - - public Element getContainerElement() { - return content; - } - - public Widget getChildWidget() { - if (getWidgetCount() > 1) { - return getWidget(1); - } else { - return null; - } - } - - public void replaceWidget(Widget newWidget) { - if (getWidgetCount() > 1) { - Widget oldWidget = getWidget(1); - ComponentConnector oldPaintable = ConnectorMap.get(client) - .getConnector(oldWidget); - ConnectorMap.get(client).unregisterConnector(oldPaintable); - widgets.remove(oldWidget); - remove(1); - } - add(newWidget, content); - widgets.add(newWidget); - } - - public void open() { - open = true; - DOM.setStyleAttribute(content, "top", getCaptionHeight() + "px"); - DOM.setStyleAttribute(content, "left", "0px"); - DOM.setStyleAttribute(content, "visibility", ""); - addStyleDependentName("open"); - } - - public void hide() { - DOM.setStyleAttribute(content, "visibility", "hidden"); - } - - public void close() { - DOM.setStyleAttribute(content, "visibility", "hidden"); - DOM.setStyleAttribute(content, "top", "-100000px"); - DOM.setStyleAttribute(content, "left", "-100000px"); - removeStyleDependentName("open"); - setHeight(-1); - setWidth(""); - open = false; - } - - public boolean isOpen() { - return open; - } - - public void setContent(UIDL contentUidl) { - final ComponentConnector newPntbl = client - .getPaintable(contentUidl); - Widget newWidget = newPntbl.getWidget(); - if (getChildWidget() == null) { - add(newWidget, content); - widgets.add(newWidget); - } else if (getChildWidget() != newWidget) { - replaceWidget(newWidget); - } - if (contentUidl.getBooleanAttribute("cached")) { - /* - * The size of a cached, relative sized component must be - * updated to report correct size. - */ - client.handleComponentRelativeSize(newPntbl.getWidget()); - } - if (isOpen() && isDynamicHeight()) { - setHeightFromWidget(); - } - } - - @Override - public void onClick(ClickEvent event) { - onSelectTab(this); - } - - public void updateCaption(UIDL uidl) { - // TODO need to call this because the caption does not have an owner - caption.updateCaptionWithoutOwner( - uidl.getStringAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_CAPTION), - uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DISABLED), - uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DESCRIPTION), - uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_ERROR_MESSAGE), - uidl.getStringAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_ICON)); - } - - public int getWidgetWidth() { - return DOM.getFirstChild(content).getOffsetWidth(); - } - - public boolean contains(ComponentConnector p) { - return (getChildWidget() == p.getWidget()); - } - - public boolean isCaptionVisible() { - return caption.isVisible(); - } - - } - - @Override - protected void clearPaintables() { - clear(); - } - - boolean isDynamicWidth() { - ComponentConnector paintable = ConnectorMap.get(client).getConnector( - this); - return paintable.isUndefinedWidth(); - } - - boolean isDynamicHeight() { - ComponentConnector paintable = ConnectorMap.get(client).getConnector( - this); - return paintable.isUndefinedHeight(); - } - - @Override - @SuppressWarnings("unchecked") - protected Iterator<Widget> getWidgetIterator() { - return widgets.iterator(); - } - - @Override - protected int getTabCount() { - return getWidgetCount(); - } - - @Override - protected void removeTab(int index) { - StackItem item = getStackItem(index); - remove(item); - touchScrollHandler.removeElement(item.getContainerElement()); - } - - @Override - protected ComponentConnector getTab(int index) { - if (index < getWidgetCount()) { - Widget w = getStackItem(index); - return ConnectorMap.get(client).getConnector(w); - } - - return null; - } - - StackItem getStackItem(int index) { - return (StackItem) getWidget(index); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/audio/AudioConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/audio/AudioConnector.java deleted file mode 100644 index df08e44f16..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/audio/AudioConnector.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.audio; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.MediaBaseConnector; -import com.vaadin.ui.Audio; - -@Connect(Audio.class) -public class AudioConnector extends MediaBaseConnector { - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - Style style = getWidget().getElement().getStyle(); - - // Make sure that the controls are not clipped if visible. - if (getState().isShowControls() - && (style.getHeight() == null || "".equals(style.getHeight()))) { - if (BrowserInfo.get().isChrome()) { - style.setHeight(32, Unit.PX); - } else { - style.setHeight(25, Unit.PX); - } - } - } - - @Override - protected Widget createWidget() { - return GWT.create(VAudio.class); - } - - @Override - protected String getDefaultAltHtml() { - return "Your browser does not support the <code>audio</code> element."; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/audio/VAudio.java b/client/src/com/vaadin/terminal/gwt/client/ui/audio/VAudio.java deleted file mode 100644 index 121ad3cc94..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/audio/VAudio.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.audio; - -import com.google.gwt.dom.client.AudioElement; -import com.google.gwt.dom.client.Document; -import com.vaadin.terminal.gwt.client.ui.VMediaBase; - -public class VAudio extends VMediaBase { - private static String CLASSNAME = "v-audio"; - - private AudioElement audio; - - public VAudio() { - audio = Document.get().createAudioElement(); - setMediaElement(audio); - setStyleName(CLASSNAME); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java deleted file mode 100644 index 59f90a9840..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.button; - -import java.util.Set; - -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.DOM; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.shared.ui.button.ButtonServerRpc; -import com.vaadin.shared.ui.button.ButtonState; -import com.vaadin.terminal.gwt.client.EventHelper; -import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder; -import com.vaadin.terminal.gwt.client.communication.RpcProxy; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; -import com.vaadin.terminal.gwt.client.ui.Icon; -import com.vaadin.ui.Button; - -@Connect(value = Button.class, loadStyle = LoadStyle.EAGER) -public class ButtonConnector extends AbstractComponentConnector implements - BlurHandler, FocusHandler, ClickHandler { - - private ButtonServerRpc rpc = RpcProxy.create(ButtonServerRpc.class, this); - private FocusAndBlurServerRpc focusBlurProxy = RpcProxy.create( - FocusAndBlurServerRpc.class, this); - - private HandlerRegistration focusHandlerRegistration = null; - private HandlerRegistration blurHandlerRegistration = null; - - @Override - public boolean delegateCaptionHandling() { - return false; - } - - @Override - public void init() { - super.init(); - getWidget().addClickHandler(this); - getWidget().client = getConnection(); - addStateChangeHandler("errorMessage", new StateChangeHandler() { - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - if (null != getState().getErrorMessage()) { - if (getWidget().errorIndicatorElement == null) { - getWidget().errorIndicatorElement = DOM.createSpan(); - getWidget().errorIndicatorElement - .setClassName("v-errorindicator"); - } - getWidget().wrapper.insertBefore( - getWidget().errorIndicatorElement, - getWidget().captionElement); - - } else if (getWidget().errorIndicatorElement != null) { - getWidget().wrapper - .removeChild(getWidget().errorIndicatorElement); - getWidget().errorIndicatorElement = null; - } - } - }); - - addStateChangeHandler("icon", new StateChangeHandler() { - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - if (getState().getIcon() != null) { - if (getWidget().icon == null) { - getWidget().icon = new Icon(getConnection()); - getWidget().wrapper.insertBefore( - getWidget().icon.getElement(), - getWidget().captionElement); - } - getWidget().icon.setUri(getState().getIcon().getURL()); - } else { - if (getWidget().icon != null) { - getWidget().wrapper.removeChild(getWidget().icon - .getElement()); - getWidget().icon = null; - } - } - } - }); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - focusHandlerRegistration = EventHelper.updateFocusHandler(this, - focusHandlerRegistration); - blurHandlerRegistration = EventHelper.updateBlurHandler(this, - blurHandlerRegistration); - - Set<String> changedProperties = stateChangeEvent.getChangedProperties(); - if (changedProperties.contains("caption") - || changedProperties.contains("htmlContentAllowed")) { - // Set text - if (getState().isHtmlContentAllowed()) { - getWidget().setHtml(getState().getCaption()); - } else { - getWidget().setText(getState().getCaption()); - } - } - - getWidget().clickShortcut = getState().getClickShortcutKeyCode(); - } - - @Override - public VButton getWidget() { - return (VButton) super.getWidget(); - } - - @Override - public ButtonState getState() { - return (ButtonState) super.getState(); - } - - @Override - public void onFocus(FocusEvent event) { - // EventHelper.updateFocusHandler ensures that this is called only when - // there is a listener on server side - focusBlurProxy.focus(); - } - - @Override - public void onBlur(BlurEvent event) { - // EventHelper.updateFocusHandler ensures that this is called only when - // there is a listener on server side - focusBlurProxy.blur(); - } - - @Override - public void onClick(ClickEvent event) { - if (getState().isDisableOnClick()) { - getWidget().setEnabled(false); - rpc.disableOnClick(); - } - - // Add mouse details - MouseEventDetails details = MouseEventDetailsBuilder - .buildMouseEventDetails(event.getNativeEvent(), getWidget() - .getElement()); - rpc.click(details); - - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java b/client/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java deleted file mode 100644 index baacac08ed..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.button; - -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.Accessibility; -import com.google.gwt.user.client.ui.FocusWidget; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.Icon; - -public class VButton extends FocusWidget implements ClickHandler { - - public static final String CLASSNAME = "v-button"; - private static final String CLASSNAME_PRESSED = "v-pressed"; - - // mouse movement is checked before synthesizing click event on mouseout - protected static int MOVE_THRESHOLD = 3; - protected int mousedownX = 0; - protected int mousedownY = 0; - - protected ApplicationConnection client; - - protected final Element wrapper = DOM.createSpan(); - - protected Element errorIndicatorElement; - - protected final Element captionElement = DOM.createSpan(); - - protected Icon icon; - - /** - * Helper flag to handle special-case where the button is moved from under - * mouse while clicking it. In this case mouse leaves the button without - * moving. - */ - protected boolean clickPending; - - private boolean enabled = true; - - private int tabIndex = 0; - - /* - * BELOW PRIVATE MEMBERS COPY-PASTED FROM GWT CustomButton - */ - - /** - * If <code>true</code>, this widget is capturing with the mouse held down. - */ - private boolean isCapturing; - - /** - * If <code>true</code>, this widget has focus with the space bar down. This - * means that we will get events when the button is released, but we should - * trigger the button only if the button is still focused at that point. - */ - private boolean isFocusing; - - /** - * Used to decide whether to allow clicks to propagate up to the superclass - * or container elements. - */ - private boolean disallowNextClick = false; - private boolean isHovering; - - protected int clickShortcut = 0; - - private HandlerRegistration focusHandlerRegistration; - private HandlerRegistration blurHandlerRegistration; - - /** - * If caption should be rendered in HTML - */ - protected boolean htmlCaption = false; - - public VButton() { - super(DOM.createDiv()); - setTabIndex(0); - sinkEvents(Event.ONCLICK | Event.MOUSEEVENTS | Event.FOCUSEVENTS - | Event.KEYEVENTS); - - setStyleName(CLASSNAME); - - // Add a11y role "button" - Accessibility.setRole(getElement(), Accessibility.ROLE_BUTTON); - - wrapper.setClassName(getStylePrimaryName() + "-wrap"); - getElement().appendChild(wrapper); - captionElement.setClassName(getStylePrimaryName() + "-caption"); - wrapper.appendChild(captionElement); - - addClickHandler(this); - } - - public void setText(String text) { - captionElement.setInnerText(text); - } - - public void setHtml(String html) { - captionElement.setInnerHTML(html); - } - - @SuppressWarnings("deprecation") - @Override - /* - * Copy-pasted from GWT CustomButton, some minor modifications done: - * - * -for IE/Opera added CLASSNAME_PRESSED - * - * -event.preventDefault() commented from ONMOUSEDOWN (Firefox won't apply - * :active styles if it is present) - * - * -Tooltip event handling added - * - * -onload event handler added (for icon handling) - */ - public void onBrowserEvent(Event event) { - if (DOM.eventGetType(event) == Event.ONLOAD) { - Util.notifyParentOfSizeChange(this, true); - } - // Should not act on button if disabled. - if (!isEnabled()) { - // This can happen when events are bubbled up from non-disabled - // children - return; - } - - int type = DOM.eventGetType(event); - switch (type) { - case Event.ONCLICK: - // If clicks are currently disallowed, keep it from bubbling or - // being passed to the superclass. - if (disallowNextClick) { - event.stopPropagation(); - disallowNextClick = false; - return; - } - break; - case Event.ONMOUSEDOWN: - if (DOM.isOrHasChild(getElement(), DOM.eventGetTarget(event))) { - // This was moved from mouseover, which iOS sometimes skips. - // We're certainly hovering at this point, and we don't actually - // need that information before this point. - setHovering(true); - } - if (event.getButton() == Event.BUTTON_LEFT) { - // save mouse position to detect movement before synthesizing - // event later - mousedownX = event.getClientX(); - mousedownY = event.getClientY(); - - disallowNextClick = true; - clickPending = true; - setFocus(true); - DOM.setCapture(getElement()); - isCapturing = true; - // Prevent dragging (on some browsers); - // DOM.eventPreventDefault(event); - if (BrowserInfo.get().isIE() || BrowserInfo.get().isOpera()) { - addStyleName(CLASSNAME_PRESSED); - } - } - break; - case Event.ONMOUSEUP: - if (isCapturing) { - isCapturing = false; - DOM.releaseCapture(getElement()); - if (isHovering() && event.getButton() == Event.BUTTON_LEFT) { - // Click ok - disallowNextClick = false; - } - if (BrowserInfo.get().isIE() || BrowserInfo.get().isOpera()) { - removeStyleName(CLASSNAME_PRESSED); - } - // Explicitly prevent IE 8 from propagating mouseup events - // upward (fixes #6753) - if (BrowserInfo.get().isIE8()) { - event.stopPropagation(); - } - } - break; - case Event.ONMOUSEMOVE: - clickPending = false; - if (isCapturing) { - // Prevent dragging (on other browsers); - DOM.eventPreventDefault(event); - } - break; - case Event.ONMOUSEOUT: - Element to = event.getRelatedTarget(); - if (getElement().isOrHasChild(DOM.eventGetTarget(event)) - && (to == null || !getElement().isOrHasChild(to))) { - if (clickPending - && Math.abs(mousedownX - event.getClientX()) < MOVE_THRESHOLD - && Math.abs(mousedownY - event.getClientY()) < MOVE_THRESHOLD) { - onClick(); - break; - } - clickPending = false; - if (isCapturing) { - } - setHovering(false); - if (BrowserInfo.get().isIE() || BrowserInfo.get().isOpera()) { - removeStyleName(CLASSNAME_PRESSED); - } - } - break; - case Event.ONBLUR: - if (isFocusing) { - isFocusing = false; - } - break; - case Event.ONLOSECAPTURE: - if (isCapturing) { - isCapturing = false; - } - break; - } - - super.onBrowserEvent(event); - - // Synthesize clicks based on keyboard events AFTER the normal key - // handling. - if ((event.getTypeInt() & Event.KEYEVENTS) != 0) { - switch (type) { - case Event.ONKEYDOWN: - // Stop propagation when the user starts pressing a button that - // we are handling to prevent actions from getting triggered - if (event.getKeyCode() == 32 /* space */) { - isFocusing = true; - event.preventDefault(); - event.stopPropagation(); - } else if (event.getKeyCode() == KeyCodes.KEY_ENTER) { - event.stopPropagation(); - } - break; - case Event.ONKEYUP: - if (isFocusing && event.getKeyCode() == 32 /* space */) { - isFocusing = false; - onClick(); - event.stopPropagation(); - event.preventDefault(); - } - break; - case Event.ONKEYPRESS: - if (event.getKeyCode() == KeyCodes.KEY_ENTER) { - onClick(); - event.stopPropagation(); - event.preventDefault(); - } - break; - } - } - } - - final void setHovering(boolean hovering) { - if (hovering != isHovering()) { - isHovering = hovering; - } - } - - final boolean isHovering() { - return isHovering; - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event - * .dom.client.ClickEvent) - */ - @Override - public void onClick(ClickEvent event) { - if (BrowserInfo.get().isSafari()) { - VButton.this.setFocus(true); - } - - clickPending = false; - } - - /* - * ALL BELOW COPY-PASTED FROM GWT CustomButton - */ - - /** - * Called internally when the user finishes clicking on this button. The - * default behavior is to fire the click event to listeners. Subclasses that - * override {@link #onClickStart()} should override this method to restore - * the normal widget display. - * <p> - * To add custom code for a click event, override - * {@link #onClick(ClickEvent)} instead of this. - */ - protected void onClick() { - // Allow the click we're about to synthesize to pass through to the - // superclass and containing elements. Element.dispatchEvent() is - // synchronous, so we simply set and clear the flag within this method. - - disallowNextClick = false; - - // Mouse coordinates are not always available (e.g., when the click is - // caused by a keyboard event). - NativeEvent evt = Document.get().createClickEvent(1, 0, 0, 0, 0, false, - false, false, false); - getElement().dispatchEvent(evt); - } - - /** - * Sets whether this button is enabled. - * - * @param enabled - * <code>true</code> to enable the button, <code>false</code> to - * disable it - */ - - @Override - public final void setEnabled(boolean enabled) { - if (isEnabled() != enabled) { - this.enabled = enabled; - if (!enabled) { - cleanupCaptureState(); - Accessibility.removeState(getElement(), - Accessibility.STATE_PRESSED); - super.setTabIndex(-1); - } else { - Accessibility.setState(getElement(), - Accessibility.STATE_PRESSED, "false"); - super.setTabIndex(tabIndex); - } - } - } - - @Override - public final boolean isEnabled() { - return enabled; - } - - @Override - public final void setTabIndex(int index) { - super.setTabIndex(index); - tabIndex = index; - } - - /** - * Resets internal state if this button can no longer service events. This - * can occur when the widget becomes detached or disabled. - */ - private void cleanupCaptureState() { - if (isCapturing || isFocusing) { - DOM.releaseCapture(getElement()); - isCapturing = false; - isFocusing = false; - } - } - - private static native int getHorizontalBorderAndPaddingWidth(Element elem) - /*-{ - // THIS METHOD IS ONLY USED FOR INTERNET EXPLORER, IT DOESN'T WORK WITH OTHERS - - var convertToPixel = function(elem, value) { - // From the awesome hack by Dean Edwards - // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 - - // Remember the original values - var left = elem.style.left, rsLeft = elem.runtimeStyle.left; - - // Put in the new values to get a computed value out - elem.runtimeStyle.left = elem.currentStyle.left; - elem.style.left = value || 0; - var ret = elem.style.pixelLeft; - - // Revert the changed values - elem.style.left = left; - elem.runtimeStyle.left = rsLeft; - - return ret; - } - - var ret = 0; - - var sides = ["Right","Left"]; - for(var i=0; i<2; i++) { - var side = sides[i]; - var value; - // Border ------------------------------------------------------- - if(elem.currentStyle["border"+side+"Style"] != "none") { - value = elem.currentStyle["border"+side+"Width"]; - if ( !/^\d+(px)?$/i.test( value ) && /^\d/.test( value ) ) { - ret += convertToPixel(elem, value); - } else if(value.length > 2) { - ret += parseInt(value.substr(0, value.length-2)); - } - } - - // Padding ------------------------------------------------------- - value = elem.currentStyle["padding"+side]; - if ( !/^\d+(px)?$/i.test( value ) && /^\d/.test( value ) ) { - ret += convertToPixel(elem, value); - } else if(value.length > 2) { - ret += parseInt(value.substr(0, value.length-2)); - } - } - - return ret; - }-*/; - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/checkbox/CheckBoxConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/checkbox/CheckBoxConnector.java deleted file mode 100644 index 7968a04b5e..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/checkbox/CheckBoxConnector.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.checkbox; - -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Event; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.checkbox.CheckBoxServerRpc; -import com.vaadin.shared.ui.checkbox.CheckBoxState; -import com.vaadin.terminal.gwt.client.EventHelper; -import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder; -import com.vaadin.terminal.gwt.client.VTooltip; -import com.vaadin.terminal.gwt.client.communication.RpcProxy; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.AbstractFieldConnector; -import com.vaadin.terminal.gwt.client.ui.Icon; -import com.vaadin.ui.CheckBox; - -@Connect(CheckBox.class) -public class CheckBoxConnector extends AbstractFieldConnector implements - FocusHandler, BlurHandler, ClickHandler { - - private HandlerRegistration focusHandlerRegistration; - private HandlerRegistration blurHandlerRegistration; - - private CheckBoxServerRpc rpc = RpcProxy.create(CheckBoxServerRpc.class, - this); - private FocusAndBlurServerRpc focusBlurRpc = RpcProxy.create( - FocusAndBlurServerRpc.class, this); - - @Override - public boolean delegateCaptionHandling() { - return false; - } - - @Override - protected void init() { - super.init(); - getWidget().addClickHandler(this); - getWidget().client = getConnection(); - getWidget().id = getConnectorId(); - - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - focusHandlerRegistration = EventHelper.updateFocusHandler(this, - focusHandlerRegistration); - blurHandlerRegistration = EventHelper.updateBlurHandler(this, - blurHandlerRegistration); - - if (null != getState().getErrorMessage()) { - if (getWidget().errorIndicatorElement == null) { - getWidget().errorIndicatorElement = DOM.createSpan(); - getWidget().errorIndicatorElement.setInnerHTML(" "); - DOM.setElementProperty(getWidget().errorIndicatorElement, - "className", "v-errorindicator"); - DOM.appendChild(getWidget().getElement(), - getWidget().errorIndicatorElement); - DOM.sinkEvents(getWidget().errorIndicatorElement, - VTooltip.TOOLTIP_EVENTS | Event.ONCLICK); - } else { - DOM.setStyleAttribute(getWidget().errorIndicatorElement, - "display", ""); - } - } else if (getWidget().errorIndicatorElement != null) { - DOM.setStyleAttribute(getWidget().errorIndicatorElement, "display", - "none"); - } - - if (isReadOnly()) { - getWidget().setEnabled(false); - } - - if (getState().getIcon() != null) { - if (getWidget().icon == null) { - getWidget().icon = new Icon(getConnection()); - DOM.insertChild(getWidget().getElement(), - getWidget().icon.getElement(), 1); - getWidget().icon.sinkEvents(VTooltip.TOOLTIP_EVENTS); - getWidget().icon.sinkEvents(Event.ONCLICK); - } - getWidget().icon.setUri(getState().getIcon().getURL()); - } else if (getWidget().icon != null) { - // detach icon - DOM.removeChild(getWidget().getElement(), - getWidget().icon.getElement()); - getWidget().icon = null; - } - - // Set text - getWidget().setText(getState().getCaption()); - getWidget().setValue(getState().isChecked()); - getWidget().immediate = getState().isImmediate(); - } - - @Override - public CheckBoxState getState() { - return (CheckBoxState) super.getState(); - } - - @Override - public VCheckBox getWidget() { - return (VCheckBox) super.getWidget(); - } - - @Override - public void onFocus(FocusEvent event) { - // EventHelper.updateFocusHandler ensures that this is called only when - // there is a listener on server side - focusBlurRpc.focus(); - } - - @Override - public void onBlur(BlurEvent event) { - // EventHelper.updateFocusHandler ensures that this is called only when - // there is a listener on server side - focusBlurRpc.blur(); - } - - @Override - public void onClick(ClickEvent event) { - if (!isEnabled()) { - return; - } - - // Add mouse details - MouseEventDetails details = MouseEventDetailsBuilder - .buildMouseEventDetails(event.getNativeEvent(), getWidget() - .getElement()); - rpc.setChecked(getWidget().getValue(), details); - - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/checkbox/VCheckBox.java b/client/src/com/vaadin/terminal/gwt/client/ui/checkbox/VCheckBox.java deleted file mode 100644 index c796b440f3..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/checkbox/VCheckBox.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.checkbox; - -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VTooltip; -import com.vaadin.terminal.gwt.client.ui.Field; -import com.vaadin.terminal.gwt.client.ui.Icon; - -public class VCheckBox extends com.google.gwt.user.client.ui.CheckBox implements - Field { - - public static final String CLASSNAME = "v-checkbox"; - - String id; - - boolean immediate; - - ApplicationConnection client; - - Element errorIndicatorElement; - - Icon icon; - - public VCheckBox() { - setStyleName(CLASSNAME); - - Element el = DOM.getFirstChild(getElement()); - while (el != null) { - DOM.sinkEvents(el, - (DOM.getEventsSunk(el) | VTooltip.TOOLTIP_EVENTS)); - el = DOM.getNextSibling(el); - } - } - - @Override - public void onBrowserEvent(Event event) { - if (icon != null && (event.getTypeInt() == Event.ONCLICK) - && (DOM.eventGetTarget(event) == icon.getElement())) { - // Click on icon should do nothing if widget is disabled - if (isEnabled()) { - setValue(!getValue()); - } - } - super.onBrowserEvent(event); - if (event.getTypeInt() == Event.ONLOAD) { - Util.notifyParentOfSizeChange(this, true); - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/combobox/ComboBoxConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/combobox/ComboBoxConnector.java deleted file mode 100644 index 7be8a1e139..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/combobox/ComboBoxConnector.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.combobox; - -import java.util.Iterator; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.combobox.ComboBoxConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.AbstractFieldConnector; -import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout; -import com.vaadin.terminal.gwt.client.ui.combobox.VFilterSelect.FilterSelectSuggestion; -import com.vaadin.terminal.gwt.client.ui.menubar.MenuItem; -import com.vaadin.ui.Select; - -@Connect(Select.class) -public class ComboBoxConnector extends AbstractFieldConnector implements - Paintable, SimpleManagedLayout { - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal - * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection) - */ - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - // Save details - getWidget().client = client; - getWidget().paintableId = uidl.getId(); - - getWidget().readonly = isReadOnly(); - getWidget().enabled = isEnabled(); - - getWidget().tb.setEnabled(getWidget().enabled); - getWidget().updateReadOnly(); - - if (!isRealUpdate(uidl)) { - return; - } - - // Inverse logic here to make the default case (text input enabled) - // work without additional UIDL messages - boolean noTextInput = uidl - .hasAttribute(ComboBoxConstants.ATTR_NO_TEXT_INPUT) - && uidl.getBooleanAttribute(ComboBoxConstants.ATTR_NO_TEXT_INPUT); - getWidget().setTextInputEnabled(!noTextInput); - - // not a FocusWidget -> needs own tabindex handling - if (uidl.hasAttribute("tabindex")) { - getWidget().tb.setTabIndex(uidl.getIntAttribute("tabindex")); - } - - if (uidl.hasAttribute("filteringmode")) { - getWidget().filteringmode = uidl.getIntAttribute("filteringmode"); - } - - getWidget().immediate = getState().isImmediate(); - - getWidget().nullSelectionAllowed = uidl.hasAttribute("nullselect"); - - getWidget().nullSelectItem = uidl.hasAttribute("nullselectitem") - && uidl.getBooleanAttribute("nullselectitem"); - - getWidget().currentPage = uidl.getIntVariable("page"); - - if (uidl.hasAttribute("pagelength")) { - getWidget().pageLength = uidl.getIntAttribute("pagelength"); - } - - if (uidl.hasAttribute(ComboBoxConstants.ATTR_INPUTPROMPT)) { - // input prompt changed from server - getWidget().inputPrompt = uidl - .getStringAttribute(ComboBoxConstants.ATTR_INPUTPROMPT); - } else { - getWidget().inputPrompt = ""; - } - - getWidget().suggestionPopup.updateStyleNames(uidl, getState()); - - getWidget().allowNewItem = uidl.hasAttribute("allownewitem"); - getWidget().lastNewItemString = null; - - getWidget().currentSuggestions.clear(); - if (!getWidget().waitingForFilteringResponse) { - /* - * Clear the current suggestions as the server response always - * includes the new ones. Exception is when filtering, then we need - * to retain the value if the user does not select any of the - * options matching the filter. - */ - getWidget().currentSuggestion = null; - /* - * Also ensure no old items in menu. Unless cleared the old values - * may cause odd effects on blur events. Suggestions in menu might - * not necessary exist in select at all anymore. - */ - getWidget().suggestionPopup.menu.clearItems(); - - } - - final UIDL options = uidl.getChildUIDL(0); - if (uidl.hasAttribute("totalMatches")) { - getWidget().totalMatches = uidl.getIntAttribute("totalMatches"); - } else { - getWidget().totalMatches = 0; - } - - // used only to calculate minimum popup width - String captions = Util.escapeHTML(getWidget().inputPrompt); - - for (final Iterator<?> i = options.getChildIterator(); i.hasNext();) { - final UIDL optionUidl = (UIDL) i.next(); - final FilterSelectSuggestion suggestion = getWidget().new FilterSelectSuggestion( - optionUidl); - getWidget().currentSuggestions.add(suggestion); - if (optionUidl.hasAttribute("selected")) { - if (!getWidget().waitingForFilteringResponse - || getWidget().popupOpenerClicked) { - String newSelectedOptionKey = Integer.toString(suggestion - .getOptionKey()); - if (!newSelectedOptionKey - .equals(getWidget().selectedOptionKey) - || suggestion.getReplacementString().equals( - getWidget().tb.getText())) { - // Update text field if we've got a new selection - // Also update if we've got the same text to retain old - // text selection behavior - getWidget().setPromptingOff( - suggestion.getReplacementString()); - getWidget().selectedOptionKey = newSelectedOptionKey; - } - } - getWidget().currentSuggestion = suggestion; - getWidget().setSelectedItemIcon(suggestion.getIconUri()); - } - - // Collect captions so we can calculate minimum width for textarea - if (captions.length() > 0) { - captions += "|"; - } - captions += Util.escapeHTML(suggestion.getReplacementString()); - } - - if ((!getWidget().waitingForFilteringResponse || getWidget().popupOpenerClicked) - && uidl.hasVariable("selected") - && uidl.getStringArrayVariable("selected").length == 0) { - // select nulled - if (!getWidget().waitingForFilteringResponse - || !getWidget().popupOpenerClicked) { - if (!getWidget().focused) { - /* - * client.updateComponent overwrites all styles so we must - * ALWAYS set the prompting style at this point, even though - * we think it has been set already... - */ - getWidget().prompting = false; - getWidget().setPromptingOn(); - } else { - // we have focus in field, prompting can't be set on, - // instead just clear the input - getWidget().tb.setValue(""); - } - } - getWidget().setSelectedItemIcon(null); - getWidget().selectedOptionKey = null; - } - - if (getWidget().waitingForFilteringResponse - && getWidget().lastFilter.toLowerCase().equals( - uidl.getStringVariable("filter"))) { - getWidget().suggestionPopup.showSuggestions( - getWidget().currentSuggestions, getWidget().currentPage, - getWidget().totalMatches); - getWidget().waitingForFilteringResponse = false; - if (!getWidget().popupOpenerClicked - && getWidget().selectPopupItemWhenResponseIsReceived != VFilterSelect.Select.NONE) { - // we're paging w/ arrows - if (getWidget().selectPopupItemWhenResponseIsReceived == VFilterSelect.Select.LAST) { - getWidget().suggestionPopup.menu.selectLastItem(); - } else { - getWidget().suggestionPopup.menu.selectFirstItem(); - } - - // This is used for paging so we update the keyboard selection - // variable as well. - MenuItem activeMenuItem = getWidget().suggestionPopup.menu - .getSelectedItem(); - getWidget().suggestionPopup.menu - .setKeyboardSelectedItem(activeMenuItem); - - // Update text field to contain the correct text - getWidget().setTextboxText(activeMenuItem.getText()); - getWidget().tb.setSelectionRange( - getWidget().lastFilter.length(), - activeMenuItem.getText().length() - - getWidget().lastFilter.length()); - - getWidget().selectPopupItemWhenResponseIsReceived = VFilterSelect.Select.NONE; // reset - } - if (getWidget().updateSelectionWhenReponseIsReceived) { - getWidget().suggestionPopup.menu - .doPostFilterSelectedItemAction(); - } - } - - // Calculate minumum textarea width - getWidget().suggestionPopupMinWidth = getWidget().minWidth(captions); - - getWidget().popupOpenerClicked = false; - - if (!getWidget().initDone) { - getWidget().updateRootWidth(); - } - - // Focus dependent style names are lost during the update, so we add - // them here back again - if (getWidget().focused) { - getWidget().addStyleDependentName("focus"); - } - - getWidget().initDone = true; - } - - @Override - public VFilterSelect getWidget() { - return (VFilterSelect) super.getWidget(); - } - - @Override - public void layout() { - VFilterSelect widget = getWidget(); - if (widget.initDone) { - widget.updateRootWidth(); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java b/client/src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java deleted file mode 100644 index 5f5826526c..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java +++ /dev/null @@ -1,1717 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.combobox; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyUpEvent; -import com.google.gwt.event.dom.client.KeyUpHandler; -import com.google.gwt.event.dom.client.LoadEvent; -import com.google.gwt.event.dom.client.LoadHandler; -import com.google.gwt.event.logical.shared.CloseEvent; -import com.google.gwt.event.logical.shared.CloseHandler; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.Image; -import com.google.gwt.user.client.ui.PopupPanel; -import com.google.gwt.user.client.ui.PopupPanel.PositionCallback; -import com.google.gwt.user.client.ui.SuggestOracle.Suggestion; -import com.google.gwt.user.client.ui.TextBox; -import com.vaadin.shared.ComponentState; -import com.vaadin.shared.EventId; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.Focusable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.ui.Field; -import com.vaadin.terminal.gwt.client.ui.SubPartAware; -import com.vaadin.terminal.gwt.client.ui.VLazyExecutor; -import com.vaadin.terminal.gwt.client.ui.VOverlay; -import com.vaadin.terminal.gwt.client.ui.menubar.MenuBar; -import com.vaadin.terminal.gwt.client.ui.menubar.MenuItem; - -/** - * Client side implementation of the Select component. - * - * TODO needs major refactoring (to be extensible etc) - */ -@SuppressWarnings("deprecation") -public class VFilterSelect extends Composite implements Field, KeyDownHandler, - KeyUpHandler, ClickHandler, FocusHandler, BlurHandler, Focusable, - SubPartAware { - - /** - * Represents a suggestion in the suggestion popup box - */ - public class FilterSelectSuggestion implements Suggestion, Command { - - private final String key; - private final String caption; - private String iconUri; - - /** - * Constructor - * - * @param uidl - * The UIDL recieved from the server - */ - public FilterSelectSuggestion(UIDL uidl) { - key = uidl.getStringAttribute("key"); - caption = uidl.getStringAttribute("caption"); - if (uidl.hasAttribute("icon")) { - iconUri = client.translateVaadinUri(uidl - .getStringAttribute("icon")); - } - } - - /** - * Gets the visible row in the popup as a HTML string. The string - * contains an image tag with the rows icon (if an icon has been - * specified) and the caption of the item - */ - - @Override - public String getDisplayString() { - final StringBuffer sb = new StringBuffer(); - if (iconUri != null) { - sb.append("<img src=\""); - sb.append(Util.escapeAttribute(iconUri)); - sb.append("\" alt=\"\" class=\"v-icon\" />"); - } - String content; - if ("".equals(caption)) { - // Ensure that empty options use the same height as other - // options and are not collapsed (#7506) - content = " "; - } else { - content = Util.escapeHTML(caption); - } - sb.append("<span>" + content + "</span>"); - return sb.toString(); - } - - /** - * Get a string that represents this item. This is used in the text box. - */ - - @Override - public String getReplacementString() { - return caption; - } - - /** - * Get the option key which represents the item on the server side. - * - * @return The key of the item - */ - public int getOptionKey() { - return Integer.parseInt(key); - } - - /** - * Get the URI of the icon. Used when constructing the displayed option. - * - * @return - */ - public String getIconUri() { - return iconUri; - } - - /** - * Executes a selection of this item. - */ - - @Override - public void execute() { - onSuggestionSelected(this); - } - } - - /** - * Represents the popup box with the selection options. Wraps a suggestion - * menu. - */ - public class SuggestionPopup extends VOverlay implements PositionCallback, - CloseHandler<PopupPanel> { - - private static final String Z_INDEX = "30000"; - - protected final SuggestionMenu menu; - - private final Element up = DOM.createDiv(); - private final Element down = DOM.createDiv(); - private final Element status = DOM.createDiv(); - - private boolean isPagingEnabled = true; - - private long lastAutoClosed; - - private int popupOuterPadding = -1; - - private int topPosition; - - /** - * Default constructor - */ - SuggestionPopup() { - super(true, false, true); - menu = new SuggestionMenu(); - setWidget(menu); - setStyleName(CLASSNAME + "-suggestpopup"); - DOM.setStyleAttribute(getElement(), "zIndex", Z_INDEX); - - final Element root = getContainerElement(); - - DOM.setInnerHTML(up, "<span>Prev</span>"); - DOM.sinkEvents(up, Event.ONCLICK); - DOM.setInnerHTML(down, "<span>Next</span>"); - DOM.sinkEvents(down, Event.ONCLICK); - DOM.insertChild(root, up, 0); - DOM.appendChild(root, down); - DOM.appendChild(root, status); - DOM.setElementProperty(status, "className", CLASSNAME + "-status"); - DOM.sinkEvents(root, Event.ONMOUSEDOWN | Event.ONMOUSEWHEEL); - addCloseHandler(this); - } - - /** - * Shows the popup where the user can see the filtered options - * - * @param currentSuggestions - * The filtered suggestions - * @param currentPage - * The current page number - * @param totalSuggestions - * The total amount of suggestions - */ - public void showSuggestions( - Collection<FilterSelectSuggestion> currentSuggestions, - int currentPage, int totalSuggestions) { - - // Add TT anchor point - DOM.setElementProperty(getElement(), "id", - "VAADIN_COMBOBOX_OPTIONLIST"); - - menu.setSuggestions(currentSuggestions); - final int x = VFilterSelect.this.getAbsoluteLeft(); - topPosition = tb.getAbsoluteTop(); - topPosition += tb.getOffsetHeight(); - setPopupPosition(x, topPosition); - - int nullOffset = (nullSelectionAllowed && "".equals(lastFilter) ? 1 - : 0); - boolean firstPage = (currentPage == 0); - final int first = currentPage * pageLength + 1 - - (firstPage ? 0 : nullOffset); - final int last = first + currentSuggestions.size() - 1 - - (firstPage && "".equals(lastFilter) ? nullOffset : 0); - final int matches = totalSuggestions - nullOffset; - if (last > 0) { - // nullsel not counted, as requested by user - DOM.setInnerText(status, (matches == 0 ? 0 : first) + "-" - + last + "/" + matches); - } else { - DOM.setInnerText(status, ""); - } - // We don't need to show arrows or statusbar if there is only one - // page - if (totalSuggestions <= pageLength || pageLength == 0) { - setPagingEnabled(false); - } else { - setPagingEnabled(true); - } - setPrevButtonActive(first > 1); - setNextButtonActive(last < matches); - - // clear previously fixed width - menu.setWidth(""); - DOM.setStyleAttribute(DOM.getFirstChild(menu.getElement()), - "width", ""); - - setPopupPositionAndShow(this); - - } - - /** - * Should the next page button be visible to the user? - * - * @param active - */ - private void setNextButtonActive(boolean active) { - if (active) { - DOM.sinkEvents(down, Event.ONCLICK); - DOM.setElementProperty(down, "className", CLASSNAME - + "-nextpage"); - } else { - DOM.sinkEvents(down, 0); - DOM.setElementProperty(down, "className", CLASSNAME - + "-nextpage-off"); - } - } - - /** - * Should the previous page button be visible to the user - * - * @param active - */ - private void setPrevButtonActive(boolean active) { - if (active) { - DOM.sinkEvents(up, Event.ONCLICK); - DOM.setElementProperty(up, "className", CLASSNAME + "-prevpage"); - } else { - DOM.sinkEvents(up, 0); - DOM.setElementProperty(up, "className", CLASSNAME - + "-prevpage-off"); - } - - } - - /** - * Selects the next item in the filtered selections - */ - public void selectNextItem() { - final MenuItem cur = menu.getSelectedItem(); - final int index = 1 + menu.getItems().indexOf(cur); - if (menu.getItems().size() > index) { - final MenuItem newSelectedItem = menu.getItems().get(index); - menu.selectItem(newSelectedItem); - tb.setText(newSelectedItem.getText()); - tb.setSelectionRange(lastFilter.length(), newSelectedItem - .getText().length() - lastFilter.length()); - - } else if (hasNextPage()) { - selectPopupItemWhenResponseIsReceived = Select.FIRST; - filterOptions(currentPage + 1, lastFilter); - } - } - - /** - * Selects the previous item in the filtered selections - */ - public void selectPrevItem() { - final MenuItem cur = menu.getSelectedItem(); - final int index = -1 + menu.getItems().indexOf(cur); - if (index > -1) { - final MenuItem newSelectedItem = menu.getItems().get(index); - menu.selectItem(newSelectedItem); - tb.setText(newSelectedItem.getText()); - tb.setSelectionRange(lastFilter.length(), newSelectedItem - .getText().length() - lastFilter.length()); - } else if (index == -1) { - if (currentPage > 0) { - selectPopupItemWhenResponseIsReceived = Select.LAST; - filterOptions(currentPage - 1, lastFilter); - } - } else { - final MenuItem newSelectedItem = menu.getItems().get( - menu.getItems().size() - 1); - menu.selectItem(newSelectedItem); - tb.setText(newSelectedItem.getText()); - tb.setSelectionRange(lastFilter.length(), newSelectedItem - .getText().length() - lastFilter.length()); - } - } - - /* - * Using a timer to scroll up or down the pages so when we receive lots - * of consecutive mouse wheel events the pages does not flicker. - */ - private LazyPageScroller lazyPageScroller = new LazyPageScroller(); - - private class LazyPageScroller extends Timer { - private int pagesToScroll = 0; - - @Override - public void run() { - if (pagesToScroll != 0) { - if (!waitingForFilteringResponse) { - /* - * Avoid scrolling while we are waiting for a response - * because otherwise the waiting flag will be reset in - * the first response and the second response will be - * ignored, causing an empty popup... - * - * As long as the scrolling delay is suitable - * double/triple clicks will work by scrolling two or - * three pages at a time and this should not be a - * problem. - */ - filterOptions(currentPage + pagesToScroll, lastFilter); - } - pagesToScroll = 0; - } - } - - public void scrollUp() { - if (currentPage + pagesToScroll > 0) { - pagesToScroll--; - cancel(); - schedule(200); - } - } - - public void scrollDown() { - if (totalMatches > (currentPage + pagesToScroll + 1) - * pageLength) { - pagesToScroll++; - cancel(); - schedule(200); - } - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt - * .user.client.Event) - */ - - @Override - public void onBrowserEvent(Event event) { - if (event.getTypeInt() == Event.ONCLICK) { - final Element target = DOM.eventGetTarget(event); - if (target == up || target == DOM.getChild(up, 0)) { - lazyPageScroller.scrollUp(); - } else if (target == down || target == DOM.getChild(down, 0)) { - lazyPageScroller.scrollDown(); - } - } else if (event.getTypeInt() == Event.ONMOUSEWHEEL) { - int velocity = event.getMouseWheelVelocityY(); - if (velocity > 0) { - lazyPageScroller.scrollDown(); - } else { - lazyPageScroller.scrollUp(); - } - } - - /* - * Prevent the keyboard focus from leaving the textfield by - * preventing the default behaviour of the browser. Fixes #4285. - */ - handleMouseDownEvent(event); - } - - /** - * Should paging be enabled. If paging is enabled then only a certain - * amount of items are visible at a time and a scrollbar or buttons are - * visible to change page. If paging is turned of then all options are - * rendered into the popup menu. - * - * @param paging - * Should the paging be turned on? - */ - public void setPagingEnabled(boolean paging) { - if (isPagingEnabled == paging) { - return; - } - if (paging) { - DOM.setStyleAttribute(down, "display", ""); - DOM.setStyleAttribute(up, "display", ""); - DOM.setStyleAttribute(status, "display", ""); - } else { - DOM.setStyleAttribute(down, "display", "none"); - DOM.setStyleAttribute(up, "display", "none"); - DOM.setStyleAttribute(status, "display", "none"); - } - isPagingEnabled = paging; - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.user.client.ui.PopupPanel$PositionCallback#setPosition - * (int, int) - */ - - @Override - public void setPosition(int offsetWidth, int offsetHeight) { - - int top = -1; - int left = -1; - - // reset menu size and retrieve its "natural" size - menu.setHeight(""); - if (currentPage > 0) { - // fix height to avoid height change when getting to last page - menu.fixHeightTo(pageLength); - } - offsetHeight = getOffsetHeight(); - - final int desiredWidth = getMainWidth(); - int naturalMenuWidth = DOM.getElementPropertyInt( - DOM.getFirstChild(menu.getElement()), "offsetWidth"); - - if (popupOuterPadding == -1) { - popupOuterPadding = Util.measureHorizontalPaddingAndBorder( - getElement(), 2); - } - - if (naturalMenuWidth < desiredWidth) { - menu.setWidth((desiredWidth - popupOuterPadding) + "px"); - DOM.setStyleAttribute(DOM.getFirstChild(menu.getElement()), - "width", "100%"); - naturalMenuWidth = desiredWidth; - } - - if (BrowserInfo.get().isIE()) { - /* - * IE requires us to specify the width for the container - * element. Otherwise it will be 100% wide - */ - int rootWidth = naturalMenuWidth - popupOuterPadding; - DOM.setStyleAttribute(getContainerElement(), "width", rootWidth - + "px"); - } - - if (offsetHeight + getPopupTop() > Window.getClientHeight() - + Window.getScrollTop()) { - // popup on top of input instead - top = getPopupTop() - offsetHeight - - VFilterSelect.this.getOffsetHeight(); - if (top < 0) { - top = 0; - } - } else { - top = getPopupTop(); - /* - * Take popup top margin into account. getPopupTop() returns the - * top value including the margin but the value we give must not - * include the margin. - */ - int topMargin = (top - topPosition); - top -= topMargin; - } - - // fetch real width (mac FF bugs here due GWT popups overflow:auto ) - offsetWidth = DOM.getElementPropertyInt( - DOM.getFirstChild(menu.getElement()), "offsetWidth"); - if (offsetWidth + getPopupLeft() > Window.getClientWidth() - + Window.getScrollLeft()) { - left = VFilterSelect.this.getAbsoluteLeft() - + VFilterSelect.this.getOffsetWidth() - + Window.getScrollLeft() - offsetWidth; - if (left < 0) { - left = 0; - } - } else { - left = getPopupLeft(); - } - setPopupPosition(left, top); - } - - /** - * Was the popup just closed? - * - * @return true if popup was just closed - */ - public boolean isJustClosed() { - final long now = (new Date()).getTime(); - return (lastAutoClosed > 0 && (now - lastAutoClosed) < 200); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google - * .gwt.event.logical.shared.CloseEvent) - */ - - @Override - public void onClose(CloseEvent<PopupPanel> event) { - if (event.isAutoClosed()) { - lastAutoClosed = (new Date()).getTime(); - } - } - - /** - * Updates style names in suggestion popup to help theme building. - * - * @param uidl - * UIDL for the whole combo box - * @param componentState - * shared state of the combo box - */ - public void updateStyleNames(UIDL uidl, ComponentState componentState) { - setStyleName(CLASSNAME + "-suggestpopup"); - if (componentState.hasStyles()) { - for (String style : componentState.getStyles()) { - if (!"".equals(style)) { - addStyleDependentName(style); - } - } - } - } - - } - - /** - * The menu where the suggestions are rendered - */ - public class SuggestionMenu extends MenuBar implements SubPartAware, - LoadHandler { - - /** - * Tracks the item that is currently selected using the keyboard. This - * is need only because mouseover changes the selection and we do not - * want to use that selection when pressing enter to select the item. - */ - private MenuItem keyboardSelectedItem; - - private VLazyExecutor delayedImageLoadExecutioner = new VLazyExecutor( - 100, new ScheduledCommand() { - - @Override - public void execute() { - if (suggestionPopup.isVisible() - && suggestionPopup.isAttached()) { - setWidth(""); - DOM.setStyleAttribute( - DOM.getFirstChild(getElement()), "width", - ""); - suggestionPopup - .setPopupPositionAndShow(suggestionPopup); - } - - } - }); - - /** - * Default constructor - */ - SuggestionMenu() { - super(true); - setStyleName(CLASSNAME + "-suggestmenu"); - addDomHandler(this, LoadEvent.getType()); - } - - /** - * Fixes menus height to use same space as full page would use. Needed - * to avoid height changes when quickly "scrolling" to last page - */ - public void fixHeightTo(int pagelenth) { - if (currentSuggestions.size() > 0) { - final int pixels = pagelenth * (getOffsetHeight() - 2) - / currentSuggestions.size(); - setHeight((pixels + 2) + "px"); - } - } - - /** - * Sets the suggestions rendered in the menu - * - * @param suggestions - * The suggestions to be rendered in the menu - */ - public void setSuggestions( - Collection<FilterSelectSuggestion> suggestions) { - // Reset keyboard selection when contents is updated to avoid - // reusing old, invalid data - setKeyboardSelectedItem(null); - - clearItems(); - final Iterator<FilterSelectSuggestion> it = suggestions.iterator(); - while (it.hasNext()) { - final FilterSelectSuggestion s = it.next(); - final MenuItem mi = new MenuItem(s.getDisplayString(), true, s); - - Util.sinkOnloadForImages(mi.getElement()); - - this.addItem(mi); - if (s == currentSuggestion) { - selectItem(mi); - } - } - } - - /** - * Send the current selection to the server. Triggered when a selection - * is made or on a blur event. - */ - public void doSelectedItemAction() { - // do not send a value change event if null was and stays selected - final String enteredItemValue = tb.getText(); - if (nullSelectionAllowed && "".equals(enteredItemValue) - && selectedOptionKey != null - && !"".equals(selectedOptionKey)) { - if (nullSelectItem) { - reset(); - return; - } - // null is not visible on pages != 0, and not visible when - // filtering: handle separately - client.updateVariable(paintableId, "filter", "", false); - client.updateVariable(paintableId, "page", 0, false); - client.updateVariable(paintableId, "selected", new String[] {}, - immediate); - suggestionPopup.hide(); - return; - } - - updateSelectionWhenReponseIsReceived = waitingForFilteringResponse; - if (!waitingForFilteringResponse) { - doPostFilterSelectedItemAction(); - } - } - - /** - * Triggered after a selection has been made - */ - public void doPostFilterSelectedItemAction() { - final MenuItem item = getSelectedItem(); - final String enteredItemValue = tb.getText(); - - updateSelectionWhenReponseIsReceived = false; - - // check for exact match in menu - int p = getItems().size(); - if (p > 0) { - for (int i = 0; i < p; i++) { - final MenuItem potentialExactMatch = getItems().get(i); - if (potentialExactMatch.getText().equals(enteredItemValue)) { - selectItem(potentialExactMatch); - // do not send a value change event if null was and - // stays selected - if (!"".equals(enteredItemValue) - || (selectedOptionKey != null && !"" - .equals(selectedOptionKey))) { - doItemAction(potentialExactMatch, true); - } - suggestionPopup.hide(); - return; - } - } - } - if (allowNewItem) { - - if (!prompting && !enteredItemValue.equals(lastNewItemString)) { - /* - * Store last sent new item string to avoid double sends - */ - lastNewItemString = enteredItemValue; - client.updateVariable(paintableId, "newitem", - enteredItemValue, immediate); - } - } else if (item != null - && !"".equals(lastFilter) - && (filteringmode == FILTERINGMODE_CONTAINS ? item - .getText().toLowerCase() - .contains(lastFilter.toLowerCase()) : item - .getText().toLowerCase() - .startsWith(lastFilter.toLowerCase()))) { - doItemAction(item, true); - } else { - // currentSuggestion has key="" for nullselection - if (currentSuggestion != null - && !currentSuggestion.key.equals("")) { - // An item (not null) selected - String text = currentSuggestion.getReplacementString(); - tb.setText(text); - selectedOptionKey = currentSuggestion.key; - } else { - // Null selected - tb.setText(""); - selectedOptionKey = null; - } - } - suggestionPopup.hide(); - } - - private static final String SUBPART_PREFIX = "item"; - - @Override - public Element getSubPartElement(String subPart) { - int index = Integer.parseInt(subPart.substring(SUBPART_PREFIX - .length())); - - MenuItem item = getItems().get(index); - - return item.getElement(); - } - - @Override - public String getSubPartName(Element subElement) { - if (!getElement().isOrHasChild(subElement)) { - return null; - } - - Element menuItemRoot = subElement; - while (menuItemRoot != null - && !menuItemRoot.getTagName().equalsIgnoreCase("td")) { - menuItemRoot = menuItemRoot.getParentElement().cast(); - } - // "menuItemRoot" is now the root of the menu item - - final int itemCount = getItems().size(); - for (int i = 0; i < itemCount; i++) { - if (getItems().get(i).getElement() == menuItemRoot) { - String name = SUBPART_PREFIX + i; - return name; - } - } - return null; - } - - @Override - public void onLoad(LoadEvent event) { - // Handle icon onload events to ensure shadow is resized - // correctly - delayedImageLoadExecutioner.trigger(); - - } - - public void selectFirstItem() { - MenuItem firstItem = getItems().get(0); - selectItem(firstItem); - } - - private MenuItem getKeyboardSelectedItem() { - return keyboardSelectedItem; - } - - protected void setKeyboardSelectedItem(MenuItem firstItem) { - keyboardSelectedItem = firstItem; - } - - public void selectLastItem() { - List<MenuItem> items = getItems(); - MenuItem lastItem = items.get(items.size() - 1); - selectItem(lastItem); - } - } - - public static final int FILTERINGMODE_OFF = 0; - public static final int FILTERINGMODE_STARTSWITH = 1; - public static final int FILTERINGMODE_CONTAINS = 2; - - private static final String CLASSNAME = "v-filterselect"; - private static final String STYLE_NO_INPUT = "no-input"; - - protected int pageLength = 10; - - private boolean enableDebug = false; - - private final FlowPanel panel = new FlowPanel(); - - /** - * The text box where the filter is written - */ - protected final TextBox tb = new TextBox() { - - // Overridden to avoid selecting text when text input is disabled - @Override - public void setSelectionRange(int pos, int length) { - if (textInputEnabled) { - super.setSelectionRange(pos, length); - } else { - super.setSelectionRange(getValue().length(), 0); - } - }; - }; - - protected final SuggestionPopup suggestionPopup = new SuggestionPopup(); - - /** - * Used when measuring the width of the popup - */ - private final HTML popupOpener = new HTML("") { - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt - * .user.client.Event) - */ - - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - - /* - * Prevent the keyboard focus from leaving the textfield by - * preventing the default behaviour of the browser. Fixes #4285. - */ - handleMouseDownEvent(event); - } - }; - - private final Image selectedItemIcon = new Image(); - - protected ApplicationConnection client; - - protected String paintableId; - - protected int currentPage; - - /** - * A collection of available suggestions (options) as received from the - * server. - */ - protected final List<FilterSelectSuggestion> currentSuggestions = new ArrayList<FilterSelectSuggestion>(); - - protected boolean immediate; - - protected String selectedOptionKey; - - protected boolean waitingForFilteringResponse = false; - protected boolean updateSelectionWhenReponseIsReceived = false; - private boolean tabPressedWhenPopupOpen = false; - protected boolean initDone = false; - - protected String lastFilter = ""; - - protected enum Select { - NONE, FIRST, LAST - }; - - protected Select selectPopupItemWhenResponseIsReceived = Select.NONE; - - /** - * The current suggestion selected from the dropdown. This is one of the - * values in currentSuggestions except when filtering, in this case - * currentSuggestion might not be in currentSuggestions. - */ - protected FilterSelectSuggestion currentSuggestion; - - protected int totalMatches; - protected boolean allowNewItem; - protected boolean nullSelectionAllowed; - protected boolean nullSelectItem; - protected boolean enabled; - protected boolean readonly; - - protected int filteringmode = FILTERINGMODE_OFF; - - // shown in unfocused empty field, disappears on focus (e.g "Search here") - private static final String CLASSNAME_PROMPT = "prompt"; - protected String inputPrompt = ""; - protected boolean prompting = false; - - // Set true when popupopened has been clicked. Cleared on each UIDL-update. - // This handles the special case where are not filtering yet and the - // selected value has changed on the server-side. See #2119 - protected boolean popupOpenerClicked; - protected int suggestionPopupMinWidth = 0; - private int popupWidth = -1; - /* - * Stores the last new item string to avoid double submissions. Cleared on - * uidl updates - */ - protected String lastNewItemString; - protected boolean focused = false; - - /** - * If set to false, the component should not allow entering text to the - * field even for filtering. - */ - private boolean textInputEnabled = true; - - /** - * Default constructor - */ - public VFilterSelect() { - selectedItemIcon.setStyleName("v-icon"); - selectedItemIcon.addLoadHandler(new LoadHandler() { - - @Override - public void onLoad(LoadEvent event) { - if (BrowserInfo.get().isIE8()) { - // IE8 needs some help to discover it should reposition the - // text field - forceReflow(); - } - updateRootWidth(); - updateSelectedIconPosition(); - } - }); - - popupOpener.sinkEvents(Event.ONMOUSEDOWN); - panel.add(tb); - panel.add(popupOpener); - initWidget(panel); - setStyleName(CLASSNAME); - tb.addKeyDownHandler(this); - tb.addKeyUpHandler(this); - tb.setStyleName(CLASSNAME + "-input"); - tb.addFocusHandler(this); - tb.addBlurHandler(this); - tb.addClickHandler(this); - popupOpener.setStyleName(CLASSNAME + "-button"); - popupOpener.addClickHandler(this); - } - - /** - * Does the Select have more pages? - * - * @return true if a next page exists, else false if the current page is the - * last page - */ - public boolean hasNextPage() { - if (totalMatches > (currentPage + 1) * pageLength) { - return true; - } else { - return false; - } - } - - /** - * Filters the options at a certain page. Uses the text box input as a - * filter - * - * @param page - * The page which items are to be filtered - */ - public void filterOptions(int page) { - filterOptions(page, tb.getText()); - } - - /** - * Filters the options at certain page using the given filter - * - * @param page - * The page to filter - * @param filter - * The filter to apply to the components - */ - public void filterOptions(int page, String filter) { - filterOptions(page, filter, true); - } - - /** - * Filters the options at certain page using the given filter - * - * @param page - * The page to filter - * @param filter - * The filter to apply to the options - * @param immediate - * Whether to send the options request immediately - */ - private void filterOptions(int page, String filter, boolean immediate) { - if (filter.equals(lastFilter) && currentPage == page) { - if (!suggestionPopup.isAttached()) { - suggestionPopup.showSuggestions(currentSuggestions, - currentPage, totalMatches); - } - return; - } - if (!filter.equals(lastFilter)) { - // we are on subsequent page and text has changed -> reset page - if ("".equals(filter)) { - // let server decide - page = -1; - } else { - page = 0; - } - } - - waitingForFilteringResponse = true; - client.updateVariable(paintableId, "filter", filter, false); - client.updateVariable(paintableId, "page", page, immediate); - lastFilter = filter; - currentPage = page; - } - - protected void updateReadOnly() { - tb.setReadOnly(readonly || !textInputEnabled); - } - - protected void setTextInputEnabled(boolean textInputEnabled) { - // Always update styles as they might have been overwritten - if (textInputEnabled) { - removeStyleDependentName(STYLE_NO_INPUT); - } else { - addStyleDependentName(STYLE_NO_INPUT); - } - - if (this.textInputEnabled == textInputEnabled) { - return; - } - - this.textInputEnabled = textInputEnabled; - updateReadOnly(); - } - - /** - * Sets the text in the text box. - * - * @param text - * the text to set in the text box - */ - protected void setTextboxText(final String text) { - tb.setText(text); - } - - /** - * Turns prompting on. When prompting is turned on a command prompt is shown - * in the text box if nothing has been entered. - */ - protected void setPromptingOn() { - if (!prompting) { - prompting = true; - addStyleDependentName(CLASSNAME_PROMPT); - } - setTextboxText(inputPrompt); - } - - /** - * Turns prompting off. When prompting is turned on a command prompt is - * shown in the text box if nothing has been entered. - * - * @param text - * The text the text box should contain. - */ - protected void setPromptingOff(String text) { - setTextboxText(text); - if (prompting) { - prompting = false; - removeStyleDependentName(CLASSNAME_PROMPT); - } - } - - /** - * Triggered when a suggestion is selected - * - * @param suggestion - * The suggestion that just got selected. - */ - public void onSuggestionSelected(FilterSelectSuggestion suggestion) { - updateSelectionWhenReponseIsReceived = false; - - currentSuggestion = suggestion; - String newKey; - if (suggestion.key.equals("")) { - // "nullselection" - newKey = ""; - } else { - // normal selection - newKey = String.valueOf(suggestion.getOptionKey()); - } - - String text = suggestion.getReplacementString(); - if ("".equals(newKey) && !focused) { - setPromptingOn(); - } else { - setPromptingOff(text); - } - setSelectedItemIcon(suggestion.getIconUri()); - if (!(newKey.equals(selectedOptionKey) || ("".equals(newKey) && selectedOptionKey == null))) { - selectedOptionKey = newKey; - client.updateVariable(paintableId, "selected", - new String[] { selectedOptionKey }, immediate); - // currentPage = -1; // forget the page - } - suggestionPopup.hide(); - } - - /** - * Sets the icon URI of the selected item. The icon is shown on the left - * side of the item caption text. Set the URI to null to remove the icon. - * - * @param iconUri - * The URI of the icon - */ - protected void setSelectedItemIcon(String iconUri) { - if (iconUri == null || iconUri.length() == 0) { - if (selectedItemIcon.isAttached()) { - panel.remove(selectedItemIcon); - if (BrowserInfo.get().isIE8()) { - // IE8 needs some help to discover it should reposition the - // text field - forceReflow(); - } - updateRootWidth(); - } - } else { - panel.insert(selectedItemIcon, 0); - selectedItemIcon.setUrl(iconUri); - updateRootWidth(); - updateSelectedIconPosition(); - } - } - - private void forceReflow() { - Util.setStyleTemporarily(tb.getElement(), "zoom", "1"); - } - - /** - * Positions the icon vertically in the middle. Should be called after the - * icon has loaded - */ - private void updateSelectedIconPosition() { - // Position icon vertically to middle - int availableHeight = 0; - availableHeight = getOffsetHeight(); - - int iconHeight = Util.getRequiredHeight(selectedItemIcon); - int marginTop = (availableHeight - iconHeight) / 2; - DOM.setStyleAttribute(selectedItemIcon.getElement(), "marginTop", - marginTop + "px"); - } - - private static Set<Integer> navigationKeyCodes = new HashSet<Integer>(); - static { - navigationKeyCodes.add(KeyCodes.KEY_DOWN); - navigationKeyCodes.add(KeyCodes.KEY_UP); - navigationKeyCodes.add(KeyCodes.KEY_PAGEDOWN); - navigationKeyCodes.add(KeyCodes.KEY_PAGEUP); - navigationKeyCodes.add(KeyCodes.KEY_ENTER); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt - * .event.dom.client.KeyDownEvent) - */ - - @Override - public void onKeyDown(KeyDownEvent event) { - if (enabled && !readonly) { - int keyCode = event.getNativeKeyCode(); - - debug("key down: " + keyCode); - if (waitingForFilteringResponse - && navigationKeyCodes.contains(keyCode)) { - /* - * Keyboard navigation events should not be handled while we are - * waiting for a response. This avoids flickering, disappearing - * items, wrongly interpreted responses and more. - */ - debug("Ignoring " + keyCode - + " because we are waiting for a filtering response"); - DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); - event.stopPropagation(); - return; - } - - if (suggestionPopup.isAttached()) { - debug("Keycode " + keyCode + " target is popup"); - popupKeyDown(event); - } else { - debug("Keycode " + keyCode + " target is text field"); - inputFieldKeyDown(event); - } - } - } - - private void debug(String string) { - if (enableDebug) { - VConsole.error(string); - } - } - - /** - * Triggered when a key is pressed in the text box - * - * @param event - * The KeyDownEvent - */ - private void inputFieldKeyDown(KeyDownEvent event) { - switch (event.getNativeKeyCode()) { - case KeyCodes.KEY_DOWN: - case KeyCodes.KEY_UP: - case KeyCodes.KEY_PAGEDOWN: - case KeyCodes.KEY_PAGEUP: - // open popup as from gadget - filterOptions(-1, ""); - lastFilter = ""; - tb.selectAll(); - break; - case KeyCodes.KEY_ENTER: - /* - * This only handles the case when new items is allowed, a text is - * entered, the popup opener button is clicked to close the popup - * and enter is then pressed (see #7560). - */ - if (!allowNewItem) { - return; - } - - if (currentSuggestion != null - && tb.getText().equals( - currentSuggestion.getReplacementString())) { - // Retain behavior from #6686 by returning without stopping - // propagation if there's nothing to do - return; - } - suggestionPopup.menu.doSelectedItemAction(); - - event.stopPropagation(); - break; - } - - } - - /** - * Triggered when a key was pressed in the suggestion popup. - * - * @param event - * The KeyDownEvent of the key - */ - private void popupKeyDown(KeyDownEvent event) { - // Propagation of handled events is stopped so other handlers such as - // shortcut key handlers do not also handle the same events. - switch (event.getNativeKeyCode()) { - case KeyCodes.KEY_DOWN: - suggestionPopup.selectNextItem(); - suggestionPopup.menu.setKeyboardSelectedItem(suggestionPopup.menu - .getSelectedItem()); - DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); - event.stopPropagation(); - break; - case KeyCodes.KEY_UP: - suggestionPopup.selectPrevItem(); - suggestionPopup.menu.setKeyboardSelectedItem(suggestionPopup.menu - .getSelectedItem()); - DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); - event.stopPropagation(); - break; - case KeyCodes.KEY_PAGEDOWN: - if (hasNextPage()) { - filterOptions(currentPage + 1, lastFilter); - } - event.stopPropagation(); - break; - case KeyCodes.KEY_PAGEUP: - if (currentPage > 0) { - filterOptions(currentPage - 1, lastFilter); - } - event.stopPropagation(); - break; - case KeyCodes.KEY_TAB: - tabPressedWhenPopupOpen = true; - filterOptions(currentPage); - // onBlur() takes care of the rest - break; - case KeyCodes.KEY_ESCAPE: - reset(); - event.stopPropagation(); - break; - case KeyCodes.KEY_ENTER: - if (suggestionPopup.menu.getKeyboardSelectedItem() == null) { - /* - * Nothing selected using up/down. Happens e.g. when entering a - * text (causes popup to open) and then pressing enter. - */ - if (!allowNewItem) { - /* - * New items are not allowed: If there is only one - * suggestion, select that. Otherwise do nothing. - */ - if (currentSuggestions.size() == 1) { - onSuggestionSelected(currentSuggestions.get(0)); - } - } else { - // Handle addition of new items. - suggestionPopup.menu.doSelectedItemAction(); - } - } else { - /* - * Get the suggestion that was navigated to using up/down. - */ - currentSuggestion = ((FilterSelectSuggestion) suggestionPopup.menu - .getKeyboardSelectedItem().getCommand()); - onSuggestionSelected(currentSuggestion); - } - - event.stopPropagation(); - break; - } - - } - - /** - * Triggered when a key was depressed - * - * @param event - * The KeyUpEvent of the key depressed - */ - - @Override - public void onKeyUp(KeyUpEvent event) { - if (enabled && !readonly) { - switch (event.getNativeKeyCode()) { - case KeyCodes.KEY_ENTER: - case KeyCodes.KEY_TAB: - case KeyCodes.KEY_SHIFT: - case KeyCodes.KEY_CTRL: - case KeyCodes.KEY_ALT: - case KeyCodes.KEY_DOWN: - case KeyCodes.KEY_UP: - case KeyCodes.KEY_PAGEDOWN: - case KeyCodes.KEY_PAGEUP: - case KeyCodes.KEY_ESCAPE: - ; // NOP - break; - default: - if (textInputEnabled) { - filterOptions(currentPage); - } - break; - } - } - } - - /** - * Resets the Select to its initial state - */ - private void reset() { - if (currentSuggestion != null) { - String text = currentSuggestion.getReplacementString(); - setPromptingOff(text); - selectedOptionKey = currentSuggestion.key; - } else { - if (focused) { - setPromptingOff(""); - } else { - setPromptingOn(); - } - selectedOptionKey = null; - } - lastFilter = ""; - suggestionPopup.hide(); - } - - /** - * Listener for popupopener - */ - - @Override - public void onClick(ClickEvent event) { - if (textInputEnabled - && event.getNativeEvent().getEventTarget().cast() == tb - .getElement()) { - // Don't process clicks on the text field if text input is enabled - return; - } - if (enabled && !readonly) { - // ask suggestionPopup if it was just closed, we are using GWT - // Popup's auto close feature - if (!suggestionPopup.isJustClosed()) { - // If a focus event is not going to be sent, send the options - // request immediately; otherwise queue in the same burst as the - // focus event. Fixes #8321. - boolean immediate = focused - || !client.hasEventListeners(this, EventId.FOCUS); - filterOptions(-1, "", immediate); - popupOpenerClicked = true; - lastFilter = ""; - } - DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); - focus(); - tb.selectAll(); - } - } - - /** - * Calculate minimum width for FilterSelect textarea - */ - protected native int minWidth(String captions) - /*-{ - if(!captions || captions.length <= 0) - return 0; - captions = captions.split("|"); - var d = $wnd.document.createElement("div"); - var html = ""; - for(var i=0; i < captions.length; i++) { - html += "<div>" + captions[i] + "</div>"; - // TODO apply same CSS classname as in suggestionmenu - } - d.style.position = "absolute"; - d.style.top = "0"; - d.style.left = "0"; - d.style.visibility = "hidden"; - d.innerHTML = html; - $wnd.document.body.appendChild(d); - var w = d.offsetWidth; - $wnd.document.body.removeChild(d); - return w; - }-*/; - - /** - * A flag which prevents a focus event from taking place - */ - boolean iePreventNextFocus = false; - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event - * .dom.client.FocusEvent) - */ - - @Override - public void onFocus(FocusEvent event) { - - /* - * When we disable a blur event in ie we need to refocus the textfield. - * This will cause a focus event we do not want to process, so in that - * case we just ignore it. - */ - if (BrowserInfo.get().isIE() && iePreventNextFocus) { - iePreventNextFocus = false; - return; - } - - focused = true; - if (prompting && !readonly) { - setPromptingOff(""); - } - addStyleDependentName("focus"); - - if (client.hasEventListeners(this, EventId.FOCUS)) { - client.updateVariable(paintableId, EventId.FOCUS, "", true); - } - } - - /** - * A flag which cancels the blur event and sets the focus back to the - * textfield if the Browser is IE - */ - boolean preventNextBlurEventInIE = false; - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event - * .dom.client.BlurEvent) - */ - - @Override - public void onBlur(BlurEvent event) { - - if (BrowserInfo.get().isIE() && preventNextBlurEventInIE) { - /* - * Clicking in the suggestion popup or on the popup button in IE - * causes a blur event to be sent for the field. In other browsers - * this is prevented by canceling/preventing default behavior for - * the focus event, in IE we handle it here by refocusing the text - * field and ignoring the resulting focus event for the textfield - * (in onFocus). - */ - preventNextBlurEventInIE = false; - - Element focusedElement = Util.getIEFocusedElement(); - if (getElement().isOrHasChild(focusedElement) - || suggestionPopup.getElement() - .isOrHasChild(focusedElement)) { - - // IF the suggestion popup or another part of the VFilterSelect - // was focused, move the focus back to the textfield and prevent - // the triggered focus event (in onFocus). - iePreventNextFocus = true; - tb.setFocus(true); - return; - } - } - - focused = false; - if (!readonly) { - // much of the TAB handling takes place here - if (tabPressedWhenPopupOpen) { - tabPressedWhenPopupOpen = false; - suggestionPopup.menu.doSelectedItemAction(); - suggestionPopup.hide(); - } else if (!suggestionPopup.isAttached() - || suggestionPopup.isJustClosed()) { - suggestionPopup.menu.doSelectedItemAction(); - } - if (selectedOptionKey == null) { - setPromptingOn(); - } else if (currentSuggestion != null) { - setPromptingOff(currentSuggestion.caption); - } - } - removeStyleDependentName("focus"); - - if (client.hasEventListeners(this, EventId.BLUR)) { - client.updateVariable(paintableId, EventId.BLUR, "", true); - } - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.Focusable#focus() - */ - - @Override - public void focus() { - focused = true; - if (prompting && !readonly) { - setPromptingOff(""); - } - tb.setFocus(true); - } - - /** - * Calculates the width of the select if the select has undefined width. - * Should be called when the width changes or when the icon changes. - */ - protected void updateRootWidth() { - ComponentConnector paintable = ConnectorMap.get(client).getConnector( - this); - if (paintable.isUndefinedWidth()) { - - /* - * When the select has a undefined with we need to check that we are - * only setting the text box width relative to the first page width - * of the items. If this is not done the text box width will change - * when the popup is used to view longer items than the text box is - * wide. - */ - int w = Util.getRequiredWidth(this); - if ((!initDone || currentPage + 1 < 0) - && suggestionPopupMinWidth > w) { - /* - * We want to compensate for the paddings just to preserve the - * exact size as in Vaadin 6.x, but we get here before - * MeasuredSize has been initialized. - * Util.measureHorizontalPaddingAndBorder does not work with - * border-box, so we must do this the hard way. - */ - Style style = getElement().getStyle(); - String originalPadding = style.getPadding(); - String originalBorder = style.getBorderWidth(); - style.setPaddingLeft(0, Unit.PX); - style.setBorderWidth(0, Unit.PX); - int offset = w - Util.getRequiredWidth(this); - style.setProperty("padding", originalPadding); - style.setProperty("borderWidth", originalBorder); - - setWidth(suggestionPopupMinWidth + offset + "px"); - } - - /* - * Lock the textbox width to its current value if it's not already - * locked - */ - if (!tb.getElement().getStyle().getWidth().endsWith("px")) { - tb.setWidth((tb.getOffsetWidth() - selectedItemIcon - .getOffsetWidth()) + "px"); - } - } - } - - /** - * Get the width of the select in pixels where the text area and icon has - * been included. - * - * @return The width in pixels - */ - private int getMainWidth() { - return getOffsetWidth(); - } - - @Override - public void setWidth(String width) { - super.setWidth(width); - if (width.length() != 0) { - tb.setWidth("100%"); - } - } - - /** - * Handles special behavior of the mouse down event - * - * @param event - */ - private void handleMouseDownEvent(Event event) { - /* - * Prevent the keyboard focus from leaving the textfield by preventing - * the default behaviour of the browser. Fixes #4285. - */ - if (event.getTypeInt() == Event.ONMOUSEDOWN) { - event.preventDefault(); - event.stopPropagation(); - - /* - * In IE the above wont work, the blur event will still trigger. So, - * we set a flag here to prevent the next blur event from happening. - * This is not needed if do not already have focus, in that case - * there will not be any blur event and we should not cancel the - * next blur. - */ - if (BrowserInfo.get().isIE() && focused) { - preventNextBlurEventInIE = true; - } - } - } - - @Override - protected void onDetach() { - super.onDetach(); - suggestionPopup.hide(); - } - - @Override - public Element getSubPartElement(String subPart) { - if ("textbox".equals(subPart)) { - return tb.getElement(); - } else if ("button".equals(subPart)) { - return popupOpener.getElement(); - } - return null; - } - - @Override - public String getSubPartName(Element subElement) { - if (tb.getElement().isOrHasChild(subElement)) { - return "textbox"; - } else if (popupOpener.getElement().isOrHasChild(subElement)) { - return "button"; - } - return null; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/csslayout/CssLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/csslayout/CssLayoutConnector.java deleted file mode 100644 index 2e51d717a4..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/csslayout/CssLayoutConnector.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.csslayout; - -import java.util.HashMap; -import java.util.Map; - -import com.google.gwt.dom.client.Style; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.LayoutClickRpc; -import com.vaadin.shared.ui.csslayout.CssLayoutServerRpc; -import com.vaadin.shared.ui.csslayout.CssLayoutState; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VCaption; -import com.vaadin.terminal.gwt.client.communication.RpcProxy; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.AbstractLayoutConnector; -import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler; -import com.vaadin.terminal.gwt.client.ui.csslayout.VCssLayout.FlowPane; -import com.vaadin.ui.CssLayout; - -@Connect(CssLayout.class) -public class CssLayoutConnector extends AbstractLayoutConnector { - - private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler( - this) { - - @Override - protected ComponentConnector getChildComponent(Element element) { - return Util.getConnectorForElement(getConnection(), getWidget(), - element); - } - - @Override - protected LayoutClickRpc getLayoutClickRPC() { - return rpc; - }; - }; - - private CssLayoutServerRpc rpc; - - private Map<ComponentConnector, VCaption> childToCaption = new HashMap<ComponentConnector, VCaption>(); - - @Override - protected void init() { - super.init(); - rpc = RpcProxy.create(CssLayoutServerRpc.class, this); - } - - @Override - public CssLayoutState getState() { - return (CssLayoutState) super.getState(); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - for (ComponentConnector child : getChildComponents()) { - if (!getState().getChildCss().containsKey(child)) { - continue; - } - String css = getState().getChildCss().get(child); - Style style = child.getWidget().getElement().getStyle(); - // should we remove styles also? How can we know what we have added - // as it is added directly to the child component? - String[] cssRules = css.split(";"); - for (String cssRule : cssRules) { - String parts[] = cssRule.split(":"); - if (parts.length == 2) { - style.setProperty(makeCamelCase(parts[0].trim()), - parts[1].trim()); - } - } - } - - } - - @Override - public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { - super.onConnectorHierarchyChange(event); - - clickEventHandler.handleEventHandlerRegistration(); - - int index = 0; - FlowPane cssLayoutWidgetContainer = getWidget().panel; - for (ComponentConnector child : getChildComponents()) { - VCaption childCaption = childToCaption.get(child); - if (childCaption != null) { - cssLayoutWidgetContainer.addOrMove(childCaption, index++); - } - cssLayoutWidgetContainer.addOrMove(child.getWidget(), index++); - } - - // Detach old child widgets and possibly their caption - for (ComponentConnector child : event.getOldChildren()) { - if (child.getParent() == this) { - // Skip current children - continue; - } - cssLayoutWidgetContainer.remove(child.getWidget()); - VCaption vCaption = childToCaption.remove(child); - if (vCaption != null) { - cssLayoutWidgetContainer.remove(vCaption); - } - } - } - - private static final String makeCamelCase(String cssProperty) { - // TODO this might be cleaner to implement with regexp - while (cssProperty.contains("-")) { - int indexOf = cssProperty.indexOf("-"); - cssProperty = cssProperty.substring(0, indexOf) - + String.valueOf(cssProperty.charAt(indexOf + 1)) - .toUpperCase() + cssProperty.substring(indexOf + 2); - } - if ("float".equals(cssProperty)) { - if (BrowserInfo.get().isIE()) { - return "styleFloat"; - } else { - return "cssFloat"; - } - } - return cssProperty; - } - - @Override - public VCssLayout getWidget() { - return (VCssLayout) super.getWidget(); - } - - @Override - public void updateCaption(ComponentConnector child) { - Widget childWidget = child.getWidget(); - FlowPane cssLayoutWidgetContainer = getWidget().panel; - int widgetPosition = cssLayoutWidgetContainer - .getWidgetIndex(childWidget); - - VCaption caption = childToCaption.get(child); - if (VCaption.isNeeded(child.getState())) { - if (caption == null) { - caption = new VCaption(child, getConnection()); - childToCaption.put(child, caption); - } - if (!caption.isAttached()) { - // Insert caption at widget index == before widget - cssLayoutWidgetContainer.insert(caption, widgetPosition); - } - caption.updateCaption(); - } else if (caption != null) { - childToCaption.remove(child); - cssLayoutWidgetContainer.remove(caption); - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/csslayout/VCssLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/csslayout/VCssLayout.java deleted file mode 100644 index e66b1c4208..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/csslayout/VCssLayout.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.csslayout; - -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.SimplePanel; -import com.google.gwt.user.client.ui.Widget; - -public class VCssLayout extends SimplePanel { - public static final String TAGNAME = "csslayout"; - public static final String CLASSNAME = "v-" + TAGNAME; - - FlowPane panel = new FlowPane(); - - Element margin = DOM.createDiv(); - - public VCssLayout() { - super(); - getElement().appendChild(margin); - setStyleName(CLASSNAME); - margin.setClassName(CLASSNAME + "-margin"); - setWidget(panel); - } - - @Override - protected Element getContainerElement() { - return margin; - } - - public class FlowPane extends FlowPanel { - - public FlowPane() { - super(); - setStyleName(CLASSNAME + "-container"); - } - - void addOrMove(Widget child, int index) { - if (child.getParent() == this) { - int currentIndex = getWidgetIndex(child); - if (index == currentIndex) { - return; - } - } - insert(child, index); - } - - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/customcomponent/CustomComponentConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/customcomponent/CustomComponentConnector.java deleted file mode 100644 index 0557b10437..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/customcomponent/CustomComponentConnector.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.customcomponent; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector; -import com.vaadin.ui.CustomComponent; - -@Connect(value = CustomComponent.class, loadStyle = LoadStyle.EAGER) -public class CustomComponentConnector extends - AbstractComponentContainerConnector { - - @Override - public VCustomComponent getWidget() { - return (VCustomComponent) super.getWidget(); - } - - @Override - public void updateCaption(ComponentConnector component) { - // NOP, custom component dont render composition roots caption - } - - @Override - public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { - super.onConnectorHierarchyChange(event); - - ComponentConnector newChild = null; - if (getChildComponents().size() == 1) { - newChild = getChildComponents().get(0); - } - - VCustomComponent customComponent = getWidget(); - customComponent.setWidget(newChild.getWidget()); - - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/customcomponent/VCustomComponent.java b/client/src/com/vaadin/terminal/gwt/client/ui/customcomponent/VCustomComponent.java deleted file mode 100644 index 854f7c161e..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/customcomponent/VCustomComponent.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.customcomponent; - -import com.google.gwt.user.client.ui.SimplePanel; - -public class VCustomComponent extends SimplePanel { - - private static final String CLASSNAME = "v-customcomponent"; - - public VCustomComponent() { - super(); - setStyleName(CLASSNAME); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/customfield/CustomFieldConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/customfield/CustomFieldConnector.java deleted file mode 100644 index 4120168f62..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/customfield/CustomFieldConnector.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.customfield; - -import com.google.gwt.core.client.GWT; -import com.vaadin.shared.AbstractFieldState; -import com.vaadin.shared.communication.SharedState; -import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.gwt.client.ui.customcomponent.CustomComponentConnector; -import com.vaadin.ui.CustomField; - -@Connect(value = CustomField.class) -public class CustomFieldConnector extends CustomComponentConnector { - @Override - protected SharedState createState() { - // Workaround as CustomFieldConnector does not extend - // AbstractFieldConnector. - return GWT.create(AbstractFieldState.class); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/customlayout/CustomLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/customlayout/CustomLayoutConnector.java deleted file mode 100644 index 1e5cbd0502..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/customlayout/CustomLayoutConnector.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.customlayout; - -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.customlayout.CustomLayoutState; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.AbstractLayoutConnector; -import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout; -import com.vaadin.ui.CustomLayout; - -@Connect(CustomLayout.class) -public class CustomLayoutConnector extends AbstractLayoutConnector implements - SimpleManagedLayout, Paintable { - - @Override - public CustomLayoutState getState() { - return (CustomLayoutState) super.getState(); - } - - @Override - protected void init() { - super.init(); - getWidget().client = getConnection(); - getWidget().pid = getConnectorId(); - - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - // Evaluate scripts - VCustomLayout.eval(getWidget().scripts); - getWidget().scripts = null; - - } - - private void updateHtmlTemplate() { - if (getWidget().hasTemplate()) { - // We (currently) only do this once. You can't change the template - // later on. - return; - } - String templateName = getState().getTemplateName(); - String templateContents = getState().getTemplateContents(); - - if (templateName != null) { - // Get the HTML-template from client. Overrides templateContents - // (even though both can never be given at the same time) - templateContents = getConnection().getResource( - "layouts/" + templateName + ".html"); - if (templateContents == null) { - templateContents = "<em>Layout file layouts/" - + templateName - + ".html is missing. Components will be drawn for debug purposes.</em>"; - } - } - - getWidget().initializeHTML(templateContents, - getConnection().getThemeUri()); - } - - @Override - public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { - super.onConnectorHierarchyChange(event); - - // Must do this once here so the HTML has been set up before we start - // adding child widgets. - - updateHtmlTemplate(); - - // For all contained widgets - for (ComponentConnector child : getChildComponents()) { - String location = getState().getChildLocations().get(child); - try { - getWidget().setWidget(child.getWidget(), location); - } catch (final IllegalArgumentException e) { - // If no location is found, this component is not visible - } - } - for (ComponentConnector oldChild : event.getOldChildren()) { - if (oldChild.getParent() == this) { - // Connector still a child of this - continue; - } - Widget oldChildWidget = oldChild.getWidget(); - if (oldChildWidget.isAttached()) { - // slot of this widget is emptied, remove it - getWidget().remove(oldChildWidget); - } - } - - } - - @Override - public VCustomLayout getWidget() { - return (VCustomLayout) super.getWidget(); - } - - @Override - public void updateCaption(ComponentConnector paintable) { - getWidget().updateCaption(paintable); - } - - @Override - public void layout() { - getWidget().iLayoutJS(DOM.getFirstChild(getWidget().getElement())); - } - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - // Not interested in anything from the UIDL - just implementing the - // interface to avoid some warning (#8688) - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/customlayout/VCustomLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/customlayout/VCustomLayout.java deleted file mode 100644 index 6fd8b19e7c..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/customlayout/VCustomLayout.java +++ /dev/null @@ -1,420 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.customlayout; - -import java.util.HashMap; -import java.util.Iterator; - -import com.google.gwt.dom.client.ImageElement; -import com.google.gwt.dom.client.NodeList; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.ComplexPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VCaption; -import com.vaadin.terminal.gwt.client.VCaptionWrapper; - -/** - * Custom Layout implements complex layout defined with HTML template. - * - * @author Vaadin Ltd - * - */ -public class VCustomLayout extends ComplexPanel { - - public static final String CLASSNAME = "v-customlayout"; - - /** Location-name to containing element in DOM map */ - private final HashMap<String, Element> locationToElement = new HashMap<String, Element>(); - - /** Location-name to contained widget map */ - final HashMap<String, Widget> locationToWidget = new HashMap<String, Widget>(); - - /** Widget to captionwrapper map */ - private final HashMap<Widget, VCaptionWrapper> childWidgetToCaptionWrapper = new HashMap<Widget, VCaptionWrapper>(); - - /** Name of the currently rendered style */ - String currentTemplateName; - - /** Unexecuted scripts loaded from the template */ - String scripts = ""; - - /** Paintable ID of this paintable */ - String pid; - - ApplicationConnection client; - - private boolean htmlInitialized = false; - - private Element elementWithNativeResizeFunction; - - private String height = ""; - - private String width = ""; - - public VCustomLayout() { - setElement(DOM.createDiv()); - // Clear any unwanted styling - DOM.setStyleAttribute(getElement(), "border", "none"); - DOM.setStyleAttribute(getElement(), "margin", "0"); - DOM.setStyleAttribute(getElement(), "padding", "0"); - - if (BrowserInfo.get().isIE()) { - DOM.setStyleAttribute(getElement(), "position", "relative"); - } - - setStyleName(CLASSNAME); - } - - /** - * Sets widget to given location. - * - * If location already contains a widget it will be removed. - * - * @param widget - * Widget to be set into location. - * @param location - * location name where widget will be added - * - * @throws IllegalArgumentException - * if no such location is found in the layout. - */ - public void setWidget(Widget widget, String location) { - - if (widget == null) { - return; - } - - // If no given location is found in the layout, and exception is throws - Element elem = locationToElement.get(location); - if (elem == null && hasTemplate()) { - throw new IllegalArgumentException("No location " + location - + " found"); - } - - // Get previous widget - final Widget previous = locationToWidget.get(location); - // NOP if given widget already exists in this location - if (previous == widget) { - return; - } - - if (previous != null) { - remove(previous); - } - - // if template is missing add element in order - if (!hasTemplate()) { - elem = getElement(); - } - - // Add widget to location - super.add(widget, elem); - locationToWidget.put(location, widget); - } - - /** Initialize HTML-layout. */ - public void initializeHTML(String template, String themeUri) { - - // Connect body of the template to DOM - template = extractBodyAndScriptsFromTemplate(template); - - // TODO prefix img src:s here with a regeps, cannot work further with IE - - String relImgPrefix = themeUri + "/layouts/"; - - // prefix all relative image elements to point to theme dir with a - // regexp search - template = template.replaceAll( - "<((?:img)|(?:IMG))\\s([^>]*)src=\"((?![a-z]+:)[^/][^\"]+)\"", - "<$1 $2src=\"" + relImgPrefix + "$3\""); - // also support src attributes without quotes - template = template - .replaceAll( - "<((?:img)|(?:IMG))\\s([^>]*)src=[^\"]((?![a-z]+:)[^/][^ />]+)[ />]", - "<$1 $2src=\"" + relImgPrefix + "$3\""); - // also prefix relative style="...url(...)..." - template = template - .replaceAll( - "(<[^>]+style=\"[^\"]*url\\()((?![a-z]+:)[^/][^\"]+)(\\)[^>]*>)", - "$1 " + relImgPrefix + "$2 $3"); - - getElement().setInnerHTML(template); - - // Remap locations to elements - locationToElement.clear(); - scanForLocations(getElement()); - - initImgElements(); - - elementWithNativeResizeFunction = DOM.getFirstChild(getElement()); - if (elementWithNativeResizeFunction == null) { - elementWithNativeResizeFunction = getElement(); - } - publishResizedFunction(elementWithNativeResizeFunction); - - htmlInitialized = true; - } - - private native boolean uriEndsWithSlash() - /*-{ - var path = $wnd.location.pathname; - if(path.charAt(path.length - 1) == "/") - return true; - return false; - }-*/; - - boolean hasTemplate() { - return htmlInitialized; - } - - /** Collect locations from template */ - private void scanForLocations(Element elem) { - - final String location = elem.getAttribute("location"); - if (!"".equals(location)) { - locationToElement.put(location, elem); - elem.setInnerHTML(""); - - } else { - final int len = DOM.getChildCount(elem); - for (int i = 0; i < len; i++) { - scanForLocations(DOM.getChild(elem, i)); - } - } - } - - /** Evaluate given script in browser document */ - static native void eval(String script) - /*-{ - try { - if (script != null) - eval("{ var document = $doc; var window = $wnd; "+ script + "}"); - } catch (e) { - } - }-*/; - - /** - * Img elements needs some special handling in custom layout. Img elements - * will get their onload events sunk. This way custom layout can notify - * parent about possible size change. - */ - private void initImgElements() { - NodeList<com.google.gwt.dom.client.Element> nodeList = getElement() - .getElementsByTagName("IMG"); - for (int i = 0; i < nodeList.getLength(); i++) { - com.google.gwt.dom.client.ImageElement img = (ImageElement) nodeList - .getItem(i); - DOM.sinkEvents((Element) img.cast(), Event.ONLOAD); - } - } - - /** - * Extract body part and script tags from raw html-template. - * - * Saves contents of all script-tags to private property: scripts. Returns - * contents of the body part for the html without script-tags. Also replaces - * all _UID_ tags with an unique id-string. - * - * @param html - * Original HTML-template received from server - * @return html that is used to create the HTMLPanel. - */ - private String extractBodyAndScriptsFromTemplate(String html) { - - // Replace UID:s - html = html.replaceAll("_UID_", pid + "__"); - - // Exctract script-tags - scripts = ""; - int endOfPrevScript = 0; - int nextPosToCheck = 0; - String lc = html.toLowerCase(); - String res = ""; - int scriptStart = lc.indexOf("<script", nextPosToCheck); - while (scriptStart > 0) { - res += html.substring(endOfPrevScript, scriptStart); - scriptStart = lc.indexOf(">", scriptStart); - final int j = lc.indexOf("</script>", scriptStart); - scripts += html.substring(scriptStart + 1, j) + ";"; - nextPosToCheck = endOfPrevScript = j + "</script>".length(); - scriptStart = lc.indexOf("<script", nextPosToCheck); - } - res += html.substring(endOfPrevScript); - - // Extract body - html = res; - lc = html.toLowerCase(); - int startOfBody = lc.indexOf("<body"); - if (startOfBody < 0) { - res = html; - } else { - res = ""; - startOfBody = lc.indexOf(">", startOfBody) + 1; - final int endOfBody = lc.indexOf("</body>", startOfBody); - if (endOfBody > startOfBody) { - res = html.substring(startOfBody, endOfBody); - } else { - res = html.substring(startOfBody); - } - } - - return res; - } - - /** Update caption for given widget */ - public void updateCaption(ComponentConnector paintable) { - Widget widget = paintable.getWidget(); - VCaptionWrapper wrapper = childWidgetToCaptionWrapper.get(widget); - if (VCaption.isNeeded(paintable.getState())) { - if (wrapper == null) { - // Add a wrapper between the layout and the child widget - final String loc = getLocation(widget); - super.remove(widget); - wrapper = new VCaptionWrapper(paintable, client); - super.add(wrapper, locationToElement.get(loc)); - childWidgetToCaptionWrapper.put(widget, wrapper); - } - wrapper.updateCaption(); - } else { - if (wrapper != null) { - // Remove the wrapper and add the widget directly to the layout - final String loc = getLocation(widget); - super.remove(wrapper); - super.add(widget, locationToElement.get(loc)); - childWidgetToCaptionWrapper.remove(widget); - } - } - } - - /** Get the location of an widget */ - public String getLocation(Widget w) { - for (final Iterator<String> i = locationToWidget.keySet().iterator(); i - .hasNext();) { - final String location = i.next(); - if (locationToWidget.get(location) == w) { - return location; - } - } - return null; - } - - /** Removes given widget from the layout */ - @Override - public boolean remove(Widget w) { - final String location = getLocation(w); - if (location != null) { - locationToWidget.remove(location); - } - final VCaptionWrapper cw = childWidgetToCaptionWrapper.get(w); - if (cw != null) { - childWidgetToCaptionWrapper.remove(w); - return super.remove(cw); - } else if (w != null) { - return super.remove(w); - } - return false; - } - - /** Adding widget without specifying location is not supported */ - @Override - public void add(Widget w) { - throw new UnsupportedOperationException(); - } - - /** Clear all widgets from the layout */ - @Override - public void clear() { - super.clear(); - locationToWidget.clear(); - childWidgetToCaptionWrapper.clear(); - } - - /** - * This method is published to JS side with the same name into first DOM - * node of custom layout. This way if one implements some resizeable - * containers in custom layout he/she can notify children after resize. - */ - public void notifyChildrenOfSizeChange() { - client.runDescendentsLayout(this); - } - - @Override - public void onDetach() { - super.onDetach(); - if (elementWithNativeResizeFunction != null) { - detachResizedFunction(elementWithNativeResizeFunction); - } - } - - private native void detachResizedFunction(Element element) - /*-{ - element.notifyChildrenOfSizeChange = null; - }-*/; - - private native void publishResizedFunction(Element element) - /*-{ - var self = this; - element.notifyChildrenOfSizeChange = $entry(function() { - self.@com.vaadin.terminal.gwt.client.ui.customlayout.VCustomLayout::notifyChildrenOfSizeChange()(); - }); - }-*/; - - /** - * In custom layout one may want to run layout functions made with - * JavaScript. This function tests if one exists (with name "iLayoutJS" in - * layouts first DOM node) and runs et. Return value is used to determine if - * children needs to be notified of size changes. - * - * Note! When implementing a JS layout function you most likely want to call - * notifyChildrenOfSizeChange() function on your custom layouts main - * element. That method is used to control whether child components layout - * functions are to be run. - * - * @param el - * @return true if layout function exists and was run successfully, else - * false. - */ - native boolean iLayoutJS(Element el) - /*-{ - if(el && el.iLayoutJS) { - try { - el.iLayoutJS(); - return true; - } catch (e) { - return false; - } - } else { - return false; - } - }-*/; - - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - if (event.getTypeInt() == Event.ONLOAD) { - Util.notifyParentOfSizeChange(this, true); - event.cancelBubble(true); - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/AbstractDateFieldConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/datefield/AbstractDateFieldConnector.java deleted file mode 100644 index 791849b067..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/AbstractDateFieldConnector.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.datefield; - -import java.util.Date; - -import com.vaadin.shared.ui.datefield.DateFieldConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.LocaleNotLoadedException; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.ui.AbstractFieldConnector; - -public class AbstractDateFieldConnector extends AbstractFieldConnector - implements Paintable { - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (!isRealUpdate(uidl)) { - return; - } - - // Save details - getWidget().client = client; - getWidget().paintableId = uidl.getId(); - getWidget().immediate = getState().isImmediate(); - - getWidget().readonly = isReadOnly(); - getWidget().enabled = isEnabled(); - - if (uidl.hasAttribute("locale")) { - final String locale = uidl.getStringAttribute("locale"); - try { - getWidget().dts.setLocale(locale); - getWidget().currentLocale = locale; - } catch (final LocaleNotLoadedException e) { - getWidget().currentLocale = getWidget().dts.getLocale(); - VConsole.error("Tried to use an unloaded locale \"" + locale - + "\". Using default locale (" - + getWidget().currentLocale + ")."); - VConsole.error(e); - } - } - - // We show week numbers only if the week starts with Monday, as ISO 8601 - // specifies - getWidget().showISOWeekNumbers = uidl - .getBooleanAttribute(DateFieldConstants.ATTR_WEEK_NUMBERS) - && getWidget().dts.getFirstDayOfWeek() == 1; - - int newResolution; - if (uidl.hasVariable("sec")) { - newResolution = VDateField.RESOLUTION_SEC; - } else if (uidl.hasVariable("min")) { - newResolution = VDateField.RESOLUTION_MIN; - } else if (uidl.hasVariable("hour")) { - newResolution = VDateField.RESOLUTION_HOUR; - } else if (uidl.hasVariable("day")) { - newResolution = VDateField.RESOLUTION_DAY; - } else if (uidl.hasVariable("month")) { - newResolution = VDateField.RESOLUTION_MONTH; - } else { - newResolution = VDateField.RESOLUTION_YEAR; - } - - // Remove old stylename that indicates current resolution - setWidgetStyleName( - VDateField.CLASSNAME - + "-" - + VDateField - .resolutionToString(getWidget().currentResolution), - false); - - getWidget().currentResolution = newResolution; - - // Add stylename that indicates current resolution - setWidgetStyleName( - VDateField.CLASSNAME - + "-" - + VDateField - .resolutionToString(getWidget().currentResolution), - true); - - final int year = uidl.getIntVariable("year"); - final int month = (getWidget().currentResolution >= VDateField.RESOLUTION_MONTH) ? uidl - .getIntVariable("month") : -1; - final int day = (getWidget().currentResolution >= VDateField.RESOLUTION_DAY) ? uidl - .getIntVariable("day") : -1; - final int hour = (getWidget().currentResolution >= VDateField.RESOLUTION_HOUR) ? uidl - .getIntVariable("hour") : 0; - final int min = (getWidget().currentResolution >= VDateField.RESOLUTION_MIN) ? uidl - .getIntVariable("min") : 0; - final int sec = (getWidget().currentResolution >= VDateField.RESOLUTION_SEC) ? uidl - .getIntVariable("sec") : 0; - - // Construct new date for this datefield (only if not null) - if (year > -1) { - getWidget().setCurrentDate( - new Date((long) getWidget().getTime(year, month, day, hour, - min, sec, 0))); - } else { - getWidget().setCurrentDate(null); - } - } - - @Override - public VDateField getWidget() { - return (VDateField) super.getWidget(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/InlineDateFieldConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/datefield/InlineDateFieldConnector.java deleted file mode 100644 index 52f10348b7..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/InlineDateFieldConnector.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.datefield; - -import java.util.Date; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.DateTimeService; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.datefield.VCalendarPanel.FocusChangeListener; -import com.vaadin.terminal.gwt.client.ui.datefield.VCalendarPanel.TimeChangeListener; -import com.vaadin.ui.InlineDateField; - -@Connect(InlineDateField.class) -public class InlineDateFieldConnector extends AbstractDateFieldConnector { - - @Override - @SuppressWarnings("deprecation") - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - super.updateFromUIDL(uidl, client); - if (!isRealUpdate(uidl)) { - return; - } - - getWidget().calendarPanel.setShowISOWeekNumbers(getWidget() - .isShowISOWeekNumbers()); - getWidget().calendarPanel.setDateTimeService(getWidget() - .getDateTimeService()); - getWidget().calendarPanel.setResolution(getWidget() - .getCurrentResolution()); - Date currentDate = getWidget().getCurrentDate(); - if (currentDate != null) { - getWidget().calendarPanel.setDate(new Date(currentDate.getTime())); - } else { - getWidget().calendarPanel.setDate(null); - } - - if (getWidget().currentResolution > VDateField.RESOLUTION_DAY) { - getWidget().calendarPanel - .setTimeChangeListener(new TimeChangeListener() { - @Override - public void changed(int hour, int min, int sec, int msec) { - Date d = getWidget().getDate(); - if (d == null) { - // date currently null, use the value from - // calendarPanel - // (~ client time at the init of the widget) - d = (Date) getWidget().calendarPanel.getDate() - .clone(); - } - d.setHours(hour); - d.setMinutes(min); - d.setSeconds(sec); - DateTimeService.setMilliseconds(d, msec); - - // Always update time changes to the server - getWidget().calendarPanel.setDate(d); - getWidget().updateValueFromPanel(); - } - }); - } - - if (getWidget().currentResolution <= VDateField.RESOLUTION_MONTH) { - getWidget().calendarPanel - .setFocusChangeListener(new FocusChangeListener() { - @Override - public void focusChanged(Date date) { - Date date2 = new Date(); - if (getWidget().calendarPanel.getDate() != null) { - date2.setTime(getWidget().calendarPanel - .getDate().getTime()); - } - /* - * Update the value of calendarPanel - */ - date2.setYear(date.getYear()); - date2.setMonth(date.getMonth()); - getWidget().calendarPanel.setDate(date2); - /* - * Then update the value from panel to server - */ - getWidget().updateValueFromPanel(); - } - }); - } else { - getWidget().calendarPanel.setFocusChangeListener(null); - } - - // Update possible changes - getWidget().calendarPanel.renderCalendar(); - } - - @Override - public VDateFieldCalendar getWidget() { - return (VDateFieldCalendar) super.getWidget(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/PopupDateFieldConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/datefield/PopupDateFieldConnector.java deleted file mode 100644 index 6c4ec40694..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/PopupDateFieldConnector.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.datefield; - -import java.util.Date; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.DateTimeService; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.datefield.VCalendarPanel.FocusChangeListener; -import com.vaadin.terminal.gwt.client.ui.datefield.VCalendarPanel.TimeChangeListener; -import com.vaadin.ui.DateField; - -@Connect(DateField.class) -public class PopupDateFieldConnector extends TextualDateConnector { - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.VTextualDate#updateFromUIDL(com.vaadin - * .terminal.gwt.client.UIDL, - * com.vaadin.terminal.gwt.client.ApplicationConnection) - */ - @Override - @SuppressWarnings("deprecation") - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - boolean lastReadOnlyState = getWidget().readonly; - boolean lastEnabledState = getWidget().isEnabled(); - - getWidget().parsable = uidl.getBooleanAttribute("parsable"); - - super.updateFromUIDL(uidl, client); - - getWidget().calendar.setDateTimeService(getWidget() - .getDateTimeService()); - getWidget().calendar.setShowISOWeekNumbers(getWidget() - .isShowISOWeekNumbers()); - if (getWidget().calendar.getResolution() != getWidget().currentResolution) { - getWidget().calendar.setResolution(getWidget().currentResolution); - if (getWidget().calendar.getDate() != null) { - getWidget().calendar.setDate((Date) getWidget() - .getCurrentDate().clone()); - // force re-render when changing resolution only - getWidget().calendar.renderCalendar(); - } - } - getWidget().calendarToggle.setEnabled(getWidget().enabled); - - if (getWidget().currentResolution <= VPopupCalendar.RESOLUTION_MONTH) { - getWidget().calendar - .setFocusChangeListener(new FocusChangeListener() { - @Override - public void focusChanged(Date date) { - getWidget().updateValue(date); - getWidget().buildDate(); - Date date2 = getWidget().calendar.getDate(); - date2.setYear(date.getYear()); - date2.setMonth(date.getMonth()); - } - }); - } else { - getWidget().calendar.setFocusChangeListener(null); - } - - if (getWidget().currentResolution > VPopupCalendar.RESOLUTION_DAY) { - getWidget().calendar - .setTimeChangeListener(new TimeChangeListener() { - @Override - public void changed(int hour, int min, int sec, int msec) { - Date d = getWidget().getDate(); - if (d == null) { - // date currently null, use the value from - // calendarPanel - // (~ client time at the init of the widget) - d = (Date) getWidget().calendar.getDate() - .clone(); - } - d.setHours(hour); - d.setMinutes(min); - d.setSeconds(sec); - DateTimeService.setMilliseconds(d, msec); - - // Always update time changes to the server - getWidget().updateValue(d); - - // Update text field - getWidget().buildDate(); - } - }); - } - - if (getWidget().readonly) { - getWidget().calendarToggle.addStyleName(VPopupCalendar.CLASSNAME - + "-button-readonly"); - } else { - getWidget().calendarToggle.removeStyleName(VPopupCalendar.CLASSNAME - + "-button-readonly"); - } - - getWidget().calendarToggle.setEnabled(true); - } - - @Override - public VPopupCalendar getWidget() { - return (VPopupCalendar) super.getWidget(); - } - - @Override - protected void setWidgetStyleName(String styleName, boolean add) { - super.setWidgetStyleName(styleName, add); - - // update the style change to popup calendar widget - getWidget().popup.setStyleName(styleName, add); - } - - @Override - protected void setWidgetStyleNameWithPrefix(String prefix, - String styleName, boolean add) { - super.setWidgetStyleNameWithPrefix(prefix, styleName, add); - - // update the style change to popup calendar widget with the correct - // prefix - if (!styleName.startsWith("-")) { - getWidget().popup.setStyleName( - VPopupCalendar.POPUP_PRIMARY_STYLE_NAME + "-" + styleName, - add); - } else { - getWidget().popup.setStyleName( - VPopupCalendar.POPUP_PRIMARY_STYLE_NAME + styleName, add); - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/TextualDateConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/datefield/TextualDateConnector.java deleted file mode 100644 index 01c1529429..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/TextualDateConnector.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.datefield; - -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.UIDL; - -public class TextualDateConnector extends AbstractDateFieldConnector { - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - int origRes = getWidget().currentResolution; - String oldLocale = getWidget().currentLocale; - super.updateFromUIDL(uidl, client); - if (origRes != getWidget().currentResolution - || oldLocale != getWidget().currentLocale) { - // force recreating format string - getWidget().formatStr = null; - } - if (uidl.hasAttribute("format")) { - getWidget().formatStr = uidl.getStringAttribute("format"); - } - - getWidget().inputPrompt = uidl - .getStringAttribute(VTextualDate.ATTR_INPUTPROMPT); - - getWidget().lenient = !uidl.getBooleanAttribute("strict"); - - getWidget().buildDate(); - // not a FocusWidget -> needs own tabindex handling - if (uidl.hasAttribute("tabindex")) { - getWidget().text.setTabIndex(uidl.getIntAttribute("tabindex")); - } - - if (getWidget().readonly) { - getWidget().text.addStyleDependentName("readonly"); - } else { - getWidget().text.removeStyleDependentName("readonly"); - } - - } - - @Override - public VTextualDate getWidget() { - return (VTextualDate) super.getWidget(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/VCalendarPanel.java b/client/src/com/vaadin/terminal/gwt/client/ui/datefield/VCalendarPanel.java deleted file mode 100644 index b61ce5dbf3..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/VCalendarPanel.java +++ /dev/null @@ -1,1769 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.datefield; - -import java.util.Date; -import java.util.Iterator; - -import com.google.gwt.dom.client.Node; -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.ChangeEvent; -import com.google.gwt.event.dom.client.ChangeHandler; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.DomEvent; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.event.dom.client.MouseDownEvent; -import com.google.gwt.event.dom.client.MouseDownHandler; -import com.google.gwt.event.dom.client.MouseOutEvent; -import com.google.gwt.event.dom.client.MouseOutHandler; -import com.google.gwt.event.dom.client.MouseUpEvent; -import com.google.gwt.event.dom.client.MouseUpHandler; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.FlexTable; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.InlineHTML; -import com.google.gwt.user.client.ui.ListBox; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.DateTimeService; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.ui.FocusableFlexTable; -import com.vaadin.terminal.gwt.client.ui.SubPartAware; -import com.vaadin.terminal.gwt.client.ui.label.VLabel; -import com.vaadin.terminal.gwt.client.ui.nativeselect.VNativeSelect; - -@SuppressWarnings("deprecation") -public class VCalendarPanel extends FocusableFlexTable implements - KeyDownHandler, KeyPressHandler, MouseOutHandler, MouseDownHandler, - MouseUpHandler, BlurHandler, FocusHandler, SubPartAware { - - public interface SubmitListener { - - /** - * Called when calendar user triggers a submitting operation in calendar - * panel. Eg. clicking on day or hitting enter. - */ - void onSubmit(); - - /** - * On eg. ESC key. - */ - void onCancel(); - } - - /** - * Blur listener that listens to blur event from the panel - */ - public interface FocusOutListener { - /** - * @return true if the calendar panel is not used after focus moves out - */ - boolean onFocusOut(DomEvent<?> event); - } - - /** - * FocusChangeListener is notified when the panel changes its _focused_ - * value. - */ - public interface FocusChangeListener { - void focusChanged(Date focusedDate); - } - - /** - * Dispatches an event when the panel when time is changed - */ - public interface TimeChangeListener { - - void changed(int hour, int min, int sec, int msec); - } - - /** - * Represents a Date button in the calendar - */ - private class VEventButton extends Button { - public VEventButton() { - addMouseDownHandler(VCalendarPanel.this); - addMouseOutHandler(VCalendarPanel.this); - addMouseUpHandler(VCalendarPanel.this); - } - } - - private static final String CN_FOCUSED = "focused"; - - private static final String CN_TODAY = "today"; - - private static final String CN_SELECTED = "selected"; - - private static final String CN_OFFMONTH = "offmonth"; - - /** - * Represents a click handler for when a user selects a value by using the - * mouse - */ - private ClickHandler dayClickHandler = new ClickHandler() { - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt - * .event.dom.client.ClickEvent) - */ - @Override - public void onClick(ClickEvent event) { - Day day = (Day) event.getSource(); - focusDay(day.getDate()); - selectFocused(); - onSubmit(); - } - }; - - private VEventButton prevYear; - - private VEventButton nextYear; - - private VEventButton prevMonth; - - private VEventButton nextMonth; - - private VTime time; - - private FlexTable days = new FlexTable(); - - private int resolution = VDateField.RESOLUTION_YEAR; - - private int focusedRow; - - private Timer mouseTimer; - - private Date value; - - private boolean enabled = true; - - private boolean readonly = false; - - private DateTimeService dateTimeService; - - private boolean showISOWeekNumbers; - - private Date displayedMonth; - - private Date focusedDate; - - private Day selectedDay; - - private Day focusedDay; - - private FocusOutListener focusOutListener; - - private SubmitListener submitListener; - - private FocusChangeListener focusChangeListener; - - private TimeChangeListener timeChangeListener; - - private boolean hasFocus = false; - - public VCalendarPanel() { - - setStyleName(VDateField.CLASSNAME + "-calendarpanel"); - - /* - * Firefox auto-repeat works correctly only if we use a key press - * handler, other browsers handle it correctly when using a key down - * handler - */ - if (BrowserInfo.get().isGecko()) { - addKeyPressHandler(this); - } else { - addKeyDownHandler(this); - } - addFocusHandler(this); - addBlurHandler(this); - - } - - /** - * Sets the focus to given date in the current view. Used when moving in the - * calendar with the keyboard. - * - * @param date - * A Date representing the day of month to be focused. Must be - * one of the days currently visible. - */ - private void focusDay(Date date) { - // Only used when calender body is present - if (resolution > VDateField.RESOLUTION_MONTH) { - if (focusedDay != null) { - focusedDay.removeStyleDependentName(CN_FOCUSED); - } - - if (date != null && focusedDate != null) { - focusedDate.setTime(date.getTime()); - int rowCount = days.getRowCount(); - for (int i = 0; i < rowCount; i++) { - int cellCount = days.getCellCount(i); - for (int j = 0; j < cellCount; j++) { - Widget widget = days.getWidget(i, j); - if (widget != null && widget instanceof Day) { - Day curday = (Day) widget; - if (curday.getDate().equals(date)) { - curday.addStyleDependentName(CN_FOCUSED); - focusedDay = curday; - focusedRow = i; - return; - } - } - } - } - } - } - } - - /** - * Sets the selection highlight to a given day in the current view - * - * @param date - * A Date representing the day of month to be selected. Must be - * one of the days currently visible. - * - */ - private void selectDate(Date date) { - if (selectedDay != null) { - selectedDay.removeStyleDependentName(CN_SELECTED); - } - - int rowCount = days.getRowCount(); - for (int i = 0; i < rowCount; i++) { - int cellCount = days.getCellCount(i); - for (int j = 0; j < cellCount; j++) { - Widget widget = days.getWidget(i, j); - if (widget != null && widget instanceof Day) { - Day curday = (Day) widget; - if (curday.getDate().equals(date)) { - curday.addStyleDependentName(CN_SELECTED); - selectedDay = curday; - return; - } - } - } - } - } - - /** - * Updates year, month, day from focusedDate to value - */ - private void selectFocused() { - if (focusedDate != null) { - if (value == null) { - // No previously selected value (set to null on server side). - // Create a new date using current date and time - value = new Date(); - } - /* - * #5594 set Date (day) to 1 in order to prevent any kind of - * wrapping of months when later setting the month. (e.g. 31 -> - * month with 30 days -> wraps to the 1st of the following month, - * e.g. 31st of May -> 31st of April = 1st of May) - */ - value.setDate(1); - if (value.getYear() != focusedDate.getYear()) { - value.setYear(focusedDate.getYear()); - } - if (value.getMonth() != focusedDate.getMonth()) { - value.setMonth(focusedDate.getMonth()); - } - if (value.getDate() != focusedDate.getDate()) { - } - // We always need to set the date, even if it hasn't changed, since - // it was forced to 1 above. - value.setDate(focusedDate.getDate()); - - selectDate(focusedDate); - } else { - VConsole.log("Trying to select a the focused date which is NULL!"); - } - } - - protected boolean onValueChange() { - return false; - } - - public int getResolution() { - return resolution; - } - - public void setResolution(int resolution) { - this.resolution = resolution; - if (time != null) { - time.removeFromParent(); - time = null; - } - } - - private boolean isReadonly() { - return readonly; - } - - private boolean isEnabled() { - return enabled; - } - - private void clearCalendarBody(boolean remove) { - if (!remove) { - // Leave the cells in place but clear their contents - - // This has the side effect of ensuring that the calendar always - // contain 7 rows. - for (int row = 1; row < 7; row++) { - for (int col = 0; col < 8; col++) { - days.setHTML(row, col, " "); - } - } - } else if (getRowCount() > 1) { - removeRow(1); - days.clear(); - } - } - - /** - * Builds the top buttons and current month and year header. - * - * @param needsMonth - * Should the month buttons be visible? - */ - private void buildCalendarHeader(boolean needsMonth) { - - getRowFormatter().addStyleName(0, - VDateField.CLASSNAME + "-calendarpanel-header"); - - if (prevMonth == null && needsMonth) { - prevMonth = new VEventButton(); - prevMonth.setHTML("‹"); - prevMonth.setStyleName("v-button-prevmonth"); - prevMonth.setTabIndex(-1); - nextMonth = new VEventButton(); - nextMonth.setHTML("›"); - nextMonth.setStyleName("v-button-nextmonth"); - nextMonth.setTabIndex(-1); - getFlexCellFormatter().setStyleName(0, 3, - VDateField.CLASSNAME + "-calendarpanel-nextmonth"); - getFlexCellFormatter().setStyleName(0, 1, - VDateField.CLASSNAME + "-calendarpanel-prevmonth"); - - setWidget(0, 3, nextMonth); - setWidget(0, 1, prevMonth); - } else if (prevMonth != null && !needsMonth) { - // Remove month traverse buttons - remove(prevMonth); - remove(nextMonth); - prevMonth = null; - nextMonth = null; - } - - if (prevYear == null) { - prevYear = new VEventButton(); - prevYear.setHTML("«"); - prevYear.setStyleName("v-button-prevyear"); - prevYear.setTabIndex(-1); - nextYear = new VEventButton(); - nextYear.setHTML("»"); - nextYear.setStyleName("v-button-nextyear"); - nextYear.setTabIndex(-1); - setWidget(0, 0, prevYear); - setWidget(0, 4, nextYear); - getFlexCellFormatter().setStyleName(0, 0, - VDateField.CLASSNAME + "-calendarpanel-prevyear"); - getFlexCellFormatter().setStyleName(0, 4, - VDateField.CLASSNAME + "-calendarpanel-nextyear"); - } - - final String monthName = needsMonth ? getDateTimeService().getMonth( - focusedDate.getMonth()) : ""; - final int year = focusedDate.getYear() + 1900; - getFlexCellFormatter().setStyleName(0, 2, - VDateField.CLASSNAME + "-calendarpanel-month"); - setHTML(0, 2, "<span class=\"" + VDateField.CLASSNAME - + "-calendarpanel-month\">" + monthName + " " + year - + "</span>"); - } - - private DateTimeService getDateTimeService() { - return dateTimeService; - } - - public void setDateTimeService(DateTimeService dateTimeService) { - this.dateTimeService = dateTimeService; - } - - /** - * Returns whether ISO 8601 week numbers should be shown in the value - * selector or not. ISO 8601 defines that a week always starts with a Monday - * so the week numbers are only shown if this is the case. - * - * @return true if week number should be shown, false otherwise - */ - public boolean isShowISOWeekNumbers() { - return showISOWeekNumbers; - } - - public void setShowISOWeekNumbers(boolean showISOWeekNumbers) { - this.showISOWeekNumbers = showISOWeekNumbers; - } - - /** - * Builds the day and time selectors of the calendar. - */ - private void buildCalendarBody() { - - final int weekColumn = 0; - final int firstWeekdayColumn = 1; - final int headerRow = 0; - - setWidget(1, 0, days); - setCellPadding(0); - setCellSpacing(0); - getFlexCellFormatter().setColSpan(1, 0, 5); - getFlexCellFormatter().setStyleName(1, 0, - VDateField.CLASSNAME + "-calendarpanel-body"); - - days.getFlexCellFormatter().setStyleName(headerRow, weekColumn, - "v-week"); - days.setHTML(headerRow, weekColumn, "<strong></strong>"); - // Hide the week column if week numbers are not to be displayed. - days.getFlexCellFormatter().setVisible(headerRow, weekColumn, - isShowISOWeekNumbers()); - - days.getRowFormatter().setStyleName(headerRow, - VDateField.CLASSNAME + "-calendarpanel-weekdays"); - - if (isShowISOWeekNumbers()) { - days.getFlexCellFormatter().setStyleName(headerRow, weekColumn, - "v-first"); - days.getFlexCellFormatter().setStyleName(headerRow, - firstWeekdayColumn, ""); - days.getRowFormatter().addStyleName(headerRow, - VDateField.CLASSNAME + "-calendarpanel-weeknumbers"); - } else { - days.getFlexCellFormatter().setStyleName(headerRow, weekColumn, ""); - days.getFlexCellFormatter().setStyleName(headerRow, - firstWeekdayColumn, "v-first"); - } - - days.getFlexCellFormatter().setStyleName(headerRow, - firstWeekdayColumn + 6, "v-last"); - - // Print weekday names - final int firstDay = getDateTimeService().getFirstDayOfWeek(); - for (int i = 0; i < 7; i++) { - int day = i + firstDay; - if (day > 6) { - day = 0; - } - if (getResolution() > VDateField.RESOLUTION_MONTH) { - days.setHTML(headerRow, firstWeekdayColumn + i, "<strong>" - + getDateTimeService().getShortDay(day) + "</strong>"); - } else { - days.setHTML(headerRow, firstWeekdayColumn + i, ""); - } - } - - // Zero out hours, minutes, seconds, and milliseconds to compare dates - // without time part - final Date tmp = new Date(); - final Date today = new Date(tmp.getYear(), tmp.getMonth(), - tmp.getDate()); - - final Date selectedDate = value == null ? null : new Date( - value.getYear(), value.getMonth(), value.getDate()); - - final int startWeekDay = getDateTimeService().getStartWeekDay( - displayedMonth); - final Date curr = (Date) displayedMonth.clone(); - // Start from the first day of the week that at least partially belongs - // to the current month - curr.setDate(1 - startWeekDay); - - // No month has more than 6 weeks so 6 is a safe maximum for rows. - for (int weekOfMonth = 1; weekOfMonth < 7; weekOfMonth++) { - for (int dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++) { - - // Actually write the day of month - Day day = new Day((Date) curr.clone()); - - if (curr.equals(selectedDate)) { - day.addStyleDependentName(CN_SELECTED); - selectedDay = day; - } - if (curr.equals(today)) { - day.addStyleDependentName(CN_TODAY); - } - if (curr.equals(focusedDate)) { - focusedDay = day; - focusedRow = weekOfMonth; - if (hasFocus) { - day.addStyleDependentName(CN_FOCUSED); - } - } - if (curr.getMonth() != displayedMonth.getMonth()) { - day.addStyleDependentName(CN_OFFMONTH); - } - - days.setWidget(weekOfMonth, firstWeekdayColumn + dayOfWeek, day); - - // ISO week numbers if requested - days.getCellFormatter().setVisible(weekOfMonth, weekColumn, - isShowISOWeekNumbers()); - if (isShowISOWeekNumbers()) { - final String baseCssClass = VDateField.CLASSNAME - + "-calendarpanel-weeknumber"; - String weekCssClass = baseCssClass; - - int weekNumber = DateTimeService.getISOWeekNumber(curr); - - days.setHTML(weekOfMonth, 0, "<span class=\"" - + weekCssClass + "\"" + ">" + weekNumber - + "</span>"); - } - curr.setDate(curr.getDate() + 1); - } - } - } - - /** - * Do we need the time selector - * - * @return True if it is required - */ - private boolean isTimeSelectorNeeded() { - return getResolution() > VDateField.RESOLUTION_DAY; - } - - /** - * Updates the calendar and text field with the selected dates. - */ - public void renderCalendar() { - if (focusedDate == null) { - Date now = new Date(); - // focusedDate must have zero hours, mins, secs, millisecs - focusedDate = new Date(now.getYear(), now.getMonth(), now.getDate()); - displayedMonth = new Date(now.getYear(), now.getMonth(), 1); - } - - if (getResolution() <= VDateField.RESOLUTION_MONTH - && focusChangeListener != null) { - focusChangeListener.focusChanged(new Date(focusedDate.getTime())); - } - - final boolean needsMonth = getResolution() > VDateField.RESOLUTION_YEAR; - boolean needsBody = getResolution() >= VDateField.RESOLUTION_DAY; - buildCalendarHeader(needsMonth); - clearCalendarBody(!needsBody); - if (needsBody) { - buildCalendarBody(); - } - - if (isTimeSelectorNeeded() && time == null) { - time = new VTime(); - setWidget(2, 0, time); - getFlexCellFormatter().setColSpan(2, 0, 5); - getFlexCellFormatter().setStyleName(2, 0, - VDateField.CLASSNAME + "-calendarpanel-time"); - } else if (isTimeSelectorNeeded()) { - time.updateTimes(); - } else if (time != null) { - remove(time); - } - } - - /** - * Moves the focus forward the given number of days. - */ - private void focusNextDay(int days) { - int oldMonth = focusedDate.getMonth(); - focusedDate.setDate(focusedDate.getDate() + days); - - if (focusedDate.getMonth() == oldMonth) { - // Month did not change, only move the selection - focusDay(focusedDate); - } else { - // If the month changed we need to re-render the calendar - displayedMonth.setMonth(focusedDate.getMonth()); - renderCalendar(); - } - } - - /** - * Moves the focus backward the given number of days. - */ - private void focusPreviousDay(int days) { - focusNextDay(-days); - } - - /** - * Selects the next month - */ - private void focusNextMonth() { - - int currentMonth = focusedDate.getMonth(); - focusedDate.setMonth(currentMonth + 1); - int requestedMonth = (currentMonth + 1) % 12; - - /* - * If the selected value was e.g. 31.3 the new value would be 31.4 but - * this value is invalid so the new value will be 1.5. This is taken - * care of by decreasing the value until we have the correct month. - */ - while (focusedDate.getMonth() != requestedMonth) { - focusedDate.setDate(focusedDate.getDate() - 1); - } - displayedMonth.setMonth(displayedMonth.getMonth() + 1); - - renderCalendar(); - } - - /** - * Selects the previous month - */ - private void focusPreviousMonth() { - int currentMonth = focusedDate.getMonth(); - focusedDate.setMonth(currentMonth - 1); - - /* - * If the selected value was e.g. 31.12 the new value would be 31.11 but - * this value is invalid so the new value will be 1.12. This is taken - * care of by decreasing the value until we have the correct month. - */ - while (focusedDate.getMonth() == currentMonth) { - focusedDate.setDate(focusedDate.getDate() - 1); - } - displayedMonth.setMonth(displayedMonth.getMonth() - 1); - - renderCalendar(); - } - - /** - * Selects the previous year - */ - private void focusPreviousYear(int years) { - int currentMonth = focusedDate.getMonth(); - focusedDate.setYear(focusedDate.getYear() - years); - displayedMonth.setYear(displayedMonth.getYear() - years); - /* - * If the focused date was a leap day (Feb 29), the new date becomes Mar - * 1 if the new year is not also a leap year. Set it to Feb 28 instead. - */ - if (focusedDate.getMonth() != currentMonth) { - focusedDate.setDate(0); - } - renderCalendar(); - } - - /** - * Selects the next year - */ - private void focusNextYear(int years) { - int currentMonth = focusedDate.getMonth(); - focusedDate.setYear(focusedDate.getYear() + years); - displayedMonth.setYear(displayedMonth.getYear() + years); - /* - * If the focused date was a leap day (Feb 29), the new date becomes Mar - * 1 if the new year is not also a leap year. Set it to Feb 28 instead. - */ - if (focusedDate.getMonth() != currentMonth) { - focusedDate.setDate(0); - } - renderCalendar(); - } - - /** - * Handles a user click on the component - * - * @param sender - * The component that was clicked - * @param updateVariable - * Should the value field be updated - * - */ - private void processClickEvent(Widget sender) { - if (!isEnabled() || isReadonly()) { - return; - } - if (sender == prevYear) { - focusPreviousYear(1); - } else if (sender == nextYear) { - focusNextYear(1); - } else if (sender == prevMonth) { - focusPreviousMonth(); - } else if (sender == nextMonth) { - focusNextMonth(); - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt - * .event.dom.client.KeyDownEvent) - */ - @Override - public void onKeyDown(KeyDownEvent event) { - handleKeyPress(event); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.KeyPressHandler#onKeyPress(com.google - * .gwt.event.dom.client.KeyPressEvent) - */ - @Override - public void onKeyPress(KeyPressEvent event) { - handleKeyPress(event); - } - - /** - * Handles the keypress from both the onKeyPress event and the onKeyDown - * event - * - * @param event - * The keydown/keypress event - */ - private void handleKeyPress(DomEvent<?> event) { - if (time != null - && time.getElement().isOrHasChild( - (Node) event.getNativeEvent().getEventTarget().cast())) { - int nativeKeyCode = event.getNativeEvent().getKeyCode(); - if (nativeKeyCode == getSelectKey()) { - onSubmit(); // submit happens if enter key hit down on listboxes - event.preventDefault(); - event.stopPropagation(); - } - return; - } - - // Check tabs - int keycode = event.getNativeEvent().getKeyCode(); - if (keycode == KeyCodes.KEY_TAB && event.getNativeEvent().getShiftKey()) { - if (onTabOut(event)) { - return; - } - } - - // Handle the navigation - if (handleNavigation(keycode, event.getNativeEvent().getCtrlKey() - || event.getNativeEvent().getMetaKey(), event.getNativeEvent() - .getShiftKey())) { - event.preventDefault(); - } - - } - - /** - * Notifies submit-listeners of a submit event - */ - private void onSubmit() { - if (getSubmitListener() != null) { - getSubmitListener().onSubmit(); - } - } - - /** - * Notifies submit-listeners of a cancel event - */ - private void onCancel() { - if (getSubmitListener() != null) { - getSubmitListener().onCancel(); - } - } - - /** - * Handles the keyboard navigation when the resolution is set to years. - * - * @param keycode - * The keycode to process - * @param ctrl - * Is ctrl pressed? - * @param shift - * is shift pressed - * @return Returns true if the keycode was processed, else false - */ - protected boolean handleNavigationYearMode(int keycode, boolean ctrl, - boolean shift) { - - // Ctrl and Shift selection not supported - if (ctrl || shift) { - return false; - } - - else if (keycode == getPreviousKey()) { - focusNextYear(10); // Add 10 years - return true; - } - - else if (keycode == getForwardKey()) { - focusNextYear(1); // Add 1 year - return true; - } - - else if (keycode == getNextKey()) { - focusPreviousYear(10); // Subtract 10 years - return true; - } - - else if (keycode == getBackwardKey()) { - focusPreviousYear(1); // Subtract 1 year - return true; - - } else if (keycode == getSelectKey()) { - value = (Date) focusedDate.clone(); - onSubmit(); - return true; - - } else if (keycode == getResetKey()) { - // Restore showing value the selected value - focusedDate.setTime(value.getTime()); - renderCalendar(); - return true; - - } else if (keycode == getCloseKey()) { - // TODO fire listener, on users responsibility?? - - return true; - } - return false; - } - - /** - * Handle the keyboard navigation when the resolution is set to MONTH - * - * @param keycode - * The keycode to handle - * @param ctrl - * Was the ctrl key pressed? - * @param shift - * Was the shift key pressed? - * @return - */ - protected boolean handleNavigationMonthMode(int keycode, boolean ctrl, - boolean shift) { - - // Ctrl selection not supported - if (ctrl) { - return false; - - } else if (keycode == getPreviousKey()) { - focusNextYear(1); // Add 1 year - return true; - - } else if (keycode == getForwardKey()) { - focusNextMonth(); // Add 1 month - return true; - - } else if (keycode == getNextKey()) { - focusPreviousYear(1); // Subtract 1 year - return true; - - } else if (keycode == getBackwardKey()) { - focusPreviousMonth(); // Subtract 1 month - return true; - - } else if (keycode == getSelectKey()) { - value = (Date) focusedDate.clone(); - onSubmit(); - return true; - - } else if (keycode == getResetKey()) { - // Restore showing value the selected value - focusedDate.setTime(value.getTime()); - renderCalendar(); - return true; - - } else if (keycode == getCloseKey() || keycode == KeyCodes.KEY_TAB) { - - // TODO fire close event - - return true; - } - - return false; - } - - /** - * Handle keyboard navigation what the resolution is set to DAY - * - * @param keycode - * The keycode to handle - * @param ctrl - * Was the ctrl key pressed? - * @param shift - * Was the shift key pressed? - * @return Return true if the key press was handled by the method, else - * return false. - */ - protected boolean handleNavigationDayMode(int keycode, boolean ctrl, - boolean shift) { - - // Ctrl key is not in use - if (ctrl) { - return false; - } - - /* - * Jumps to the next day. - */ - if (keycode == getForwardKey() && !shift) { - focusNextDay(1); - return true; - - /* - * Jumps to the previous day - */ - } else if (keycode == getBackwardKey() && !shift) { - focusPreviousDay(1); - return true; - - /* - * Jumps one week forward in the calendar - */ - } else if (keycode == getNextKey() && !shift) { - focusNextDay(7); - return true; - - /* - * Jumps one week back in the calendar - */ - } else if (keycode == getPreviousKey() && !shift) { - focusPreviousDay(7); - return true; - - /* - * Selects the value that is chosen - */ - } else if (keycode == getSelectKey() && !shift) { - selectFocused(); - onSubmit(); // submit - return true; - - } else if (keycode == getCloseKey()) { - onCancel(); - // TODO close event - - return true; - - /* - * Jumps to the next month - */ - } else if (shift && keycode == getForwardKey()) { - focusNextMonth(); - return true; - - /* - * Jumps to the previous month - */ - } else if (shift && keycode == getBackwardKey()) { - focusPreviousMonth(); - return true; - - /* - * Jumps to the next year - */ - } else if (shift && keycode == getPreviousKey()) { - focusNextYear(1); - return true; - - /* - * Jumps to the previous year - */ - } else if (shift && keycode == getNextKey()) { - focusPreviousYear(1); - return true; - - /* - * Resets the selection - */ - } else if (keycode == getResetKey() && !shift) { - // Restore showing value the selected value - focusedDate = new Date(value.getYear(), value.getMonth(), - value.getDate()); - displayedMonth = new Date(value.getYear(), value.getMonth(), 1); - renderCalendar(); - return true; - } - - return false; - } - - /** - * Handles the keyboard navigation - * - * @param keycode - * The key code that was pressed - * @param ctrl - * Was the ctrl key pressed - * @param shift - * Was the shift key pressed - * @return Return true if key press was handled by the component, else - * return false - */ - protected boolean handleNavigation(int keycode, boolean ctrl, boolean shift) { - if (!isEnabled() || isReadonly()) { - return false; - } - - else if (resolution == VDateField.RESOLUTION_YEAR) { - return handleNavigationYearMode(keycode, ctrl, shift); - } - - else if (resolution == VDateField.RESOLUTION_MONTH) { - return handleNavigationMonthMode(keycode, ctrl, shift); - } - - else if (resolution == VDateField.RESOLUTION_DAY) { - return handleNavigationDayMode(keycode, ctrl, shift); - } - - else { - return handleNavigationDayMode(keycode, ctrl, shift); - } - - } - - /** - * Returns the reset key which will reset the calendar to the previous - * selection. By default this is backspace but it can be overriden to change - * the key to whatever you want. - * - * @return - */ - protected int getResetKey() { - return KeyCodes.KEY_BACKSPACE; - } - - /** - * Returns the select key which selects the value. By default this is the - * enter key but it can be changed to whatever you like by overriding this - * method. - * - * @return - */ - protected int getSelectKey() { - return KeyCodes.KEY_ENTER; - } - - /** - * Returns the key that closes the popup window if this is a VPopopCalendar. - * Else this does nothing. By default this is the Escape key but you can - * change the key to whatever you want by overriding this method. - * - * @return - */ - protected int getCloseKey() { - return KeyCodes.KEY_ESCAPE; - } - - /** - * The key that selects the next day in the calendar. By default this is the - * right arrow key but by overriding this method it can be changed to - * whatever you like. - * - * @return - */ - protected int getForwardKey() { - return KeyCodes.KEY_RIGHT; - } - - /** - * The key that selects the previous day in the calendar. By default this is - * the left arrow key but by overriding this method it can be changed to - * whatever you like. - * - * @return - */ - protected int getBackwardKey() { - return KeyCodes.KEY_LEFT; - } - - /** - * The key that selects the next week in the calendar. By default this is - * the down arrow key but by overriding this method it can be changed to - * whatever you like. - * - * @return - */ - protected int getNextKey() { - return KeyCodes.KEY_DOWN; - } - - /** - * The key that selects the previous week in the calendar. By default this - * is the up arrow key but by overriding this method it can be changed to - * whatever you like. - * - * @return - */ - protected int getPreviousKey() { - return KeyCodes.KEY_UP; - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.MouseOutHandler#onMouseOut(com.google - * .gwt.event.dom.client.MouseOutEvent) - */ - @Override - public void onMouseOut(MouseOutEvent event) { - if (mouseTimer != null) { - mouseTimer.cancel(); - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.MouseDownHandler#onMouseDown(com.google - * .gwt.event.dom.client.MouseDownEvent) - */ - @Override - public void onMouseDown(MouseDownEvent event) { - // Allow user to click-n-hold for fast-forward or fast-rewind. - // Timer is first used for a 500ms delay after mousedown. After that has - // elapsed, another timer is triggered to go off every 150ms. Both - // timers are cancelled on mouseup or mouseout. - if (event.getSource() instanceof VEventButton) { - final VEventButton sender = (VEventButton) event.getSource(); - processClickEvent(sender); - mouseTimer = new Timer() { - @Override - public void run() { - mouseTimer = new Timer() { - @Override - public void run() { - processClickEvent(sender); - } - }; - mouseTimer.scheduleRepeating(150); - } - }; - mouseTimer.schedule(500); - } - - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.MouseUpHandler#onMouseUp(com.google.gwt - * .event.dom.client.MouseUpEvent) - */ - @Override - public void onMouseUp(MouseUpEvent event) { - if (mouseTimer != null) { - mouseTimer.cancel(); - } - } - - /** - * Sets the data of the Panel. - * - * @param currentDate - * The date to set - */ - public void setDate(Date currentDate) { - - // Check that we are not re-rendering an already active date - if (currentDate == value && currentDate != null) { - return; - } - - Date oldDisplayedMonth = displayedMonth; - value = currentDate; - - if (value == null) { - focusedDate = displayedMonth = null; - } else { - focusedDate = new Date(value.getYear(), value.getMonth(), - value.getDate()); - displayedMonth = new Date(value.getYear(), value.getMonth(), 1); - } - - // Re-render calendar if the displayed month is changed, - // or if a time selector is needed but does not exist. - if ((isTimeSelectorNeeded() && time == null) - || oldDisplayedMonth == null || value == null - || oldDisplayedMonth.getYear() != value.getYear() - || oldDisplayedMonth.getMonth() != value.getMonth()) { - renderCalendar(); - } else { - focusDay(focusedDate); - selectFocused(); - if (isTimeSelectorNeeded()) { - time.updateTimes(); - } - } - - if (!hasFocus) { - focusDay(null); - } - } - - /** - * TimeSelector is a widget consisting of list boxes that modifie the Date - * object that is given for. - * - */ - public class VTime extends FlowPanel implements ChangeHandler { - - private ListBox hours; - - private ListBox mins; - - private ListBox sec; - - private ListBox ampm; - - /** - * Constructor - */ - public VTime() { - super(); - setStyleName(VDateField.CLASSNAME + "-time"); - buildTime(); - } - - private ListBox createListBox() { - ListBox lb = new ListBox(); - lb.setStyleName(VNativeSelect.CLASSNAME); - lb.addChangeHandler(this); - lb.addBlurHandler(VCalendarPanel.this); - lb.addFocusHandler(VCalendarPanel.this); - return lb; - } - - /** - * Constructs the ListBoxes and updates their value - * - * @param redraw - * Should new instances of the listboxes be created - */ - private void buildTime() { - clear(); - - hours = createListBox(); - if (getDateTimeService().isTwelveHourClock()) { - hours.addItem("12"); - for (int i = 1; i < 12; i++) { - hours.addItem((i < 10) ? "0" + i : "" + i); - } - } else { - for (int i = 0; i < 24; i++) { - hours.addItem((i < 10) ? "0" + i : "" + i); - } - } - - hours.addChangeHandler(this); - if (getDateTimeService().isTwelveHourClock()) { - ampm = createListBox(); - final String[] ampmText = getDateTimeService().getAmPmStrings(); - ampm.addItem(ampmText[0]); - ampm.addItem(ampmText[1]); - ampm.addChangeHandler(this); - } - - if (getResolution() >= VDateField.RESOLUTION_MIN) { - mins = createListBox(); - for (int i = 0; i < 60; i++) { - mins.addItem((i < 10) ? "0" + i : "" + i); - } - mins.addChangeHandler(this); - } - if (getResolution() >= VDateField.RESOLUTION_SEC) { - sec = createListBox(); - for (int i = 0; i < 60; i++) { - sec.addItem((i < 10) ? "0" + i : "" + i); - } - sec.addChangeHandler(this); - } - - final String delimiter = getDateTimeService().getClockDelimeter(); - if (isReadonly()) { - int h = 0; - if (value != null) { - h = value.getHours(); - } - if (getDateTimeService().isTwelveHourClock()) { - h -= h < 12 ? 0 : 12; - } - add(new VLabel(h < 10 ? "0" + h : "" + h)); - } else { - add(hours); - } - - if (getResolution() >= VDateField.RESOLUTION_MIN) { - add(new VLabel(delimiter)); - if (isReadonly()) { - final int m = mins.getSelectedIndex(); - add(new VLabel(m < 10 ? "0" + m : "" + m)); - } else { - add(mins); - } - } - if (getResolution() >= VDateField.RESOLUTION_SEC) { - add(new VLabel(delimiter)); - if (isReadonly()) { - final int s = sec.getSelectedIndex(); - add(new VLabel(s < 10 ? "0" + s : "" + s)); - } else { - add(sec); - } - } - if (getResolution() == VDateField.RESOLUTION_HOUR) { - add(new VLabel(delimiter + "00")); // o'clock - } - if (getDateTimeService().isTwelveHourClock()) { - add(new VLabel(" ")); - if (isReadonly()) { - int i = 0; - if (value != null) { - i = (value.getHours() < 12) ? 0 : 1; - } - add(new VLabel(ampm.getItemText(i))); - } else { - add(ampm); - } - } - - if (isReadonly()) { - return; - } - - // Update times - updateTimes(); - - ListBox lastDropDown = getLastDropDown(); - lastDropDown.addKeyDownHandler(new KeyDownHandler() { - @Override - public void onKeyDown(KeyDownEvent event) { - boolean shiftKey = event.getNativeEvent().getShiftKey(); - if (shiftKey) { - return; - } else { - int nativeKeyCode = event.getNativeKeyCode(); - if (nativeKeyCode == KeyCodes.KEY_TAB) { - onTabOut(event); - } - } - } - }); - - } - - private ListBox getLastDropDown() { - int i = getWidgetCount() - 1; - while (i >= 0) { - Widget widget = getWidget(i); - if (widget instanceof ListBox) { - return (ListBox) widget; - } - i--; - } - return null; - } - - /** - * Updates the valus to correspond to the values in value - */ - public void updateTimes() { - boolean selected = true; - if (value == null) { - value = new Date(); - selected = false; - } - if (getDateTimeService().isTwelveHourClock()) { - int h = value.getHours(); - ampm.setSelectedIndex(h < 12 ? 0 : 1); - h -= ampm.getSelectedIndex() * 12; - hours.setSelectedIndex(h); - } else { - hours.setSelectedIndex(value.getHours()); - } - if (getResolution() >= VDateField.RESOLUTION_MIN) { - mins.setSelectedIndex(value.getMinutes()); - } - if (getResolution() >= VDateField.RESOLUTION_SEC) { - sec.setSelectedIndex(value.getSeconds()); - } - if (getDateTimeService().isTwelveHourClock()) { - ampm.setSelectedIndex(value.getHours() < 12 ? 0 : 1); - } - - hours.setEnabled(isEnabled()); - if (mins != null) { - mins.setEnabled(isEnabled()); - } - if (sec != null) { - sec.setEnabled(isEnabled()); - } - if (ampm != null) { - ampm.setEnabled(isEnabled()); - } - - } - - private int getMilliseconds() { - return DateTimeService.getMilliseconds(value); - } - - private DateTimeService getDateTimeService() { - if (dateTimeService == null) { - dateTimeService = new DateTimeService(); - } - return dateTimeService; - } - - /* - * (non-Javadoc) VT - * - * @see - * com.google.gwt.event.dom.client.ChangeHandler#onChange(com.google.gwt - * .event.dom.client.ChangeEvent) - */ - @Override - public void onChange(ChangeEvent event) { - /* - * Value from dropdowns gets always set for the value. Like year and - * month when resolution is month or year. - */ - if (event.getSource() == hours) { - int h = hours.getSelectedIndex(); - if (getDateTimeService().isTwelveHourClock()) { - h = h + ampm.getSelectedIndex() * 12; - } - value.setHours(h); - if (timeChangeListener != null) { - timeChangeListener.changed(h, value.getMinutes(), - value.getSeconds(), - DateTimeService.getMilliseconds(value)); - } - event.preventDefault(); - event.stopPropagation(); - } else if (event.getSource() == mins) { - final int m = mins.getSelectedIndex(); - value.setMinutes(m); - if (timeChangeListener != null) { - timeChangeListener.changed(value.getHours(), m, - value.getSeconds(), - DateTimeService.getMilliseconds(value)); - } - event.preventDefault(); - event.stopPropagation(); - } else if (event.getSource() == sec) { - final int s = sec.getSelectedIndex(); - value.setSeconds(s); - if (timeChangeListener != null) { - timeChangeListener.changed(value.getHours(), - value.getMinutes(), s, - DateTimeService.getMilliseconds(value)); - } - event.preventDefault(); - event.stopPropagation(); - } else if (event.getSource() == ampm) { - final int h = hours.getSelectedIndex() - + (ampm.getSelectedIndex() * 12); - value.setHours(h); - if (timeChangeListener != null) { - timeChangeListener.changed(h, value.getMinutes(), - value.getSeconds(), - DateTimeService.getMilliseconds(value)); - } - event.preventDefault(); - event.stopPropagation(); - } - } - - } - - /** - * A widget representing a single day in the calendar panel. - */ - private class Day extends InlineHTML { - private static final String BASECLASS = VDateField.CLASSNAME - + "-calendarpanel-day"; - private final Date date; - - Day(Date date) { - super("" + date.getDate()); - setStyleName(BASECLASS); - this.date = date; - addClickHandler(dayClickHandler); - } - - public Date getDate() { - return date; - } - } - - public Date getDate() { - return value; - } - - /** - * If true should be returned if the panel will not be used after this - * event. - * - * @param event - * @return - */ - protected boolean onTabOut(DomEvent<?> event) { - if (focusOutListener != null) { - return focusOutListener.onFocusOut(event); - } - return false; - } - - /** - * A focus out listener is triggered when the panel loosed focus. This can - * happen either after a user clicks outside the panel or tabs out. - * - * @param listener - * The listener to trigger - */ - public void setFocusOutListener(FocusOutListener listener) { - focusOutListener = listener; - } - - /** - * The submit listener is called when the user selects a value from the - * calender either by clicking the day or selects it by keyboard. - * - * @param submitListener - * The listener to trigger - */ - public void setSubmitListener(SubmitListener submitListener) { - this.submitListener = submitListener; - } - - /** - * The given FocusChangeListener is notified when the focused date changes - * by user either clicking on a new date or by using the keyboard. - * - * @param listener - * The FocusChangeListener to be notified - */ - public void setFocusChangeListener(FocusChangeListener listener) { - focusChangeListener = listener; - } - - /** - * The time change listener is triggered when the user changes the time. - * - * @param listener - */ - public void setTimeChangeListener(TimeChangeListener listener) { - timeChangeListener = listener; - } - - /** - * Returns the submit listener that listens to selection made from the panel - * - * @return The listener or NULL if no listener has been set - */ - public SubmitListener getSubmitListener() { - return submitListener; - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event - * .dom.client.BlurEvent) - */ - @Override - public void onBlur(final BlurEvent event) { - if (event.getSource() instanceof VCalendarPanel) { - hasFocus = false; - focusDay(null); - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event - * .dom.client.FocusEvent) - */ - @Override - public void onFocus(FocusEvent event) { - if (event.getSource() instanceof VCalendarPanel) { - hasFocus = true; - - // Focuses the current day if the calendar shows the days - if (focusedDay != null) { - focusDay(focusedDate); - } - } - } - - private static final String SUBPART_NEXT_MONTH = "nextmon"; - private static final String SUBPART_PREV_MONTH = "prevmon"; - - private static final String SUBPART_NEXT_YEAR = "nexty"; - private static final String SUBPART_PREV_YEAR = "prevy"; - private static final String SUBPART_HOUR_SELECT = "h"; - private static final String SUBPART_MINUTE_SELECT = "m"; - private static final String SUBPART_SECS_SELECT = "s"; - private static final String SUBPART_MSECS_SELECT = "ms"; - private static final String SUBPART_AMPM_SELECT = "ampm"; - private static final String SUBPART_DAY = "day"; - private static final String SUBPART_MONTH_YEAR_HEADER = "header"; - - @Override - public String getSubPartName(Element subElement) { - if (contains(nextMonth, subElement)) { - return SUBPART_NEXT_MONTH; - } else if (contains(prevMonth, subElement)) { - return SUBPART_PREV_MONTH; - } else if (contains(nextYear, subElement)) { - return SUBPART_NEXT_YEAR; - } else if (contains(prevYear, subElement)) { - return SUBPART_PREV_YEAR; - } else if (contains(days, subElement)) { - // Day, find out which dayOfMonth and use that as the identifier - Day day = Util.findWidget(subElement, Day.class); - if (day != null) { - Date date = day.getDate(); - int id = date.getDate(); - // Zero or negative ids map to days of the preceding month, - // past-the-end-of-month ids to days of the following month - if (date.getMonth() < displayedMonth.getMonth()) { - id -= DateTimeService.getNumberOfDaysInMonth(date); - } else if (date.getMonth() > displayedMonth.getMonth()) { - id += DateTimeService - .getNumberOfDaysInMonth(displayedMonth); - } - return SUBPART_DAY + id; - } - } else if (time != null) { - if (contains(time.hours, subElement)) { - return SUBPART_HOUR_SELECT; - } else if (contains(time.mins, subElement)) { - return SUBPART_MINUTE_SELECT; - } else if (contains(time.sec, subElement)) { - return SUBPART_SECS_SELECT; - } else if (contains(time.ampm, subElement)) { - return SUBPART_AMPM_SELECT; - - } - } else if (getCellFormatter().getElement(0, 2).isOrHasChild(subElement)) { - return SUBPART_MONTH_YEAR_HEADER; - } - - return null; - } - - /** - * Checks if subElement is inside the widget DOM hierarchy. - * - * @param w - * @param subElement - * @return true if {@code w} is a parent of subElement, false otherwise. - */ - private boolean contains(Widget w, Element subElement) { - if (w == null || w.getElement() == null) { - return false; - } - - return w.getElement().isOrHasChild(subElement); - } - - @Override - public Element getSubPartElement(String subPart) { - if (SUBPART_NEXT_MONTH.equals(subPart)) { - return nextMonth.getElement(); - } - if (SUBPART_PREV_MONTH.equals(subPart)) { - return prevMonth.getElement(); - } - if (SUBPART_NEXT_YEAR.equals(subPart)) { - return nextYear.getElement(); - } - if (SUBPART_PREV_YEAR.equals(subPart)) { - return prevYear.getElement(); - } - if (SUBPART_HOUR_SELECT.equals(subPart)) { - return time.hours.getElement(); - } - if (SUBPART_MINUTE_SELECT.equals(subPart)) { - return time.mins.getElement(); - } - if (SUBPART_SECS_SELECT.equals(subPart)) { - return time.sec.getElement(); - } - if (SUBPART_AMPM_SELECT.equals(subPart)) { - return time.ampm.getElement(); - } - if (subPart.startsWith(SUBPART_DAY)) { - // Zero or negative ids map to days in the preceding month, - // past-the-end-of-month ids to days in the following month - int dayOfMonth = Integer.parseInt(subPart.substring(SUBPART_DAY - .length())); - Date date = new Date(displayedMonth.getYear(), - displayedMonth.getMonth(), dayOfMonth); - Iterator<Widget> iter = days.iterator(); - while (iter.hasNext()) { - Widget w = iter.next(); - if (w instanceof Day) { - Day day = (Day) w; - if (day.getDate().equals(date)) { - return day.getElement(); - } - } - } - } - - if (SUBPART_MONTH_YEAR_HEADER.equals(subPart)) { - return (Element) getCellFormatter().getElement(0, 2).getChild(0); - } - return null; - } - - @Override - protected void onDetach() { - super.onDetach(); - if (mouseTimer != null) { - mouseTimer.cancel(); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateField.java b/client/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateField.java deleted file mode 100644 index a339fb36d0..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateField.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.datefield; - -import java.util.Date; - -import com.google.gwt.user.client.ui.FlowPanel; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.DateTimeService; -import com.vaadin.terminal.gwt.client.ui.Field; - -public class VDateField extends FlowPanel implements Field { - - public static final String CLASSNAME = "v-datefield"; - - protected String paintableId; - - protected ApplicationConnection client; - - protected boolean immediate; - - public static final int RESOLUTION_YEAR = 1; - public static final int RESOLUTION_MONTH = 2; - public static final int RESOLUTION_DAY = 4; - public static final int RESOLUTION_HOUR = 8; - public static final int RESOLUTION_MIN = 16; - public static final int RESOLUTION_SEC = 32; - - static String resolutionToString(int res) { - if (res > RESOLUTION_DAY) { - return "full"; - } - if (res == RESOLUTION_DAY) { - return "day"; - } - if (res == RESOLUTION_MONTH) { - return "month"; - } - return "year"; - } - - protected int currentResolution = RESOLUTION_YEAR; - - protected String currentLocale; - - protected boolean readonly; - - protected boolean enabled; - - /** - * The date that is selected in the date field. Null if an invalid date is - * specified. - */ - private Date date = null; - - protected DateTimeService dts; - - protected boolean showISOWeekNumbers = false; - - public VDateField() { - setStyleName(CLASSNAME); - dts = new DateTimeService(); - } - - /* - * We need this redundant native function because Java's Date object doesn't - * have a setMilliseconds method. - */ - protected static native double getTime(int y, int m, int d, int h, int mi, - int s, int ms) - /*-{ - try { - var date = new Date(2000,1,1,1); // don't use current date here - if(y && y >= 0) date.setFullYear(y); - if(m && m >= 1) date.setMonth(m-1); - if(d && d >= 0) date.setDate(d); - if(h >= 0) date.setHours(h); - if(mi >= 0) date.setMinutes(mi); - if(s >= 0) date.setSeconds(s); - if(ms >= 0) date.setMilliseconds(ms); - return date.getTime(); - } catch (e) { - // TODO print some error message on the console - //console.log(e); - return (new Date()).getTime(); - } - }-*/; - - public int getMilliseconds() { - return DateTimeService.getMilliseconds(date); - } - - public void setMilliseconds(int ms) { - DateTimeService.setMilliseconds(date, ms); - } - - public int getCurrentResolution() { - return currentResolution; - } - - public void setCurrentResolution(int currentResolution) { - this.currentResolution = currentResolution; - } - - public String getCurrentLocale() { - return currentLocale; - } - - public void setCurrentLocale(String currentLocale) { - this.currentLocale = currentLocale; - } - - public Date getCurrentDate() { - return date; - } - - public void setCurrentDate(Date date) { - this.date = date; - } - - public boolean isImmediate() { - return immediate; - } - - public boolean isReadonly() { - return readonly; - } - - public boolean isEnabled() { - return enabled; - } - - public DateTimeService getDateTimeService() { - return dts; - } - - public String getId() { - return paintableId; - } - - public ApplicationConnection getClient() { - return client; - } - - /** - * Returns whether ISO 8601 week numbers should be shown in the date - * selector or not. ISO 8601 defines that a week always starts with a Monday - * so the week numbers are only shown if this is the case. - * - * @return true if week number should be shown, false otherwise - */ - public boolean isShowISOWeekNumbers() { - return showISOWeekNumbers; - } - - /** - * Returns a copy of the current date. Modifying the returned date will not - * modify the value of this VDateField. Use {@link #setDate(Date)} to change - * the current date. - * - * @return A copy of the current date - */ - protected Date getDate() { - Date current = getCurrentDate(); - if (current == null) { - return null; - } else { - return (Date) getCurrentDate().clone(); - } - } - - /** - * Sets the current date for this VDateField. - * - * @param date - * The new date to use - */ - protected void setDate(Date date) { - this.date = date; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateFieldCalendar.java b/client/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateFieldCalendar.java deleted file mode 100644 index 42640f0c0b..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateFieldCalendar.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.datefield; - -import java.util.Date; - -import com.google.gwt.event.dom.client.DomEvent; -import com.vaadin.terminal.gwt.client.DateTimeService; -import com.vaadin.terminal.gwt.client.ui.datefield.VCalendarPanel.FocusOutListener; -import com.vaadin.terminal.gwt.client.ui.datefield.VCalendarPanel.SubmitListener; - -/** - * A client side implementation for InlineDateField - */ -public class VDateFieldCalendar extends VDateField { - - protected final VCalendarPanel calendarPanel; - - public VDateFieldCalendar() { - super(); - calendarPanel = new VCalendarPanel(); - add(calendarPanel); - calendarPanel.setSubmitListener(new SubmitListener() { - @Override - public void onSubmit() { - updateValueFromPanel(); - } - - @Override - public void onCancel() { - // TODO Auto-generated method stub - - } - }); - calendarPanel.setFocusOutListener(new FocusOutListener() { - @Override - public boolean onFocusOut(DomEvent<?> event) { - updateValueFromPanel(); - return false; - } - }); - } - - /** - * TODO refactor: almost same method as in VPopupCalendar.updateValue - */ - @SuppressWarnings("deprecation") - protected void updateValueFromPanel() { - - // If field is invisible at the beginning, client can still be null when - // this function is called. - if (getClient() == null) { - return; - } - - Date date2 = calendarPanel.getDate(); - Date currentDate = getCurrentDate(); - if (currentDate == null || date2.getTime() != currentDate.getTime()) { - setCurrentDate((Date) date2.clone()); - getClient().updateVariable(getId(), "year", date2.getYear() + 1900, - false); - if (getCurrentResolution() > VDateField.RESOLUTION_YEAR) { - getClient().updateVariable(getId(), "month", - date2.getMonth() + 1, false); - if (getCurrentResolution() > RESOLUTION_MONTH) { - getClient().updateVariable(getId(), "day", date2.getDate(), - false); - if (getCurrentResolution() > RESOLUTION_DAY) { - getClient().updateVariable(getId(), "hour", - date2.getHours(), false); - if (getCurrentResolution() > RESOLUTION_HOUR) { - getClient().updateVariable(getId(), "min", - date2.getMinutes(), false); - if (getCurrentResolution() > RESOLUTION_MIN) { - getClient().updateVariable(getId(), "sec", - date2.getSeconds(), false); - if (getCurrentResolution() > RESOLUTION_SEC) { - getClient().updateVariable( - getId(), - "msec", - DateTimeService - .getMilliseconds(date2), - false); - } - } - } - } - } - } - if (isImmediate()) { - getClient().sendPendingVariableChanges(); - } - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/VPopupCalendar.java b/client/src/com/vaadin/terminal/gwt/client/ui/datefield/VPopupCalendar.java deleted file mode 100644 index b7e0a2fb4e..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/VPopupCalendar.java +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.datefield; - -import java.util.Date; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.DomEvent; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.logical.shared.CloseEvent; -import com.google.gwt.event.logical.shared.CloseHandler; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.PopupPanel; -import com.google.gwt.user.client.ui.PopupPanel.PositionCallback; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.ui.Field; -import com.vaadin.terminal.gwt.client.ui.SubPartAware; -import com.vaadin.terminal.gwt.client.ui.VOverlay; -import com.vaadin.terminal.gwt.client.ui.datefield.VCalendarPanel.FocusOutListener; -import com.vaadin.terminal.gwt.client.ui.datefield.VCalendarPanel.SubmitListener; - -/** - * Represents a date selection component with a text field and a popup date - * selector. - * - * <b>Note:</b> To change the keyboard assignments used in the popup dialog you - * should extend <code>com.vaadin.terminal.gwt.client.ui.VCalendarPanel</code> - * and then pass set it by calling the - * <code>setCalendarPanel(VCalendarPanel panel)</code> method. - * - */ -public class VPopupCalendar extends VTextualDate implements Field, - ClickHandler, CloseHandler<PopupPanel>, SubPartAware { - - protected static final String POPUP_PRIMARY_STYLE_NAME = VDateField.CLASSNAME - + "-popup"; - - protected final Button calendarToggle; - - protected VCalendarPanel calendar; - - protected final VOverlay popup; - private boolean open = false; - protected boolean parsable = true; - - public VPopupCalendar() { - super(); - - calendarToggle = new Button(); - calendarToggle.setStyleName(CLASSNAME + "-button"); - calendarToggle.setText(""); - calendarToggle.addClickHandler(this); - // -2 instead of -1 to avoid FocusWidget.onAttach to reset it - calendarToggle.getElement().setTabIndex(-2); - add(calendarToggle); - - calendar = GWT.create(VCalendarPanel.class); - calendar.setFocusOutListener(new FocusOutListener() { - @Override - public boolean onFocusOut(DomEvent<?> event) { - event.preventDefault(); - closeCalendarPanel(); - return true; - } - }); - - calendar.setSubmitListener(new SubmitListener() { - @Override - public void onSubmit() { - // Update internal value and send valuechange event if immediate - updateValue(calendar.getDate()); - - // Update text field (a must when not immediate). - buildDate(true); - - closeCalendarPanel(); - } - - @Override - public void onCancel() { - closeCalendarPanel(); - } - }); - - popup = new VOverlay(true, true, true); - popup.setStyleName(POPUP_PRIMARY_STYLE_NAME); - popup.setWidget(calendar); - popup.addCloseHandler(this); - - DOM.setElementProperty(calendar.getElement(), "id", - "PID_VAADIN_POPUPCAL"); - - sinkEvents(Event.ONKEYDOWN); - - } - - @SuppressWarnings("deprecation") - protected void updateValue(Date newDate) { - Date currentDate = getCurrentDate(); - if (currentDate == null || newDate.getTime() != currentDate.getTime()) { - setCurrentDate((Date) newDate.clone()); - getClient().updateVariable(getId(), "year", - newDate.getYear() + 1900, false); - if (getCurrentResolution() > VDateField.RESOLUTION_YEAR) { - getClient().updateVariable(getId(), "month", - newDate.getMonth() + 1, false); - if (getCurrentResolution() > RESOLUTION_MONTH) { - getClient().updateVariable(getId(), "day", - newDate.getDate(), false); - if (getCurrentResolution() > RESOLUTION_DAY) { - getClient().updateVariable(getId(), "hour", - newDate.getHours(), false); - if (getCurrentResolution() > RESOLUTION_HOUR) { - getClient().updateVariable(getId(), "min", - newDate.getMinutes(), false); - if (getCurrentResolution() > RESOLUTION_MIN) { - getClient().updateVariable(getId(), "sec", - newDate.getSeconds(), false); - } - } - } - } - } - if (isImmediate()) { - getClient().sendPendingVariableChanges(); - } - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.user.client.ui.UIObject#setStyleName(java.lang.String) - */ - @Override - public void setStyleName(String style) { - // make sure the style is there before size calculation - super.setStyleName(style + " " + CLASSNAME + "-popupcalendar"); - } - - /** - * Opens the calendar panel popup - */ - public void openCalendarPanel() { - - if (!open && !readonly) { - open = true; - - if (getCurrentDate() != null) { - calendar.setDate((Date) getCurrentDate().clone()); - } else { - calendar.setDate(new Date()); - } - - // clear previous values - popup.setWidth(""); - popup.setHeight(""); - popup.setPopupPositionAndShow(new PositionCallback() { - @Override - public void setPosition(int offsetWidth, int offsetHeight) { - final int w = offsetWidth; - final int h = offsetHeight; - final int browserWindowWidth = Window.getClientWidth() - + Window.getScrollLeft(); - final int browserWindowHeight = Window.getClientHeight() - + Window.getScrollTop(); - int t = calendarToggle.getAbsoluteTop(); - int l = calendarToggle.getAbsoluteLeft(); - - // Add a little extra space to the right to avoid - // problems with IE7 scrollbars and to make it look - // nicer. - int extraSpace = 30; - - boolean overflowRight = false; - if (l + +w + extraSpace > browserWindowWidth) { - overflowRight = true; - // Part of the popup is outside the browser window - // (to the right) - l = browserWindowWidth - w - extraSpace; - } - - if (t + h + calendarToggle.getOffsetHeight() + 30 > browserWindowHeight) { - // Part of the popup is outside the browser window - // (below) - t = browserWindowHeight - h - - calendarToggle.getOffsetHeight() - 30; - if (!overflowRight) { - // Show to the right of the popup button unless we - // are in the lower right corner of the screen - l += calendarToggle.getOffsetWidth(); - } - } - - // fix size - popup.setWidth(w + "px"); - popup.setHeight(h + "px"); - - popup.setPopupPosition(l, - t + calendarToggle.getOffsetHeight() + 2); - - /* - * We have to wait a while before focusing since the popup - * needs to be opened before we can focus - */ - Timer focusTimer = new Timer() { - @Override - public void run() { - setFocus(true); - } - }; - - focusTimer.schedule(100); - } - }); - } else { - VConsole.error("Cannot reopen popup, it is already open!"); - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event - * .dom.client.ClickEvent) - */ - @Override - public void onClick(ClickEvent event) { - if (event.getSource() == calendarToggle && isEnabled()) { - openCalendarPanel(); - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google.gwt - * .event.logical.shared.CloseEvent) - */ - @Override - public void onClose(CloseEvent<PopupPanel> event) { - if (event.getSource() == popup) { - buildDate(); - if (!BrowserInfo.get().isTouchDevice()) { - /* - * Move focus to textbox, unless on touch device (avoids opening - * virtual keyboard). - */ - focus(); - } - - // TODO resolve what the "Sigh." is all about and document it here - // Sigh. - Timer t = new Timer() { - @Override - public void run() { - open = false; - } - }; - t.schedule(100); - } - } - - /** - * Sets focus to Calendar panel. - * - * @param focus - */ - public void setFocus(boolean focus) { - calendar.setFocus(focus); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.ui.VTextualDate#buildDate() - */ - @Override - protected void buildDate() { - // Save previous value - String previousValue = getText(); - super.buildDate(); - - // Restore previous value if the input could not be parsed - if (!parsable) { - setText(previousValue); - } - } - - /** - * Update the text field contents from the date. See {@link #buildDate()}. - * - * @param forceValid - * true to force the text field to be updated, false to only - * update if the parsable flag is true. - */ - protected void buildDate(boolean forceValid) { - if (forceValid) { - parsable = true; - } - buildDate(); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.VDateField#onBrowserEvent(com.google - * .gwt.user.client.Event) - */ - @Override - public void onBrowserEvent(com.google.gwt.user.client.Event event) { - super.onBrowserEvent(event); - if (DOM.eventGetType(event) == Event.ONKEYDOWN - && event.getKeyCode() == getOpenCalenderPanelKey()) { - openCalendarPanel(); - event.preventDefault(); - } - } - - /** - * Get the key code that opens the calendar panel. By default it is the down - * key but you can override this to be whatever you like - * - * @return - */ - protected int getOpenCalenderPanelKey() { - return KeyCodes.KEY_DOWN; - } - - /** - * Closes the open popup panel - */ - public void closeCalendarPanel() { - if (open) { - popup.hide(true); - } - } - - private final String CALENDAR_TOGGLE_ID = "popupButton"; - - @Override - public Element getSubPartElement(String subPart) { - if (subPart.equals(CALENDAR_TOGGLE_ID)) { - return calendarToggle.getElement(); - } - - return super.getSubPartElement(subPart); - } - - @Override - public String getSubPartName(Element subElement) { - if (calendarToggle.getElement().isOrHasChild(subElement)) { - return CALENDAR_TOGGLE_ID; - } - - return super.getSubPartName(subElement); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/VTextualDate.java b/client/src/com/vaadin/terminal/gwt/client/ui/datefield/VTextualDate.java deleted file mode 100644 index 4e82058f68..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/datefield/VTextualDate.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.datefield; - -import java.util.Date; - -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.ChangeEvent; -import com.google.gwt.event.dom.client.ChangeHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.TextBox; -import com.vaadin.shared.EventId; -import com.vaadin.terminal.gwt.client.Focusable; -import com.vaadin.terminal.gwt.client.LocaleNotLoadedException; -import com.vaadin.terminal.gwt.client.LocaleService; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.ui.Field; -import com.vaadin.terminal.gwt.client.ui.SubPartAware; -import com.vaadin.terminal.gwt.client.ui.textfield.VTextField; - -public class VTextualDate extends VDateField implements Field, ChangeHandler, - Focusable, SubPartAware { - - private static final String PARSE_ERROR_CLASSNAME = CLASSNAME - + "-parseerror"; - - protected final TextBox text; - - protected String formatStr; - - protected boolean lenient; - - private static final String CLASSNAME_PROMPT = "prompt"; - protected static final String ATTR_INPUTPROMPT = "prompt"; - protected String inputPrompt = ""; - private boolean prompting = false; - - public VTextualDate() { - - super(); - text = new TextBox(); - // use normal textfield styles as a basis - text.setStyleName(VTextField.CLASSNAME); - // add datefield spesific style name also - text.addStyleName(CLASSNAME + "-textfield"); - text.addChangeHandler(this); - text.addFocusHandler(new FocusHandler() { - @Override - public void onFocus(FocusEvent event) { - text.addStyleName(VTextField.CLASSNAME + "-" - + VTextField.CLASSNAME_FOCUS); - if (prompting) { - text.setText(""); - setPrompting(false); - } - if (getClient() != null - && getClient().hasEventListeners(VTextualDate.this, - EventId.FOCUS)) { - getClient() - .updateVariable(getId(), EventId.FOCUS, "", true); - } - } - }); - text.addBlurHandler(new BlurHandler() { - @Override - public void onBlur(BlurEvent event) { - text.removeStyleName(VTextField.CLASSNAME + "-" - + VTextField.CLASSNAME_FOCUS); - String value = getText(); - setPrompting(inputPrompt != null - && (value == null || "".equals(value))); - if (prompting) { - text.setText(readonly ? "" : inputPrompt); - } - if (getClient() != null - && getClient().hasEventListeners(VTextualDate.this, - EventId.BLUR)) { - getClient().updateVariable(getId(), EventId.BLUR, "", true); - } - } - }); - add(text); - } - - protected String getFormatString() { - if (formatStr == null) { - if (currentResolution == RESOLUTION_YEAR) { - formatStr = "yyyy"; // force full year - } else { - - try { - String frmString = LocaleService - .getDateFormat(currentLocale); - frmString = cleanFormat(frmString); - // String delim = LocaleService - // .getClockDelimiter(currentLocale); - - if (currentResolution >= RESOLUTION_HOUR) { - if (dts.isTwelveHourClock()) { - frmString += " hh"; - } else { - frmString += " HH"; - } - if (currentResolution >= RESOLUTION_MIN) { - frmString += ":mm"; - if (currentResolution >= RESOLUTION_SEC) { - frmString += ":ss"; - } - } - if (dts.isTwelveHourClock()) { - frmString += " aaa"; - } - - } - - formatStr = frmString; - } catch (LocaleNotLoadedException e) { - // TODO should die instead? Can the component survive - // without format string? - VConsole.error(e); - } - } - } - return formatStr; - } - - /** - * Updates the text field according to the current date (provided by - * {@link #getDate()}). Takes care of updating text, enabling and disabling - * the field, setting/removing readonly status and updating readonly styles. - * - * TODO: Split part of this into a method that only updates the text as this - * is what usually is needed except for updateFromUIDL. - */ - protected void buildDate() { - removeStyleName(PARSE_ERROR_CLASSNAME); - // Create the initial text for the textfield - String dateText; - Date currentDate = getDate(); - if (currentDate != null) { - dateText = getDateTimeService().formatDate(currentDate, - getFormatString()); - } else { - dateText = ""; - } - - setText(dateText); - text.setEnabled(enabled); - text.setReadOnly(readonly); - - if (readonly) { - text.addStyleName("v-readonly"); - } else { - text.removeStyleName("v-readonly"); - } - - } - - protected void setPrompting(boolean prompting) { - this.prompting = prompting; - if (prompting) { - addStyleDependentName(CLASSNAME_PROMPT); - } else { - removeStyleDependentName(CLASSNAME_PROMPT); - } - } - - @Override - @SuppressWarnings("deprecation") - public void onChange(ChangeEvent event) { - if (!text.getText().equals("")) { - try { - String enteredDate = text.getText(); - - setDate(getDateTimeService().parseDate(enteredDate, - getFormatString(), lenient)); - - if (lenient) { - // If date value was leniently parsed, normalize text - // presentation. - // FIXME: Add a description/example here of when this is - // needed - text.setValue( - getDateTimeService().formatDate(getDate(), - getFormatString()), false); - } - - // remove possibly added invalid value indication - removeStyleName(PARSE_ERROR_CLASSNAME); - } catch (final Exception e) { - VConsole.log(e); - - addStyleName(PARSE_ERROR_CLASSNAME); - // this is a hack that may eventually be removed - getClient().updateVariable(getId(), "lastInvalidDateString", - text.getText(), false); - setDate(null); - } - } else { - setDate(null); - // remove possibly added invalid value indication - removeStyleName(PARSE_ERROR_CLASSNAME); - } - // always send the date string - getClient() - .updateVariable(getId(), "dateString", text.getText(), false); - - // Update variables - // (only the smallest defining resolution needs to be - // immediate) - Date currentDate = getDate(); - getClient().updateVariable(getId(), "year", - currentDate != null ? currentDate.getYear() + 1900 : -1, - currentResolution == VDateField.RESOLUTION_YEAR && immediate); - if (currentResolution >= VDateField.RESOLUTION_MONTH) { - getClient().updateVariable( - getId(), - "month", - currentDate != null ? currentDate.getMonth() + 1 : -1, - currentResolution == VDateField.RESOLUTION_MONTH - && immediate); - } - if (currentResolution >= VDateField.RESOLUTION_DAY) { - getClient() - .updateVariable( - getId(), - "day", - currentDate != null ? currentDate.getDate() : -1, - currentResolution == VDateField.RESOLUTION_DAY - && immediate); - } - if (currentResolution >= VDateField.RESOLUTION_HOUR) { - getClient().updateVariable( - getId(), - "hour", - currentDate != null ? currentDate.getHours() : -1, - currentResolution == VDateField.RESOLUTION_HOUR - && immediate); - } - if (currentResolution >= VDateField.RESOLUTION_MIN) { - getClient() - .updateVariable( - getId(), - "min", - currentDate != null ? currentDate.getMinutes() : -1, - currentResolution == VDateField.RESOLUTION_MIN - && immediate); - } - if (currentResolution >= VDateField.RESOLUTION_SEC) { - getClient() - .updateVariable( - getId(), - "sec", - currentDate != null ? currentDate.getSeconds() : -1, - currentResolution == VDateField.RESOLUTION_SEC - && immediate); - } - - } - - private String cleanFormat(String format) { - // Remove unnecessary d & M if resolution is too low - if (currentResolution < VDateField.RESOLUTION_DAY) { - format = format.replaceAll("d", ""); - } - if (currentResolution < VDateField.RESOLUTION_MONTH) { - format = format.replaceAll("M", ""); - } - - // Remove unsupported patterns - // TODO support for 'G', era designator (used at least in Japan) - format = format.replaceAll("[GzZwWkK]", ""); - - // Remove extra delimiters ('/' and '.') - while (format.startsWith("/") || format.startsWith(".") - || format.startsWith("-")) { - format = format.substring(1); - } - while (format.endsWith("/") || format.endsWith(".") - || format.endsWith("-")) { - format = format.substring(0, format.length() - 1); - } - - // Remove duplicate delimiters - format = format.replaceAll("//", "/"); - format = format.replaceAll("\\.\\.", "."); - format = format.replaceAll("--", "-"); - - return format.trim(); - } - - @Override - public void focus() { - text.setFocus(true); - } - - protected String getText() { - if (prompting) { - return ""; - } - return text.getText(); - } - - protected void setText(String text) { - if (inputPrompt != null && (text == null || "".equals(text))) { - text = readonly ? "" : inputPrompt; - setPrompting(true); - } else { - setPrompting(false); - } - - this.text.setText(text); - } - - private final String TEXTFIELD_ID = "field"; - - @Override - public Element getSubPartElement(String subPart) { - if (subPart.equals(TEXTFIELD_ID)) { - return text.getElement(); - } - - return null; - } - - @Override - public String getSubPartName(Element subElement) { - if (text.getElement().isOrHasChild(subElement)) { - return TEXTFIELD_ID; - } - - return null; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java deleted file mode 100644 index a4d00f59de..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Window; -import com.vaadin.shared.ui.dd.HorizontalDropLocation; -import com.vaadin.shared.ui.dd.VerticalDropLocation; -import com.vaadin.terminal.gwt.client.Util; - -public class DDUtil { - - public static VerticalDropLocation getVerticalDropLocation(Element element, - NativeEvent event, double topBottomRatio) { - int offsetHeight = element.getOffsetHeight(); - return getVerticalDropLocation(element, offsetHeight, event, - topBottomRatio); - } - - public static VerticalDropLocation getVerticalDropLocation(Element element, - int offsetHeight, NativeEvent event, double topBottomRatio) { - int clientY = Util.getTouchOrMouseClientY(event); - return getVerticalDropLocation(element, offsetHeight, clientY, - topBottomRatio); - } - - public static VerticalDropLocation getVerticalDropLocation(Element element, - int offsetHeight, int clientY, double topBottomRatio) { - - // Event coordinates are relative to the viewport, element absolute - // position is relative to the document. Make element position relative - // to viewport by adjusting for viewport scrolling. See #6021 - int elementTop = element.getAbsoluteTop() - Window.getScrollTop(); - int fromTop = clientY - elementTop; - - float percentageFromTop = (fromTop / (float) offsetHeight); - if (percentageFromTop < topBottomRatio) { - return VerticalDropLocation.TOP; - } else if (percentageFromTop > 1 - topBottomRatio) { - return VerticalDropLocation.BOTTOM; - } else { - return VerticalDropLocation.MIDDLE; - } - } - - public static HorizontalDropLocation getHorizontalDropLocation( - Element element, NativeEvent event, double leftRightRatio) { - int clientX = Util.getTouchOrMouseClientX(event); - - // Event coordinates are relative to the viewport, element absolute - // position is relative to the document. Make element position relative - // to viewport by adjusting for viewport scrolling. See #6021 - int elementLeft = element.getAbsoluteLeft() - Window.getScrollLeft(); - int offsetWidth = element.getOffsetWidth(); - int fromLeft = clientX - elementLeft; - - float percentageFromLeft = (fromLeft / (float) offsetWidth); - if (percentageFromLeft < leftRightRatio) { - return HorizontalDropLocation.LEFT; - } else if (percentageFromLeft > 1 - leftRightRatio) { - return HorizontalDropLocation.RIGHT; - } else { - return HorizontalDropLocation.CENTER; - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAbstractDropHandler.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAbstractDropHandler.java deleted file mode 100644 index bf0ab24c32..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAbstractDropHandler.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import java.util.Iterator; - -import com.google.gwt.user.client.Command; -import com.vaadin.event.Transferable; -import com.vaadin.event.dd.DropTarget; -import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.UIDL; - -public abstract class VAbstractDropHandler implements VDropHandler { - - private UIDL criterioUIDL; - private VAcceptCriterion acceptCriteria = new VAcceptAll(); - - /** - * Implementor/user of {@link VAbstractDropHandler} must pass the UIDL - * painted by {@link AcceptCriterion} to this method. Practically the - * details about {@link AcceptCriterion} are saved. - * - * @param uidl - */ - public void updateAcceptRules(UIDL uidl) { - criterioUIDL = uidl; - /* - * supports updating the accept rule root directly or so that it is - * contained in given uidl node - */ - if (!uidl.getTag().equals("-ac")) { - Iterator<Object> childIterator = uidl.getChildIterator(); - while (!uidl.getTag().equals("-ac") && childIterator.hasNext()) { - uidl = (UIDL) childIterator.next(); - } - } - acceptCriteria = VAcceptCriteria.get(uidl.getStringAttribute("name")); - if (acceptCriteria == null) { - throw new IllegalArgumentException( - "No accept criteria found with given name " - + uidl.getStringAttribute("name")); - } - } - - /** - * Default implementation does nothing. - */ - @Override - public void dragOver(VDragEvent drag) { - - } - - /** - * Default implementation does nothing. Implementors should clean possible - * emphasis or drag icons here. - */ - @Override - public void dragLeave(VDragEvent drag) { - - } - - /** - * The default implementation in {@link VAbstractDropHandler} checks if the - * Transferable is accepted. - * <p> - * If transferable is accepted (either via server visit or client side - * rules) the default implementation calls abstract - * {@link #dragAccepted(VDragEvent)} method. - * <p> - * If drop handler has distinct places where some parts may accept the - * {@link Transferable} and others don't, one should use similar validation - * logic in dragOver method and replace this method with empty - * implementation. - * - */ - @Override - public void dragEnter(final VDragEvent drag) { - validate(new VAcceptCallback() { - @Override - public void accepted(VDragEvent event) { - dragAccepted(drag); - } - }, drag); - } - - /** - * This method is called when a valid drop location was found with - * {@link AcceptCriterion} either via client or server side check. - * <p> - * Implementations can set some hints for users here to highlight that the - * drag is on a valid drop location. - * - * @param drag - */ - abstract protected void dragAccepted(VDragEvent drag); - - protected void validate(final VAcceptCallback cb, final VDragEvent event) { - Command checkCriteria = new Command() { - @Override - public void execute() { - acceptCriteria.accept(event, criterioUIDL, cb); - } - }; - - VDragAndDropManager.get().executeWhenReady(checkCriteria); - } - - boolean validated = false; - - /** - * The default implemmentation visits server if {@link AcceptCriterion} - * can't be verified on client or if {@link AcceptCriterion} are met on - * client. - */ - @Override - public boolean drop(VDragEvent drag) { - if (acceptCriteria.needsServerSideCheck(drag, criterioUIDL)) { - return true; - } else { - validated = false; - acceptCriteria.accept(drag, criterioUIDL, new VAcceptCallback() { - @Override - public void accepted(VDragEvent event) { - validated = true; - } - }); - return validated; - } - - } - - /** - * Returns the Paintable who owns this {@link VAbstractDropHandler}. Server - * side counterpart of the Paintable is expected to implement - * {@link DropTarget} interface. - */ - @Override - public abstract ComponentConnector getConnector(); - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptAll.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptAll.java deleted file mode 100644 index 661e47c506..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptAll.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.event.dd.acceptcriteria.AcceptAll; -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.terminal.gwt.client.UIDL; - -@AcceptCriterion(AcceptAll.class) -final public class VAcceptAll extends VAcceptCriterion { - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - return true; - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptCallback.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptCallback.java deleted file mode 100644 index a8b3518406..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptCallback.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -public interface VAcceptCallback { - - /** - * This method is called by {@link VDragAndDropManager} if the - * {@link VDragEvent} is still active. Developer can update for example drag - * icon or empahsis the target if the target accepts the transferable. If - * the drag and drop operation ends or the {@link VAbstractDropHandler} has - * changed before response arrives, the method is never called. - */ - public void accepted(VDragEvent event); - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptCriteria.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptCriteria.java deleted file mode 100644 index 05330c2187..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptCriteria.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.google.gwt.core.client.GWT; - -/** - * A class via all AcceptCriteria instances are fetched by an identifier. - */ -public class VAcceptCriteria { - private static VAcceptCriterionFactory impl; - - static { - impl = GWT.create(VAcceptCriterionFactory.class); - } - - public static VAcceptCriterion get(String name) { - return impl.get(name); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptCriterion.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptCriterion.java deleted file mode 100644 index 6d3bda9676..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptCriterion.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.terminal.gwt.client.UIDL; - -public abstract class VAcceptCriterion { - - /** - * Checks if current drag event has valid drop target and target accepts the - * transferable. If drop target is valid, callback is used. - * - * @param drag - * @param configuration - * @param callback - */ - public void accept(final VDragEvent drag, UIDL configuration, - final VAcceptCallback callback) { - if (needsServerSideCheck(drag, configuration)) { - VDragEventServerCallback acceptCallback = new VDragEventServerCallback() { - @Override - public void handleResponse(boolean accepted, UIDL response) { - if (accepted) { - callback.accepted(drag); - } - } - }; - VDragAndDropManager.get().visitServer(acceptCallback); - } else { - boolean validates = accept(drag, configuration); - if (validates) { - callback.accepted(drag); - } - } - - } - - protected abstract boolean accept(VDragEvent drag, UIDL configuration); - - public boolean needsServerSideCheck(VDragEvent drag, UIDL criterioUIDL) { - return false; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptCriterionFactory.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptCriterionFactory.java deleted file mode 100644 index a0ff9ecfdf..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptCriterionFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -/** - * Generated by - * {@link com.vaadin.terminal.gwt.widgetsetutils.AcceptCriteriaFactoryGenerator} - */ -public abstract class VAcceptCriterionFactory { - - public abstract VAcceptCriterion get(String name); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAnd.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAnd.java deleted file mode 100644 index 8eb72712ef..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VAnd.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.event.dd.acceptcriteria.And; -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.terminal.gwt.client.UIDL; - -@AcceptCriterion(And.class) -final public class VAnd extends VAcceptCriterion implements VAcceptCallback { - private boolean b1; - - static VAcceptCriterion getCriteria(VDragEvent drag, UIDL configuration, - int i) { - UIDL childUIDL = configuration.getChildUIDL(i); - return VAcceptCriteria.get(childUIDL.getStringAttribute("name")); - } - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - int childCount = configuration.getChildCount(); - for (int i = 0; i < childCount; i++) { - VAcceptCriterion crit = getCriteria(drag, configuration, i); - b1 = false; - crit.accept(drag, configuration.getChildUIDL(i), this); - if (!b1) { - return false; - } - } - return true; - } - - @Override - public void accepted(VDragEvent event) { - b1 = true; - } - -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VContainsDataFlavor.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VContainsDataFlavor.java deleted file mode 100644 index f06aa7eb15..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VContainsDataFlavor.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.event.dd.acceptcriteria.ContainsDataFlavor; -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.terminal.gwt.client.UIDL; - -@AcceptCriterion(ContainsDataFlavor.class) -final public class VContainsDataFlavor extends VAcceptCriterion { - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - String name = configuration.getStringAttribute("p"); - return drag.getTransferable().getDataFlavors().contains(name); - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VDragAndDropManager.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VDragAndDropManager.java deleted file mode 100644 index 82592d1846..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VDragAndDropManager.java +++ /dev/null @@ -1,752 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.RepeatingCommand; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.EventTarget; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.dom.client.Node; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Display; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Event.NativePreviewEvent; -import com.google.gwt.user.client.Event.NativePreviewHandler; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ApplicationConstants; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.dd.DragEventType; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ValueMap; - -/** - * Helper class to manage the state of drag and drop event on Vaadin client - * side. Can be used to implement most of the drag and drop operation - * automatically via cross-browser event preview method or just as a helper when - * implementing own low level drag and drop operation (like with HTML5 api). - * <p> - * Singleton. Only one drag and drop operation can be active anyways. Use - * {@link #get()} to get instance. - * - * TODO cancel drag and drop if more than one touches !? - */ -public class VDragAndDropManager { - - public static final String ACTIVE_DRAG_SOURCE_STYLENAME = "v-active-drag-source"; - - private final class DefaultDragAndDropEventHandler implements - NativePreviewHandler { - - @Override - public void onPreviewNativeEvent(NativePreviewEvent event) { - NativeEvent nativeEvent = event.getNativeEvent(); - - int typeInt = event.getTypeInt(); - if (typeInt == Event.ONKEYDOWN) { - int keyCode = event.getNativeEvent().getKeyCode(); - if (keyCode == KeyCodes.KEY_ESCAPE) { - // end drag if ESC is hit - interruptDrag(); - event.cancel(); - event.getNativeEvent().preventDefault(); - } - // no use for handling for any key down event - return; - } - - currentDrag.setCurrentGwtEvent(nativeEvent); - updateDragImagePosition(); - - Element targetElement = Element.as(nativeEvent.getEventTarget()); - if (Util.isTouchEvent(nativeEvent) - || (dragElement != null && dragElement - .isOrHasChild(targetElement))) { - // to detect the "real" target, hide dragelement temporary and - // use elementFromPoint - String display = dragElement.getStyle().getDisplay(); - dragElement.getStyle().setDisplay(Display.NONE); - try { - int x = Util.getTouchOrMouseClientX(nativeEvent); - int y = Util.getTouchOrMouseClientY(nativeEvent); - // Util.browserDebugger(); - targetElement = Util.getElementFromPoint(x, y); - if (targetElement == null) { - // ApplicationConnection.getConsole().log( - // "Event on dragImage, ignored"); - event.cancel(); - nativeEvent.stopPropagation(); - return; - - } else { - // ApplicationConnection.getConsole().log( - // "Event on dragImage, target changed"); - // special handling for events over dragImage - // pretty much all events are mousemove althout below - // kind of happens mouseover - switch (typeInt) { - case Event.ONMOUSEOVER: - case Event.ONMOUSEOUT: - // ApplicationConnection - // .getConsole() - // .log( - // "IGNORING proxy image event, fired because of hack or not significant"); - return; - case Event.ONMOUSEMOVE: - case Event.ONTOUCHMOVE: - VDropHandler findDragTarget = findDragTarget(targetElement); - if (findDragTarget != currentDropHandler) { - // dragleave on old - if (currentDropHandler != null) { - currentDropHandler.dragLeave(currentDrag); - currentDrag.getDropDetails().clear(); - serverCallback = null; - } - // dragenter on new - currentDropHandler = findDragTarget; - if (findDragTarget != null) { - // ApplicationConnection.getConsole().log( - // "DropHandler now" - // + currentDropHandler - // .getPaintable()); - } - - if (currentDropHandler != null) { - currentDrag - .setElementOver((com.google.gwt.user.client.Element) targetElement); - currentDropHandler.dragEnter(currentDrag); - } - } else if (findDragTarget != null) { - currentDrag - .setElementOver((com.google.gwt.user.client.Element) targetElement); - currentDropHandler.dragOver(currentDrag); - } - // prevent text selection on IE - nativeEvent.preventDefault(); - return; - default: - // just update element over and let the actual - // handling code do the thing - // ApplicationConnection.getConsole().log( - // "Target just modified on " - // + event.getType()); - currentDrag - .setElementOver((com.google.gwt.user.client.Element) targetElement); - break; - } - - } - } catch (RuntimeException e) { - // ApplicationConnection.getConsole().log( - // "ERROR during elementFromPoint hack."); - throw e; - } finally { - dragElement.getStyle().setProperty("display", display); - } - } - - switch (typeInt) { - case Event.ONMOUSEOVER: - VDropHandler target = findDragTarget(targetElement); - - if (target != null && target != currentDropHandler) { - if (currentDropHandler != null) { - currentDropHandler.dragLeave(currentDrag); - currentDrag.getDropDetails().clear(); - } - - currentDropHandler = target; - // ApplicationConnection.getConsole().log( - // "DropHandler now" - // + currentDropHandler.getPaintable()); - currentDrag - .setElementOver((com.google.gwt.user.client.Element) targetElement); - target.dragEnter(currentDrag); - } else if (target == null && currentDropHandler != null) { - // ApplicationConnection.getConsole().log("Invalid state!?"); - currentDropHandler.dragLeave(currentDrag); - currentDrag.getDropDetails().clear(); - currentDropHandler = null; - } - break; - case Event.ONMOUSEOUT: - Element relatedTarget = Element.as(nativeEvent - .getRelatedEventTarget()); - VDropHandler newDragHanler = findDragTarget(relatedTarget); - if (dragElement != null - && dragElement.isOrHasChild(relatedTarget)) { - // ApplicationConnection.getConsole().log( - // "Mouse out of dragImage, ignored"); - return; - } - - if (currentDropHandler != null - && currentDropHandler != newDragHanler) { - currentDropHandler.dragLeave(currentDrag); - currentDrag.getDropDetails().clear(); - currentDropHandler = null; - serverCallback = null; - } - break; - case Event.ONMOUSEMOVE: - case Event.ONTOUCHMOVE: - if (currentDropHandler != null) { - currentDrag - .setElementOver((com.google.gwt.user.client.Element) targetElement); - currentDropHandler.dragOver(currentDrag); - } - nativeEvent.preventDefault(); - - break; - - case Event.ONTOUCHEND: - /* Avoid simulated event on drag end */ - event.getNativeEvent().preventDefault(); - case Event.ONMOUSEUP: - endDrag(); - break; - - default: - break; - } - - } - - } - - private static VDragAndDropManager instance; - private HandlerRegistration handlerRegistration; - private VDragEvent currentDrag; - - /** - * If dragging is currently on a drophandler, this field has reference to it - */ - private VDropHandler currentDropHandler; - - public VDropHandler getCurrentDropHandler() { - return currentDropHandler; - } - - /** - * If drag and drop operation is not handled by {@link VDragAndDropManager}s - * internal handler, this can be used to update current {@link VDropHandler} - * . - * - * @param currentDropHandler - */ - public void setCurrentDropHandler(VDropHandler currentDropHandler) { - this.currentDropHandler = currentDropHandler; - } - - private VDragEventServerCallback serverCallback; - - private HandlerRegistration deferredStartRegistration; - - public static VDragAndDropManager get() { - if (instance == null) { - instance = GWT.create(VDragAndDropManager.class); - } - return instance; - } - - /* Singleton */ - private VDragAndDropManager() { - } - - private NativePreviewHandler defaultDragAndDropEventHandler = new DefaultDragAndDropEventHandler(); - - /** - * Flag to indicate if drag operation has really started or not. Null check - * of currentDrag field is not enough as a lazy start may be pending. - */ - private boolean isStarted; - - /** - * This method is used to start Vaadin client side drag and drop operation. - * Operation may be started by virtually any Widget. - * <p> - * Cancels possible existing drag. TODO figure out if this is always a bug - * if one is active. Maybe a good and cheap lifesaver thought. - * <p> - * If possible, method automatically detects current {@link VDropHandler} - * and fires {@link VDropHandler#dragEnter(VDragEvent)} event on it. - * <p> - * May also be used to control the drag and drop operation. If this option - * is used, {@link VDropHandler} is searched on mouse events and appropriate - * methods on it called automatically. - * - * @param transferable - * @param nativeEvent - * @param handleDragEvents - * if true, {@link VDragAndDropManager} handles the drag and drop - * operation GWT event preview. - * @return - */ - public VDragEvent startDrag(VTransferable transferable, - final NativeEvent startEvent, final boolean handleDragEvents) { - interruptDrag(); - isStarted = false; - - currentDrag = new VDragEvent(transferable, startEvent); - currentDrag.setCurrentGwtEvent(startEvent); - - final Command startDrag = new Command() { - - @Override - public void execute() { - isStarted = true; - addActiveDragSourceStyleName(); - VDropHandler dh = null; - if (startEvent != null) { - dh = findDragTarget(Element.as(currentDrag - .getCurrentGwtEvent().getEventTarget())); - } - if (dh != null) { - // drag has started on a DropHandler, kind of drag over - // happens - currentDropHandler = dh; - dh.dragEnter(currentDrag); - } - - if (handleDragEvents) { - handlerRegistration = Event - .addNativePreviewHandler(defaultDragAndDropEventHandler); - if (dragElement != null - && dragElement.getParentElement() == null) { - // deferred attaching drag image is on going, we can - // hurry with it now - lazyAttachDragElement.cancel(); - lazyAttachDragElement.run(); - } - } - // just capture something to prevent text selection in IE - Event.setCapture(RootPanel.getBodyElement()); - } - - private void addActiveDragSourceStyleName() { - ComponentConnector dragSource = currentDrag.getTransferable() - .getDragSource(); - dragSource.getWidget().addStyleName( - ACTIVE_DRAG_SOURCE_STYLENAME); - } - }; - - final int eventType = Event.as(startEvent).getTypeInt(); - if (handleDragEvents - && (eventType == Event.ONMOUSEDOWN || eventType == Event.ONTOUCHSTART)) { - // only really start drag event on mousemove - deferredStartRegistration = Event - .addNativePreviewHandler(new NativePreviewHandler() { - - @Override - public void onPreviewNativeEvent( - NativePreviewEvent event) { - int typeInt = event.getTypeInt(); - switch (typeInt) { - case Event.ONMOUSEOVER: - if (dragElement == null) { - break; - } - EventTarget currentEventTarget = event - .getNativeEvent() - .getCurrentEventTarget(); - if (Node.is(currentEventTarget) - && !dragElement.isOrHasChild(Node - .as(currentEventTarget))) { - // drag image appeared below, ignore - break; - } - case Event.ONKEYDOWN: - case Event.ONKEYPRESS: - case Event.ONKEYUP: - case Event.ONBLUR: - case Event.ONFOCUS: - // don't cancel possible drag start - break; - case Event.ONMOUSEOUT: - - if (dragElement == null) { - break; - } - EventTarget relatedEventTarget = event - .getNativeEvent() - .getRelatedEventTarget(); - if (Node.is(relatedEventTarget) - && !dragElement.isOrHasChild(Node - .as(relatedEventTarget))) { - // drag image appeared below, ignore - break; - } - case Event.ONMOUSEMOVE: - case Event.ONTOUCHMOVE: - if (deferredStartRegistration != null) { - deferredStartRegistration.removeHandler(); - deferredStartRegistration = null; - } - currentDrag.setCurrentGwtEvent(event - .getNativeEvent()); - startDrag.execute(); - break; - default: - // on any other events, clean up the - // deferred drag start - if (deferredStartRegistration != null) { - deferredStartRegistration.removeHandler(); - deferredStartRegistration = null; - } - currentDrag = null; - clearDragElement(); - break; - } - } - - }); - - } else { - startDrag.execute(); - } - - return currentDrag; - } - - private void updateDragImagePosition() { - if (currentDrag.getCurrentGwtEvent() != null && dragElement != null) { - Style style = dragElement.getStyle(); - int clientY = Util.getTouchOrMouseClientY(currentDrag - .getCurrentGwtEvent()); - int clientX = Util.getTouchOrMouseClientX(currentDrag - .getCurrentGwtEvent()); - style.setTop(clientY, Unit.PX); - style.setLeft(clientX, Unit.PX); - } - } - - /** - * First seeks the widget from this element, then iterates widgets until one - * implement HasDropHandler. Returns DropHandler from that. - * - * @param element - * @return - */ - private VDropHandler findDragTarget(Element element) { - try { - Widget w = Util.findWidget( - (com.google.gwt.user.client.Element) element, null); - if (w == null) { - return null; - } - while (!(w instanceof VHasDropHandler)) { - w = w.getParent(); - if (w == null) { - break; - } - } - if (w == null) { - return null; - } else { - VDropHandler dh = ((VHasDropHandler) w).getDropHandler(); - return dh; - } - - } catch (Exception e) { - // ApplicationConnection.getConsole().log( - // "FIXME: Exception when detecting drop handler"); - // e.printStackTrace(); - return null; - } - - } - - /** - * Drag is ended (drop happened) on current drop handler. Calls drop method - * on current drop handler and does appropriate cleanup. - */ - public void endDrag() { - endDrag(true); - } - - /** - * The drag and drop operation is ended, but drop did not happen. If - * operation is currently on a drop handler, its dragLeave method is called - * and appropriate cleanup happens. - */ - public void interruptDrag() { - endDrag(false); - } - - private void endDrag(boolean doDrop) { - if (handlerRegistration != null) { - handlerRegistration.removeHandler(); - handlerRegistration = null; - } - boolean sendTransferableToServer = false; - if (currentDropHandler != null) { - if (doDrop) { - // we have dropped on a drop target - sendTransferableToServer = currentDropHandler.drop(currentDrag); - if (sendTransferableToServer) { - doRequest(DragEventType.DROP); - /* - * Clean active source class name deferred until response is - * handled. E.g. hidden on start, removed in drophandler -> - * would flicker in case removed eagerly. - */ - final ComponentConnector dragSource = currentDrag - .getTransferable().getDragSource(); - final ApplicationConnection client = currentDropHandler - .getApplicationConnection(); - Scheduler.get().scheduleFixedDelay(new RepeatingCommand() { - @Override - public boolean execute() { - if (!client.hasActiveRequest()) { - removeActiveDragSourceStyleName(dragSource); - return false; - } - return true; - } - - }, 30); - - } - } else { - currentDrag.setCurrentGwtEvent(null); - currentDropHandler.dragLeave(currentDrag); - } - currentDropHandler = null; - serverCallback = null; - visitId = 0; // reset to ignore ongoing server check - } - - /* - * Remove class name indicating drag source when server visit is done - * iff server visit was not initiated. Otherwise it will be removed once - * the server visit is done. - */ - if (!sendTransferableToServer && currentDrag != null) { - removeActiveDragSourceStyleName(currentDrag.getTransferable() - .getDragSource()); - } - - currentDrag = null; - - clearDragElement(); - - // release the capture (set to prevent text selection in IE) - Event.releaseCapture(RootPanel.getBodyElement()); - - } - - private void removeActiveDragSourceStyleName(ComponentConnector dragSource) { - dragSource.getWidget().removeStyleName(ACTIVE_DRAG_SOURCE_STYLENAME); - } - - private void clearDragElement() { - if (dragElement != null) { - if (dragElement.getParentElement() != null) { - RootPanel.getBodyElement().removeChild(dragElement); - } - dragElement = null; - } - } - - private int visitId = 0; - private Element dragElement; - - /** - * Visits server during drag and drop procedure. Transferable and event type - * is given to server side counterpart of DropHandler. - * - * If another server visit is started before the current is received, the - * current is just dropped. TODO consider if callback should have - * interrupted() method for cleanup. - * - * @param acceptCallback - */ - public void visitServer(VDragEventServerCallback acceptCallback) { - doRequest(DragEventType.ENTER); - serverCallback = acceptCallback; - } - - private void doRequest(DragEventType drop) { - if (currentDropHandler == null) { - return; - } - ComponentConnector paintable = currentDropHandler.getConnector(); - ApplicationConnection client = currentDropHandler - .getApplicationConnection(); - /* - * For drag events we are using special id that are routed to - * "drag service" which then again finds the corresponding DropHandler - * on server side. - * - * TODO add rest of the data in Transferable - * - * TODO implement partial updates to Transferable (currently the whole - * Transferable is sent on each request) - */ - visitId++; - client.updateVariable(ApplicationConstants.DRAG_AND_DROP_CONNECTOR_ID, - "visitId", visitId, false); - client.updateVariable(ApplicationConstants.DRAG_AND_DROP_CONNECTOR_ID, - "eventId", currentDrag.getEventId(), false); - client.updateVariable(ApplicationConstants.DRAG_AND_DROP_CONNECTOR_ID, - "dhowner", paintable, false); - - VTransferable transferable = currentDrag.getTransferable(); - - client.updateVariable(ApplicationConstants.DRAG_AND_DROP_CONNECTOR_ID, - "component", transferable.getDragSource(), false); - - client.updateVariable(ApplicationConstants.DRAG_AND_DROP_CONNECTOR_ID, - "type", drop.ordinal(), false); - - if (currentDrag.getCurrentGwtEvent() != null) { - try { - MouseEventDetails mouseEventDetails = MouseEventDetailsBuilder - .buildMouseEventDetails(currentDrag - .getCurrentGwtEvent()); - currentDrag.getDropDetails().put("mouseEvent", - mouseEventDetails.serialize()); - } catch (Exception e) { - // NOP, (at least oophm on Safari) can't serialize html dd event - // to mouseevent - } - } else { - currentDrag.getDropDetails().put("mouseEvent", null); - } - client.updateVariable(ApplicationConstants.DRAG_AND_DROP_CONNECTOR_ID, - "evt", currentDrag.getDropDetails(), false); - - client.updateVariable(ApplicationConstants.DRAG_AND_DROP_CONNECTOR_ID, - "tra", transferable.getVariableMap(), true); - - } - - public void handleServerResponse(ValueMap valueMap) { - if (serverCallback == null) { - return; - } - UIDL uidl = (UIDL) valueMap.cast(); - int visitId = uidl.getIntAttribute("visitId"); - - if (this.visitId == visitId) { - serverCallback.handleResponse(uidl.getBooleanAttribute("accepted"), - uidl); - serverCallback = null; - } - runDeferredCommands(); - } - - private void runDeferredCommands() { - if (deferredCommand != null) { - Command command = deferredCommand; - deferredCommand = null; - command.execute(); - if (!isBusy()) { - runDeferredCommands(); - } - } - } - - void setDragElement(Element node) { - if (currentDrag != null) { - if (dragElement != null && dragElement != node) { - clearDragElement(); - } else if (node == dragElement) { - return; - } - - dragElement = node; - dragElement.addClassName("v-drag-element"); - updateDragImagePosition(); - - if (isStarted) { - lazyAttachDragElement.run(); - } else { - /* - * To make our default dnd handler as compatible as possible, we - * need to defer the appearance of dragElement. Otherwise events - * that are derived from sequences of other events might not - * fire as domchanged will fire between them or mouse up might - * happen on dragElement. - */ - lazyAttachDragElement.schedule(300); - } - } - } - - Element getDragElement() { - return dragElement; - } - - private final Timer lazyAttachDragElement = new Timer() { - - @Override - public void run() { - if (dragElement != null && dragElement.getParentElement() == null) { - RootPanel.getBodyElement().appendChild(dragElement); - } - - } - }; - - private Command deferredCommand; - - private boolean isBusy() { - return serverCallback != null; - } - - /** - * Method to que tasks until all dd related server visits are done - * - * @param command - */ - private void defer(Command command) { - deferredCommand = command; - } - - /** - * Method to execute commands when all existing dd related tasks are - * completed (some may require server visit). - * <p> - * Using this method may be handy if criterion that uses lazy initialization - * are used. Check - * <p> - * TODO Optimization: consider if we actually only need to keep the last - * command in queue here. - * - * @param command - */ - public void executeWhenReady(Command command) { - if (isBusy()) { - defer(command); - } else { - command.execute(); - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VDragEvent.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VDragEvent.java deleted file mode 100644 index 7b3950f64f..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VDragEvent.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import java.util.HashMap; -import java.util.Map; - -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.dom.client.TableElement; -import com.google.gwt.dom.client.TableSectionElement; -import com.google.gwt.event.dom.client.MouseOverEvent; -import com.google.gwt.user.client.Element; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.Util; - -/** - * DragEvent used by Vaadin client side engine. Supports components, items, - * properties and custom payload (HTML5 style). - * - * - */ -public class VDragEvent { - - private static final int DEFAULT_OFFSET = 10; - - private static int eventId = 0; - - private VTransferable transferable; - - private NativeEvent currentGwtEvent; - - private NativeEvent startEvent; - - private int id; - - private HashMap<String, Object> dropDetails = new HashMap<String, Object>(); - - private Element elementOver; - - VDragEvent(VTransferable t, NativeEvent startEvent) { - transferable = t; - this.startEvent = startEvent; - id = eventId++; - } - - public VTransferable getTransferable() { - return transferable; - } - - /** - * Returns the the latest {@link NativeEvent} that relates to this drag and - * drop operation. For example on {@link VDropHandler#dragEnter(VDragEvent)} - * this is commonly a {@link MouseOverEvent}. - * - * @return - */ - public NativeEvent getCurrentGwtEvent() { - return currentGwtEvent; - } - - public void setCurrentGwtEvent(NativeEvent event) { - currentGwtEvent = event; - } - - int getEventId() { - return id; - } - - /** - * Detecting the element on which the the event is happening may be - * problematic during drag and drop operation. This is especially the case - * if a drag image (often called also drag proxy) is kept under the mouse - * cursor (see {@link #createDragImage(Element, boolean)}. Drag and drop - * event handlers (like the one provided by {@link VDragAndDropManager} ) - * should set elmentOver field to reflect the the actual element on which - * the pointer currently is (drag image excluded). {@link VDropHandler}s can - * then more easily react properly on drag events by reading the element via - * this method. - * - * @return the element in {@link VDropHandler} on which mouse cursor is on - */ - public Element getElementOver() { - if (elementOver != null) { - return elementOver; - } else if (currentGwtEvent != null) { - return currentGwtEvent.getEventTarget().cast(); - } - return null; - } - - public void setElementOver(Element targetElement) { - elementOver = targetElement; - } - - /** - * Sets the drag image used for current drag and drop operation. Drag image - * is displayed next to mouse cursor during drag and drop. - * <p> - * The element to be used as drag image will automatically get CSS style - * name "v-drag-element". - * - * TODO decide if this method should be here or in {@link VTransferable} (in - * HTML5 it is in DataTransfer) or {@link VDragAndDropManager} - * - * TODO should be possible to override behavior. Like to proxy the element - * to HTML5 DataTransfer - * - * @param node - */ - public void setDragImage(Element node) { - setDragImage(node, DEFAULT_OFFSET, DEFAULT_OFFSET); - } - - /** - * TODO consider using similar smaller (than map) api as in Transferable - * - * TODO clean up when drop handler changes - * - * @return - */ - public Map<String, Object> getDropDetails() { - return dropDetails; - } - - /** - * Sets the drag image used for current drag and drop operation. Drag image - * is displayed next to mouse cursor during drag and drop. - * <p> - * The element to be used as drag image will automatically get CSS style - * name "v-drag-element". - * - * @param element - * the dom element to be positioned next to mouse cursor - * @param offsetX - * the horizontal offset of drag image from mouse cursor - * @param offsetY - * the vertical offset of drag image from mouse cursor - */ - public void setDragImage(Element element, int offsetX, int offsetY) { - element.getStyle().setMarginLeft(offsetX, Unit.PX); - element.getStyle().setMarginTop(offsetY, Unit.PX); - VDragAndDropManager.get().setDragElement(element); - } - - /** - * @return the current Element used as a drag image (aka drag proxy) or null - * if drag image is not currently set for this drag operation. - */ - public Element getDragImage() { - return (Element) VDragAndDropManager.get().getDragElement(); - } - - /** - * Automatically tries to create a proxy image from given element. - * - * @param element - * @param alignImageToEvent - * if true, proxy image is aligned to start event, else next to - * mouse cursor - */ - public void createDragImage(Element element, boolean alignImageToEvent) { - Element cloneNode = (Element) element.cloneNode(true); - if (BrowserInfo.get().isIE()) { - if (cloneNode.getTagName().toLowerCase().equals("tr")) { - TableElement table = Document.get().createTableElement(); - TableSectionElement tbody = Document.get().createTBodyElement(); - table.appendChild(tbody); - tbody.appendChild(cloneNode); - cloneNode = table.cast(); - } - } - if (alignImageToEvent) { - int absoluteTop = element.getAbsoluteTop(); - int absoluteLeft = element.getAbsoluteLeft(); - int clientX = Util.getTouchOrMouseClientX(startEvent); - int clientY = Util.getTouchOrMouseClientY(startEvent); - int offsetX = absoluteLeft - clientX; - int offsetY = absoluteTop - clientY; - setDragImage(cloneNode, offsetX, offsetY); - } else { - setDragImage(cloneNode); - } - - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VDragEventServerCallback.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VDragEventServerCallback.java deleted file mode 100644 index 00fe2d2659..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VDragEventServerCallback.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.terminal.gwt.client.UIDL; - -public interface VDragEventServerCallback { - - public void handleResponse(boolean accepted, UIDL response); - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VDragSourceIs.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VDragSourceIs.java deleted file mode 100644 index e812ca8117..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VDragSourceIs.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.event.dd.acceptcriteria.SourceIs; -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.UIDL; - -/** - * TODO Javadoc! - * - * @since 6.3 - */ -@AcceptCriterion(SourceIs.class) -final public class VDragSourceIs extends VAcceptCriterion { - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - try { - ComponentConnector component = drag.getTransferable() - .getDragSource(); - int c = configuration.getIntAttribute("c"); - for (int i = 0; i < c; i++) { - String requiredPid = configuration - .getStringAttribute("component" + i); - VDropHandler currentDropHandler = VDragAndDropManager.get() - .getCurrentDropHandler(); - ComponentConnector paintable = (ComponentConnector) ConnectorMap - .get(currentDropHandler.getApplicationConnection()) - .getConnector(requiredPid); - if (paintable == component) { - return true; - } - } - } catch (Exception e) { - } - return false; - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VDropHandler.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VDropHandler.java deleted file mode 100644 index ddc3af9931..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VDropHandler.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ComponentConnector; - -/** - * Vaadin Widgets that want to receive something via drag and drop implement - * this interface. - */ -public interface VDropHandler { - - /** - * Called by DragAndDropManager when a drag operation is in progress and the - * cursor enters the area occupied by this Paintable. - * - * @param dragEvent - * DragEvent which contains the transferable and other - * information for the operation - */ - public void dragEnter(VDragEvent dragEvent); - - /** - * Called by DragAndDropManager when a drag operation is in progress and the - * cursor leaves the area occupied by this Paintable. - * - * @param dragEvent - * DragEvent which contains the transferable and other - * information for the operation - */ - public void dragLeave(VDragEvent dragEvent); - - /** - * Called by DragAndDropManager when a drag operation was in progress and a - * drop was performed on this Paintable. - * - * - * @param dragEvent - * DragEvent which contains the transferable and other - * information for the operation - * - * @return true if the Tranferrable of this drag event needs to be sent to - * the server, false if drop is rejected or no server side event - * should be sent - */ - public boolean drop(VDragEvent drag); - - /** - * When drag is over current drag handler. - * - * With drag implementation by {@link VDragAndDropManager} will be called - * when mouse is moved. HTML5 implementations call this continuously even - * though mouse is not moved. - * - * @param currentDrag - */ - public void dragOver(VDragEvent currentDrag); - - /** - * Returns the ComponentConnector with which this DropHandler is associated - */ - public ComponentConnector getConnector(); - - /** - * Returns the application connection to which this {@link VDropHandler} - * belongs to. DragAndDropManager uses this fucction to send Transferable to - * server side. - */ - public ApplicationConnection getApplicationConnection(); - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VHasDropHandler.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VHasDropHandler.java deleted file mode 100644 index 01c57741d8..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VHasDropHandler.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.terminal.gwt.client.ComponentConnector; - -/** - * Used to detect Widget from widget tree that has {@link #getDropHandler()} - * - * Decide whether to get rid of this class. If so, {@link VAbstractDropHandler} - * must extend {@link ComponentConnector}. - * - */ -public interface VHasDropHandler { - public VDropHandler getDropHandler(); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent.java deleted file mode 100644 index 34bdb28c91..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.google.gwt.core.client.JsArrayString; -import com.google.gwt.dom.client.NativeEvent; - -/** - * Helper class to access html5 style drag events. - * - * TODO Gears support ? - */ -public class VHtml5DragEvent extends NativeEvent { - protected VHtml5DragEvent() { - } - - public final native JsArrayString getTypes() - /*-{ - // IE does not support types, return some basic values - return this.dataTransfer.types ? this.dataTransfer.types : ["Text","Url","Html"]; - }-*/; - - public final native String getDataAsText(String type) - /*-{ - var v = this.dataTransfer.getData(type); - return v; - }-*/; - - /** - * Works on FF 3.6 and possibly with gears. - * - * @param index - * @return - */ - public final native String getFileAsString(int index) - /*-{ - if(this.dataTransfer.files.length > 0 && this.dataTransfer.files[0].getAsText) { - return this.dataTransfer.files[index].getAsText("UTF-8"); - } - return null; - }-*/; - - public final native void setDropEffect(String effect) - /*-{ - try { - this.dataTransfer.dropEffect = effect; - } catch (e){} - }-*/; - - public final native String getEffectAllowed() - /*-{ - return this.dataTransfer.effectAllowed; - }-*/; - - public final native void setEffectAllowed(String effect) - /*-{ - this.dataTransfer.effectAllowed = effect; - }-*/; - - public final native int getFileCount() - /*-{ - return this.dataTransfer.files ? this.dataTransfer.files.length : 0; - }-*/; - - public final native VHtml5File getFile(int fileIndex) - /*-{ - return this.dataTransfer.files[fileIndex]; - }-*/; - - public final native void setHtml5DataFlavor(String flavor, String data) - /*-{ - this.dataTransfer.setData(flavor, data); - }-*/; - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VHtml5File.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VHtml5File.java deleted file mode 100644 index 961008c860..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VHtml5File.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.google.gwt.core.client.JavaScriptObject; - -/** - * Wrapper for html5 File object. - */ -public class VHtml5File extends JavaScriptObject { - - protected VHtml5File() { - }; - - public native final String getName() - /*-{ - return this.name; - }-*/; - - public native final String getType() - /*-{ - return this.type; - }-*/; - - public native final int getSize() - /*-{ - return this.size ? this.size : 0; - }-*/; - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VIsOverId.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VIsOverId.java deleted file mode 100644 index c9bf630658..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VIsOverId.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.ui.AbstractSelect; - -@AcceptCriterion(AbstractSelect.TargetItemIs.class) -final public class VIsOverId extends VAcceptCriterion { - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - try { - - String pid = configuration.getStringAttribute("s"); - VDropHandler currentDropHandler = VDragAndDropManager.get() - .getCurrentDropHandler(); - ComponentConnector dropHandlerConnector = currentDropHandler - .getConnector(); - ConnectorMap paintableMap = ConnectorMap.get(currentDropHandler - .getApplicationConnection()); - - String pid2 = dropHandlerConnector.getConnectorId(); - if (pid2.equals(pid)) { - Object searchedId = drag.getDropDetails().get("itemIdOver"); - String[] stringArrayAttribute = configuration - .getStringArrayAttribute("keys"); - for (String string : stringArrayAttribute) { - if (string.equals(searchedId)) { - return true; - } - } - } - } catch (Exception e) { - } - return false; - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VItemIdIs.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VItemIdIs.java deleted file mode 100644 index 4f6aca082b..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VItemIdIs.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.ui.AbstractSelect; - -@AcceptCriterion(AbstractSelect.AcceptItem.class) -final public class VItemIdIs extends VAcceptCriterion { - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - try { - String pid = configuration.getStringAttribute("s"); - ComponentConnector dragSource = drag.getTransferable() - .getDragSource(); - VDropHandler currentDropHandler = VDragAndDropManager.get() - .getCurrentDropHandler(); - String pid2 = dragSource.getConnectorId(); - if (pid2.equals(pid)) { - Object searchedId = drag.getTransferable().getData("itemId"); - String[] stringArrayAttribute = configuration - .getStringArrayAttribute("keys"); - for (String string : stringArrayAttribute) { - if (string.equals(searchedId)) { - return true; - } - } - } - } catch (Exception e) { - } - return false; - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VLazyInitItemIdentifiers.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VLazyInitItemIdentifiers.java deleted file mode 100644 index ad028b7198..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VLazyInitItemIdentifiers.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import java.util.HashSet; - -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.ui.Table; -import com.vaadin.ui.Tree; - -/** - * - */ -public class VLazyInitItemIdentifiers extends VAcceptCriterion { - private boolean loaded = false; - private HashSet<String> hashSet; - private VDragEvent lastDragEvent; - - @AcceptCriterion(Table.TableDropCriterion.class) - final public static class VTableLazyInitItemIdentifiers extends - VLazyInitItemIdentifiers { - // all logic in superclass - } - - @AcceptCriterion(Tree.TreeDropCriterion.class) - final public static class VTreeLazyInitItemIdentifiers extends - VLazyInitItemIdentifiers { - // all logic in superclass - } - - @Override - public void accept(final VDragEvent drag, UIDL configuration, - final VAcceptCallback callback) { - if (lastDragEvent == null || lastDragEvent != drag) { - loaded = false; - lastDragEvent = drag; - } - if (loaded) { - Object object = drag.getDropDetails().get("itemIdOver"); - if (hashSet.contains(object)) { - callback.accepted(drag); - } - } else { - - VDragEventServerCallback acceptCallback = new VDragEventServerCallback() { - - @Override - public void handleResponse(boolean accepted, UIDL response) { - hashSet = new HashSet<String>(); - String[] stringArrayAttribute = response - .getStringArrayAttribute("allowedIds"); - for (int i = 0; i < stringArrayAttribute.length; i++) { - hashSet.add(stringArrayAttribute[i]); - } - loaded = true; - if (accepted) { - callback.accepted(drag); - } - } - }; - - VDragAndDropManager.get().visitServer(acceptCallback); - } - - } - - @Override - public boolean needsServerSideCheck(VDragEvent drag, UIDL criterioUIDL) { - return loaded; - } - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - return false; // not used is this implementation - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VNot.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VNot.java deleted file mode 100644 index 662b1c2da2..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VNot.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.event.dd.acceptcriteria.Not; -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.VConsole; - -/** - * TODO implementation could now be simplified/optimized - * - */ -@AcceptCriterion(Not.class) -final public class VNot extends VAcceptCriterion { - private boolean b1; - private VAcceptCriterion crit1; - - @Override - public void accept(VDragEvent drag, UIDL configuration, - VAcceptCallback callback) { - if (crit1 == null) { - crit1 = getCriteria(drag, configuration, 0); - if (crit1 == null) { - VConsole.log("Not criteria didn't found a child criteria"); - return; - } - } - - b1 = false; - - VAcceptCallback accept1cb = new VAcceptCallback() { - @Override - public void accepted(VDragEvent event) { - b1 = true; - } - }; - - crit1.accept(drag, configuration.getChildUIDL(0), accept1cb); - if (!b1) { - callback.accepted(drag); - } - } - - private VAcceptCriterion getCriteria(VDragEvent drag, UIDL configuration, - int i) { - UIDL childUIDL = configuration.getChildUIDL(i); - return VAcceptCriteria.get(childUIDL.getStringAttribute("name")); - } - - @Override - public boolean needsServerSideCheck(VDragEvent drag, UIDL criterioUIDL) { - return false; // TODO enforce on server side - } - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - return false; // not used - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VOr.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VOr.java deleted file mode 100644 index b51800e31f..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VOr.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.event.dd.acceptcriteria.Or; -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.terminal.gwt.client.UIDL; - -/** - * - */ -@AcceptCriterion(Or.class) -final public class VOr extends VAcceptCriterion implements VAcceptCallback { - private boolean accepted; - - @Override - public void accept(VDragEvent drag, UIDL configuration, - VAcceptCallback callback) { - int childCount = configuration.getChildCount(); - accepted = false; - for (int i = 0; i < childCount; i++) { - VAcceptCriterion crit = VAnd.getCriteria(drag, configuration, i); - crit.accept(drag, configuration.getChildUIDL(i), this); - if (accepted == true) { - callback.accepted(drag); - return; - } - } - } - - @Override - public boolean needsServerSideCheck(VDragEvent drag, UIDL criterioUIDL) { - return false; - } - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - return false; // not used here - } - - @Override - public void accepted(VDragEvent event) { - accepted = true; - } - -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VOverTreeNode.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VOverTreeNode.java deleted file mode 100644 index 77fd89c123..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VOverTreeNode.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.terminal.gwt.client.UIDL; - -final public class VOverTreeNode extends VAcceptCriterion { - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - Boolean containsKey = (Boolean) drag.getDropDetails().get( - "itemIdOverIsNode"); - return containsKey != null && containsKey.booleanValue(); - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VServerAccept.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VServerAccept.java deleted file mode 100644 index eee0f47a91..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VServerAccept.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion; -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.terminal.gwt.client.UIDL; - -@AcceptCriterion(ServerSideCriterion.class) -final public class VServerAccept extends VAcceptCriterion { - @Override - public void accept(final VDragEvent drag, UIDL configuration, - final VAcceptCallback callback) { - - VDragEventServerCallback acceptCallback = new VDragEventServerCallback() { - @Override - public void handleResponse(boolean accepted, UIDL response) { - if (accepted) { - callback.accepted(drag); - } - } - }; - VDragAndDropManager.get().visitServer(acceptCallback); - } - - @Override - public boolean needsServerSideCheck(VDragEvent drag, UIDL criterioUIDL) { - return true; - } - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - return false; // not used - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VSourceIsTarget.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VSourceIsTarget.java deleted file mode 100644 index 21e6ab130a..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VSourceIsTarget.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.event.dd.acceptcriteria.SourceIsTarget; -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.UIDL; - -@AcceptCriterion(SourceIsTarget.class) -final public class VSourceIsTarget extends VAcceptCriterion { - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - ComponentConnector dragSource = drag.getTransferable().getDragSource(); - ComponentConnector paintable = VDragAndDropManager.get() - .getCurrentDropHandler().getConnector(); - - return paintable == dragSource; - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetDetailIs.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetDetailIs.java deleted file mode 100644 index 8c6c522be4..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetDetailIs.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.vaadin.event.dd.acceptcriteria.TargetDetailIs; -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.terminal.gwt.client.UIDL; - -@AcceptCriterion(TargetDetailIs.class) -final public class VTargetDetailIs extends VAcceptCriterion { - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - String name = configuration.getStringAttribute("p"); - String t = configuration.hasAttribute("t") ? configuration - .getStringAttribute("t").intern() : "s"; - Object value = null; - if (t == "s") { - value = configuration.getStringAttribute("v"); - } else if (t == "b") { - value = configuration.getBooleanAttribute("v"); - } - if (value != null) { - Object object = drag.getDropDetails().get(name); - if (object instanceof Enum) { - return ((Enum<?>) object).name().equals(value); - } else { - return value.equals(object); - } - } else { - return false; - } - - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetInSubtree.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetInSubtree.java deleted file mode 100644 index 56421a6ed7..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetInSubtree.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/** - * - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.tree.VTree; -import com.vaadin.terminal.gwt.client.ui.tree.VTree.TreeNode; -import com.vaadin.ui.Tree; - -@AcceptCriterion(Tree.TargetInSubtree.class) -final public class VTargetInSubtree extends VAcceptCriterion { - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - - VTree tree = (VTree) VDragAndDropManager.get().getCurrentDropHandler() - .getConnector(); - TreeNode treeNode = tree.getNodeByKey((String) drag.getDropDetails() - .get("itemIdOver")); - if (treeNode != null) { - Widget parent2 = treeNode; - int depth = configuration.getIntAttribute("depth"); - if (depth < 0) { - depth = Integer.MAX_VALUE; - } - final String searchedKey = configuration.getStringAttribute("key"); - for (int i = 0; i <= depth && parent2 instanceof TreeNode; i++) { - if (searchedKey.equals(((TreeNode) parent2).key)) { - return true; - } - // panel -> next level node - parent2 = parent2.getParent().getParent(); - } - } - - return false; - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VTransferable.java b/client/src/com/vaadin/terminal/gwt/client/ui/dd/VTransferable.java deleted file mode 100644 index 12cd1ed598..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/dd/VTransferable.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.dd; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import com.vaadin.event.dd.DragSource; -import com.vaadin.terminal.gwt.client.ComponentConnector; - -/** - * Client side counterpart for Transferable in com.vaadin.event.Transferable - * - */ -public class VTransferable { - - private ComponentConnector component; - - private final Map<String, Object> variables = new HashMap<String, Object>(); - - /** - * Returns the component from which the transferable is created (eg. a tree - * which node is dragged). - * - * @return the component - */ - public ComponentConnector getDragSource() { - return component; - } - - /** - * Sets the component currently being dragged or from which the transferable - * is created (eg. a tree which node is dragged). - * <p> - * The server side counterpart of the component may implement - * {@link DragSource} interface if it wants to translate or complement the - * server side instance of this Transferable. - * - * @param component - * the component to set - */ - public void setDragSource(ComponentConnector component) { - this.component = component; - } - - public Object getData(String dataFlavor) { - return variables.get(dataFlavor); - } - - public void setData(String dataFlavor, Object value) { - variables.put(dataFlavor, value); - } - - public Collection<String> getDataFlavors() { - return variables.keySet(); - } - - /** - * This helper method should only be called by {@link VDragAndDropManager}. - * - * @return data in this Transferable that needs to be moved to server. - */ - Map<String, Object> getVariableMap() { - return variables; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_alignment.png b/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_alignment.png Binary files differdeleted file mode 100644 index 49b918ec0c..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_alignment.png +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_component_handles_the_caption.png b/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_component_handles_the_caption.png Binary files differdeleted file mode 100644 index 9fd6635765..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_component_handles_the_caption.png +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_h150.png b/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_h150.png Binary files differdeleted file mode 100644 index 7cd07369dc..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_h150.png +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_horizontal.png b/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_horizontal.png Binary files differdeleted file mode 100644 index c2e1f49efe..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_horizontal.png +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_horizontal_spacing.png b/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_horizontal_spacing.png Binary files differdeleted file mode 100644 index 417c9aecfd..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_horizontal_spacing.png +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_margin.png b/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_margin.png Binary files differdeleted file mode 100644 index 2f1e461b0a..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_margin.png +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_no_caption.png b/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_no_caption.png Binary files differdeleted file mode 100644 index 63984cdee7..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_no_caption.png +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_normal_caption.png b/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_normal_caption.png Binary files differdeleted file mode 100644 index 1e730c072b..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_normal_caption.png +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_special-margin.png b/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_special-margin.png Binary files differdeleted file mode 100644 index 34e47d1551..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_special-margin.png +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_vertical.png b/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_vertical.png Binary files differdeleted file mode 100644 index 99e3709acc..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_vertical.png +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_vertical_spacing.png b/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_vertical_spacing.png Binary files differdeleted file mode 100644 index be9a4cd8c5..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_vertical_spacing.png +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_w300.png b/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_w300.png Binary files differdeleted file mode 100644 index 0b555ad1e7..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_w300.png +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_w300_h150.png b/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_w300_h150.png Binary files differdeleted file mode 100644 index 8ff42ed0f4..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/doc-files/IOrderedLayout_w300_h150.png +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java deleted file mode 100644 index 7542754e58..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.draganddropwrapper; - -import java.util.HashMap; -import java.util.Set; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.draganddropwrapper.DragAndDropWrapperConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.customcomponent.CustomComponentConnector; -import com.vaadin.ui.DragAndDropWrapper; - -@Connect(DragAndDropWrapper.class) -public class DragAndDropWrapperConnector extends CustomComponentConnector - implements Paintable { - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - getWidget().client = client; - if (isRealUpdate(uidl) && !uidl.hasAttribute("hidden")) { - UIDL acceptCrit = uidl.getChildByTagName("-ac"); - if (acceptCrit == null) { - getWidget().dropHandler = null; - } else { - if (getWidget().dropHandler == null) { - getWidget().dropHandler = getWidget().new CustomDropHandler(); - } - getWidget().dropHandler.updateAcceptRules(acceptCrit); - } - - Set<String> variableNames = uidl.getVariableNames(); - for (String fileId : variableNames) { - if (fileId.startsWith("rec-")) { - String receiverUrl = uidl.getStringVariable(fileId); - fileId = fileId.substring(4); - if (getWidget().fileIdToReceiver == null) { - getWidget().fileIdToReceiver = new HashMap<String, String>(); - } - if ("".equals(receiverUrl)) { - Integer id = Integer.parseInt(fileId); - int indexOf = getWidget().fileIds.indexOf(id); - if (indexOf != -1) { - getWidget().files.remove(indexOf); - getWidget().fileIds.remove(indexOf); - } - } else { - getWidget().fileIdToReceiver.put(fileId, receiverUrl); - } - } - } - getWidget().startNextUpload(); - - getWidget().dragStartMode = uidl - .getIntAttribute(DragAndDropWrapperConstants.DRAG_START_MODE); - getWidget().initDragStartMode(); - getWidget().html5DataFlavors = uidl - .getMapAttribute(DragAndDropWrapperConstants.HTML5_DATA_FLAVORS); - - // Used to prevent wrapper from stealing tooltips when not defined - getWidget().hasTooltip = getState().hasDescription(); - } - } - - @Override - public VDragAndDropWrapper getWidget() { - return (VDragAndDropWrapper) super.getWidget(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java b/client/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java deleted file mode 100644 index 7d38624f22..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java +++ /dev/null @@ -1,606 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.draganddropwrapper; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.core.client.JsArrayString; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.event.dom.client.MouseDownEvent; -import com.google.gwt.event.dom.client.MouseDownHandler; -import com.google.gwt.event.dom.client.TouchStartEvent; -import com.google.gwt.event.dom.client.TouchStartHandler; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.ui.Widget; -import com.google.gwt.xhr.client.ReadyStateChangeHandler; -import com.google.gwt.xhr.client.XMLHttpRequest; -import com.vaadin.shared.ui.dd.HorizontalDropLocation; -import com.vaadin.shared.ui.dd.VerticalDropLocation; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.LayoutManager; -import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.ValueMap; -import com.vaadin.terminal.gwt.client.ui.customcomponent.VCustomComponent; -import com.vaadin.terminal.gwt.client.ui.dd.DDUtil; -import com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler; -import com.vaadin.terminal.gwt.client.ui.dd.VAcceptCallback; -import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager; -import com.vaadin.terminal.gwt.client.ui.dd.VDragEvent; -import com.vaadin.terminal.gwt.client.ui.dd.VDropHandler; -import com.vaadin.terminal.gwt.client.ui.dd.VHasDropHandler; -import com.vaadin.terminal.gwt.client.ui.dd.VHtml5DragEvent; -import com.vaadin.terminal.gwt.client.ui.dd.VHtml5File; -import com.vaadin.terminal.gwt.client.ui.dd.VTransferable; - -/** - * - * Must have features pending: - * - * drop details: locations + sizes in document hierarchy up to wrapper - * - */ -public class VDragAndDropWrapper extends VCustomComponent implements - VHasDropHandler { - - private static final String CLASSNAME = "v-ddwrapper"; - protected static final String DRAGGABLE = "draggable"; - - boolean hasTooltip = false; - - public VDragAndDropWrapper() { - super(); - - hookHtml5Events(getElement()); - setStyleName(CLASSNAME); - addDomHandler(new MouseDownHandler() { - - @Override - public void onMouseDown(MouseDownEvent event) { - if (startDrag(event.getNativeEvent())) { - event.preventDefault(); // prevent text selection - } - } - }, MouseDownEvent.getType()); - - addDomHandler(new TouchStartHandler() { - - @Override - public void onTouchStart(TouchStartEvent event) { - if (startDrag(event.getNativeEvent())) { - /* - * Dont let eg. panel start scrolling. - */ - event.stopPropagation(); - } - } - }, TouchStartEvent.getType()); - - sinkEvents(Event.TOUCHEVENTS); - } - - /** - * Starts a drag and drop operation from mousedown or touchstart event if - * required conditions are met. - * - * @param event - * @return true if the event was handled as a drag start event - */ - private boolean startDrag(NativeEvent event) { - if (dragStartMode == WRAPPER || dragStartMode == COMPONENT) { - VTransferable transferable = new VTransferable(); - transferable.setDragSource(ConnectorMap.get(client).getConnector( - VDragAndDropWrapper.this)); - - ComponentConnector paintable = Util.findPaintable(client, - (Element) event.getEventTarget().cast()); - Widget widget = paintable.getWidget(); - transferable.setData("component", paintable); - VDragEvent dragEvent = VDragAndDropManager.get().startDrag( - transferable, event, true); - - transferable.setData("mouseDown", MouseEventDetailsBuilder - .buildMouseEventDetails(event).serialize()); - - if (dragStartMode == WRAPPER) { - dragEvent.createDragImage(getElement(), true); - } else { - dragEvent.createDragImage(widget.getElement(), true); - } - return true; - } - return false; - } - - protected final static int NONE = 0; - protected final static int COMPONENT = 1; - protected final static int WRAPPER = 2; - protected final static int HTML5 = 3; - - protected int dragStartMode; - - ApplicationConnection client; - VAbstractDropHandler dropHandler; - private VDragEvent vaadinDragEvent; - - int filecounter = 0; - Map<String, String> fileIdToReceiver; - ValueMap html5DataFlavors; - private Element dragStartElement; - - protected void initDragStartMode() { - Element div = getElement(); - if (dragStartMode == HTML5) { - if (dragStartElement == null) { - dragStartElement = getDragStartElement(); - dragStartElement.setPropertyBoolean(DRAGGABLE, true); - VConsole.log("draggable = " - + dragStartElement.getPropertyBoolean(DRAGGABLE)); - hookHtml5DragStart(dragStartElement); - VConsole.log("drag start listeners hooked."); - } - } else { - dragStartElement = null; - if (div.hasAttribute(DRAGGABLE)) { - div.removeAttribute(DRAGGABLE); - } - } - } - - protected Element getDragStartElement() { - return getElement(); - } - - private boolean uploading; - - private ReadyStateChangeHandler readyStateChangeHandler = new ReadyStateChangeHandler() { - - @Override - public void onReadyStateChange(XMLHttpRequest xhr) { - if (xhr.getReadyState() == XMLHttpRequest.DONE) { - // visit server for possible - // variable changes - client.sendPendingVariableChanges(); - uploading = false; - startNextUpload(); - xhr.clearOnReadyStateChange(); - } - } - }; - private Timer dragleavetimer; - - void startNextUpload() { - Scheduler.get().scheduleDeferred(new Command() { - - @Override - public void execute() { - if (!uploading) { - if (fileIds.size() > 0) { - - uploading = true; - final Integer fileId = fileIds.remove(0); - VHtml5File file = files.remove(0); - final String receiverUrl = client - .translateVaadinUri(fileIdToReceiver - .remove(fileId.toString())); - ExtendedXHR extendedXHR = (ExtendedXHR) ExtendedXHR - .create(); - extendedXHR - .setOnReadyStateChange(readyStateChangeHandler); - extendedXHR.open("POST", receiverUrl); - extendedXHR.postFile(file); - } - } - - } - }); - - } - - public boolean html5DragStart(VHtml5DragEvent event) { - if (dragStartMode == HTML5) { - /* - * Populate html5 payload with dataflavors from the serverside - */ - JsArrayString flavors = html5DataFlavors.getKeyArray(); - for (int i = 0; i < flavors.length(); i++) { - String flavor = flavors.get(i); - event.setHtml5DataFlavor(flavor, - html5DataFlavors.getString(flavor)); - } - event.setEffectAllowed("copy"); - return true; - } - return false; - } - - public boolean html5DragEnter(VHtml5DragEvent event) { - if (dropHandler == null) { - return true; - } - try { - if (dragleavetimer != null) { - // returned quickly back to wrapper - dragleavetimer.cancel(); - dragleavetimer = null; - } - if (VDragAndDropManager.get().getCurrentDropHandler() != getDropHandler()) { - VTransferable transferable = new VTransferable(); - transferable.setDragSource(ConnectorMap.get(client) - .getConnector(this)); - - vaadinDragEvent = VDragAndDropManager.get().startDrag( - transferable, event, false); - VDragAndDropManager.get().setCurrentDropHandler( - getDropHandler()); - } - try { - event.preventDefault(); - event.stopPropagation(); - } catch (Exception e) { - // VConsole.log("IE9 fails"); - } - return false; - } catch (Exception e) { - GWT.getUncaughtExceptionHandler().onUncaughtException(e); - return true; - } - } - - public boolean html5DragLeave(VHtml5DragEvent event) { - if (dropHandler == null) { - return true; - } - - try { - dragleavetimer = new Timer() { - - @Override - public void run() { - // Yes, dragleave happens before drop. Makes no sense to me. - // IMO shouldn't fire leave at all if drop happens (I guess - // this - // is what IE does). - // In Vaadin we fire it only if drop did not happen. - if (vaadinDragEvent != null - && VDragAndDropManager.get() - .getCurrentDropHandler() == getDropHandler()) { - VDragAndDropManager.get().interruptDrag(); - } - } - }; - dragleavetimer.schedule(350); - try { - event.preventDefault(); - event.stopPropagation(); - } catch (Exception e) { - // VConsole.log("IE9 fails"); - } - return false; - } catch (Exception e) { - GWT.getUncaughtExceptionHandler().onUncaughtException(e); - return true; - } - } - - public boolean html5DragOver(VHtml5DragEvent event) { - if (dropHandler == null) { - return true; - } - - if (dragleavetimer != null) { - // returned quickly back to wrapper - dragleavetimer.cancel(); - dragleavetimer = null; - } - - vaadinDragEvent.setCurrentGwtEvent(event); - getDropHandler().dragOver(vaadinDragEvent); - - String s = event.getEffectAllowed(); - if ("all".equals(s) || s.contains("opy")) { - event.setDropEffect("copy"); - } else { - event.setDropEffect(s); - } - - try { - event.preventDefault(); - event.stopPropagation(); - } catch (Exception e) { - // VConsole.log("IE9 fails"); - } - return false; - } - - public boolean html5DragDrop(VHtml5DragEvent event) { - if (dropHandler == null || !currentlyValid) { - return true; - } - try { - - VTransferable transferable = vaadinDragEvent.getTransferable(); - - JsArrayString types = event.getTypes(); - for (int i = 0; i < types.length(); i++) { - String type = types.get(i); - if (isAcceptedType(type)) { - String data = event.getDataAsText(type); - if (data != null) { - transferable.setData(type, data); - } - } - } - - int fileCount = event.getFileCount(); - if (fileCount > 0) { - transferable.setData("filecount", fileCount); - for (int i = 0; i < fileCount; i++) { - final int fileId = filecounter++; - final VHtml5File file = event.getFile(i); - transferable.setData("fi" + i, "" + fileId); - transferable.setData("fn" + i, file.getName()); - transferable.setData("ft" + i, file.getType()); - transferable.setData("fs" + i, file.getSize()); - queueFilePost(fileId, file); - } - - } - - VDragAndDropManager.get().endDrag(); - vaadinDragEvent = null; - try { - event.preventDefault(); - event.stopPropagation(); - } catch (Exception e) { - // VConsole.log("IE9 fails"); - } - return false; - } catch (Exception e) { - GWT.getUncaughtExceptionHandler().onUncaughtException(e); - return true; - } - - } - - protected String[] acceptedTypes = new String[] { "Text", "Url", - "text/html", "text/plain", "text/rtf" }; - - private boolean isAcceptedType(String type) { - for (String t : acceptedTypes) { - if (t.equals(type)) { - return true; - } - } - return false; - } - - static class ExtendedXHR extends XMLHttpRequest { - - protected ExtendedXHR() { - } - - public final native void postFile(VHtml5File file) - /*-{ - - this.setRequestHeader('Content-Type', 'multipart/form-data'); - this.send(file); - }-*/; - - } - - /** - * Currently supports only FF36 as no other browser supports natively File - * api. - * - * @param fileId - * @param data - */ - List<Integer> fileIds = new ArrayList<Integer>(); - List<VHtml5File> files = new ArrayList<VHtml5File>(); - - private void queueFilePost(final int fileId, final VHtml5File file) { - fileIds.add(fileId); - files.add(file); - } - - @Override - public VDropHandler getDropHandler() { - return dropHandler; - } - - protected VerticalDropLocation verticalDropLocation; - protected HorizontalDropLocation horizontalDropLocation; - private VerticalDropLocation emphasizedVDrop; - private HorizontalDropLocation emphasizedHDrop; - - /** - * Flag used by html5 dd - */ - private boolean currentlyValid; - - private static final String OVER_STYLE = "v-ddwrapper-over"; - - public class CustomDropHandler extends VAbstractDropHandler { - - @Override - public void dragEnter(VDragEvent drag) { - updateDropDetails(drag); - currentlyValid = false; - super.dragEnter(drag); - } - - @Override - public void dragLeave(VDragEvent drag) { - deEmphasis(true); - dragleavetimer = null; - } - - @Override - public void dragOver(final VDragEvent drag) { - boolean detailsChanged = updateDropDetails(drag); - if (detailsChanged) { - currentlyValid = false; - validate(new VAcceptCallback() { - - @Override - public void accepted(VDragEvent event) { - dragAccepted(drag); - } - }, drag); - } - } - - @Override - public boolean drop(VDragEvent drag) { - deEmphasis(true); - - Map<String, Object> dd = drag.getDropDetails(); - - // this is absolute layout based, and we may want to set - // component - // relatively to where the drag ended. - // need to add current location of the drop area - - int absoluteLeft = getAbsoluteLeft(); - int absoluteTop = getAbsoluteTop(); - - dd.put("absoluteLeft", absoluteLeft); - dd.put("absoluteTop", absoluteTop); - - if (verticalDropLocation != null) { - dd.put("verticalLocation", verticalDropLocation.toString()); - dd.put("horizontalLocation", horizontalDropLocation.toString()); - } - - return super.drop(drag); - } - - @Override - protected void dragAccepted(VDragEvent drag) { - currentlyValid = true; - emphasis(drag); - } - - @Override - public ComponentConnector getConnector() { - return ConnectorMap.get(client).getConnector( - VDragAndDropWrapper.this); - } - - @Override - public ApplicationConnection getApplicationConnection() { - return client; - } - - } - - protected native void hookHtml5DragStart(Element el) - /*-{ - var me = this; - el.addEventListener("dragstart", $entry(function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.draganddropwrapper.VDragAndDropWrapper::html5DragStart(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - }), false); - }-*/; - - /** - * Prototype code, memory leak risk. - * - * @param el - */ - protected native void hookHtml5Events(Element el) - /*-{ - var me = this; - - el.addEventListener("dragenter", $entry(function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.draganddropwrapper.VDragAndDropWrapper::html5DragEnter(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - }), false); - - el.addEventListener("dragleave", $entry(function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.draganddropwrapper.VDragAndDropWrapper::html5DragLeave(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - }), false); - - el.addEventListener("dragover", $entry(function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.draganddropwrapper.VDragAndDropWrapper::html5DragOver(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - }), false); - - el.addEventListener("drop", $entry(function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.draganddropwrapper.VDragAndDropWrapper::html5DragDrop(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - }), false); - }-*/; - - public boolean updateDropDetails(VDragEvent drag) { - VerticalDropLocation oldVL = verticalDropLocation; - verticalDropLocation = DDUtil.getVerticalDropLocation(getElement(), - drag.getCurrentGwtEvent(), 0.2); - drag.getDropDetails().put("verticalLocation", - verticalDropLocation.toString()); - HorizontalDropLocation oldHL = horizontalDropLocation; - horizontalDropLocation = DDUtil.getHorizontalDropLocation(getElement(), - drag.getCurrentGwtEvent(), 0.2); - drag.getDropDetails().put("horizontalLocation", - horizontalDropLocation.toString()); - if (oldHL != horizontalDropLocation || oldVL != verticalDropLocation) { - return true; - } else { - return false; - } - } - - protected void deEmphasis(boolean doLayout) { - if (emphasizedVDrop != null) { - VDragAndDropWrapper.setStyleName(getElement(), OVER_STYLE, false); - VDragAndDropWrapper.setStyleName(getElement(), OVER_STYLE + "-" - + emphasizedVDrop.toString().toLowerCase(), false); - VDragAndDropWrapper.setStyleName(getElement(), OVER_STYLE + "-" - + emphasizedHDrop.toString().toLowerCase(), false); - } - if (doLayout) { - notifySizePotentiallyChanged(); - } - } - - private void notifySizePotentiallyChanged() { - LayoutManager.get(client).setNeedsMeasure( - ConnectorMap.get(client).getConnector(getElement())); - } - - protected void emphasis(VDragEvent drag) { - deEmphasis(false); - VDragAndDropWrapper.setStyleName(getElement(), OVER_STYLE, true); - VDragAndDropWrapper.setStyleName(getElement(), OVER_STYLE + "-" - + verticalDropLocation.toString().toLowerCase(), true); - VDragAndDropWrapper.setStyleName(getElement(), OVER_STYLE + "-" - + horizontalDropLocation.toString().toLowerCase(), true); - emphasizedVDrop = verticalDropLocation; - emphasizedHDrop = horizontalDropLocation; - - // TODO build (to be an example) an emphasis mode where drag image - // is fitted before or after the content - notifySizePotentiallyChanged(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapperIE.java b/client/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapperIE.java deleted file mode 100644 index fc9829d387..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapperIE.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.draganddropwrapper; - -import com.google.gwt.dom.client.AnchorElement; -import com.google.gwt.dom.client.Document; -import com.google.gwt.user.client.Element; -import com.vaadin.terminal.gwt.client.VConsole; - -public class VDragAndDropWrapperIE extends VDragAndDropWrapper { - private AnchorElement anchor = null; - - @Override - protected Element getDragStartElement() { - VConsole.log("IE get drag start element..."); - Element div = getElement(); - if (dragStartMode == HTML5) { - if (anchor == null) { - anchor = Document.get().createAnchorElement(); - anchor.setHref("#"); - anchor.setClassName("drag-start"); - div.appendChild(anchor); - } - VConsole.log("IE get drag start element..."); - return (Element) anchor.cast(); - } else { - if (anchor != null) { - div.removeChild(anchor); - anchor = null; - } - return div; - } - } - - @Override - protected native void hookHtml5DragStart(Element el) - /*-{ - var me = this; - - el.attachEvent("ondragstart", $entry(function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.draganddropwrapper.VDragAndDropWrapper::html5DragStart(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - })); - }-*/; - - @Override - protected native void hookHtml5Events(Element el) - /*-{ - var me = this; - - el.attachEvent("ondragenter", $entry(function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.draganddropwrapper.VDragAndDropWrapper::html5DragEnter(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - })); - - el.attachEvent("ondragleave", $entry(function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.draganddropwrapper.VDragAndDropWrapper::html5DragLeave(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - })); - - el.attachEvent("ondragover", $entry(function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.draganddropwrapper.VDragAndDropWrapper::html5DragOver(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - })); - - el.attachEvent("ondrop", $entry(function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.draganddropwrapper.VDragAndDropWrapper::html5DragDrop(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - })); - }-*/; - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/embedded/EmbeddedConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/embedded/EmbeddedConnector.java deleted file mode 100644 index 5c95f9f554..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/embedded/EmbeddedConnector.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.embedded; - -import java.util.Map; - -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.dom.client.Node; -import com.google.gwt.dom.client.NodeList; -import com.google.gwt.dom.client.ObjectElement; -import com.google.gwt.dom.client.Style; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.embedded.EmbeddedConstants; -import com.vaadin.shared.ui.embedded.EmbeddedServerRpc; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.VTooltip; -import com.vaadin.terminal.gwt.client.communication.RpcProxy; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; -import com.vaadin.terminal.gwt.client.ui.ClickEventHandler; -import com.vaadin.ui.Embedded; - -@Connect(Embedded.class) -public class EmbeddedConnector extends AbstractComponentConnector implements - Paintable { - - EmbeddedServerRpc rpc; - - @Override - protected void init() { - super.init(); - rpc = RpcProxy.create(EmbeddedServerRpc.class, this); - } - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (!isRealUpdate(uidl)) { - return; - } - - // Save details - getWidget().client = client; - - boolean clearBrowserElement = true; - - clickEventHandler.handleEventHandlerRegistration(); - - if (uidl.hasAttribute("type")) { - // remove old style name related to type - if (getWidget().type != null) { - getWidget().removeStyleName( - VEmbedded.CLASSNAME + "-" + getWidget().type); - } - // remove old style name related to mime type - if (getWidget().mimetype != null) { - getWidget().removeStyleName( - VEmbedded.CLASSNAME + "-" + getWidget().mimetype); - } - getWidget().type = uidl.getStringAttribute("type"); - if (getWidget().type.equals("image")) { - getWidget().addStyleName(VEmbedded.CLASSNAME + "-image"); - Element el = null; - boolean created = false; - NodeList<Node> nodes = getWidget().getElement().getChildNodes(); - if (nodes != null && nodes.getLength() == 1) { - Node n = nodes.getItem(0); - if (n.getNodeType() == Node.ELEMENT_NODE) { - Element e = (Element) n; - if (e.getTagName().equals("IMG")) { - el = e; - } - } - } - if (el == null) { - getWidget().setHTML(""); - el = DOM.createImg(); - created = true; - DOM.sinkEvents(el, Event.ONLOAD); - } - - // Set attributes - Style style = el.getStyle(); - style.setProperty("width", getState().getWidth()); - style.setProperty("height", getState().getHeight()); - - DOM.setElementProperty(el, "src", - getWidget().getSrc(uidl, client)); - - if (uidl.hasAttribute(EmbeddedConstants.ALTERNATE_TEXT)) { - el.setPropertyString( - EmbeddedConstants.ALTERNATE_TEXT, - uidl.getStringAttribute(EmbeddedConstants.ALTERNATE_TEXT)); - } - - if (created) { - // insert in dom late - getWidget().getElement().appendChild(el); - } - - /* - * Sink tooltip events so tooltip is displayed when hovering the - * image. - */ - getWidget().sinkEvents(VTooltip.TOOLTIP_EVENTS); - - } else if (getWidget().type.equals("browser")) { - getWidget().addStyleName(VEmbedded.CLASSNAME + "-browser"); - if (getWidget().browserElement == null) { - getWidget().setHTML( - "<iframe width=\"100%\" height=\"100%\" frameborder=\"0\"" - + " allowTransparency=\"true\" src=\"\"" - + " name=\"" + uidl.getId() - + "\"></iframe>"); - getWidget().browserElement = DOM.getFirstChild(getWidget() - .getElement()); - } - DOM.setElementAttribute(getWidget().browserElement, "src", - getWidget().getSrc(uidl, client)); - clearBrowserElement = false; - } else { - VConsole.log("Unknown Embedded type '" + getWidget().type + "'"); - } - } else if (uidl.hasAttribute("mimetype")) { - // remove old style name related to type - if (getWidget().type != null) { - getWidget().removeStyleName( - VEmbedded.CLASSNAME + "-" + getWidget().type); - } - // remove old style name related to mime type - if (getWidget().mimetype != null) { - getWidget().removeStyleName( - VEmbedded.CLASSNAME + "-" + getWidget().mimetype); - } - final String mime = uidl.getStringAttribute("mimetype"); - if (mime.equals("application/x-shockwave-flash")) { - getWidget().mimetype = "flash"; - // Handle embedding of Flash - getWidget().addStyleName(VEmbedded.CLASSNAME + "-flash"); - getWidget().setHTML(getWidget().createFlashEmbed(uidl)); - - } else if (mime.equals("image/svg+xml")) { - getWidget().mimetype = "svg"; - getWidget().addStyleName(VEmbedded.CLASSNAME + "-svg"); - String data; - Map<String, String> parameters = VEmbedded.getParameters(uidl); - if (parameters.get("data") == null) { - data = getWidget().getSrc(uidl, client); - } else { - data = "data:image/svg+xml," + parameters.get("data"); - } - getWidget().setHTML(""); - ObjectElement obj = Document.get().createObjectElement(); - obj.setType(mime); - obj.setData(data); - if (!isUndefinedWidth()) { - obj.getStyle().setProperty("width", "100%"); - } - if (!isUndefinedHeight()) { - obj.getStyle().setProperty("height", "100%"); - } - if (uidl.hasAttribute("classid")) { - obj.setAttribute("classid", - uidl.getStringAttribute("classid")); - } - if (uidl.hasAttribute("codebase")) { - obj.setAttribute("codebase", - uidl.getStringAttribute("codebase")); - } - if (uidl.hasAttribute("codetype")) { - obj.setAttribute("codetype", - uidl.getStringAttribute("codetype")); - } - if (uidl.hasAttribute("archive")) { - obj.setAttribute("archive", - uidl.getStringAttribute("archive")); - } - if (uidl.hasAttribute("standby")) { - obj.setAttribute("standby", - uidl.getStringAttribute("standby")); - } - getWidget().getElement().appendChild(obj); - if (uidl.hasAttribute(EmbeddedConstants.ALTERNATE_TEXT)) { - obj.setInnerText(uidl - .getStringAttribute(EmbeddedConstants.ALTERNATE_TEXT)); - } - } else { - VConsole.log("Unknown Embedded mimetype '" + mime + "'"); - } - } else { - VConsole.log("Unknown Embedded; no type or mimetype attribute"); - } - - if (clearBrowserElement) { - getWidget().browserElement = null; - } - } - - @Override - public VEmbedded getWidget() { - return (VEmbedded) super.getWidget(); - } - - protected final ClickEventHandler clickEventHandler = new ClickEventHandler( - this) { - - @Override - protected void fireClick(NativeEvent event, - MouseEventDetails mouseDetails) { - rpc.click(mouseDetails); - } - - }; - -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/embedded/VEmbedded.java b/client/src/com/vaadin/terminal/gwt/client/ui/embedded/VEmbedded.java deleted file mode 100644 index dca4686a5c..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/embedded/VEmbedded.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.embedded; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.HTML; -import com.vaadin.shared.ui.embedded.EmbeddedConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VConsole; - -public class VEmbedded extends HTML { - public static String CLASSNAME = "v-embedded"; - - protected Element browserElement; - - protected String type; - protected String mimetype; - - protected ApplicationConnection client; - - public VEmbedded() { - setStyleName(CLASSNAME); - } - - /** - * Creates the Object and Embed tags for the Flash plugin so it works - * cross-browser - * - * @param uidl - * The UIDL - * @return Tags concatenated into a string - */ - protected String createFlashEmbed(UIDL uidl) { - /* - * To ensure cross-browser compatibility we are using the twice-cooked - * method to embed flash i.e. we add a OBJECT tag for IE ActiveX and - * inside it a EMBED for all other browsers. - */ - - StringBuilder html = new StringBuilder(); - - // Start the object tag - html.append("<object "); - - /* - * Add classid required for ActiveX to recognize the flash. This is a - * predefined value which ActiveX recognizes and must be the given - * value. More info can be found on - * http://kb2.adobe.com/cps/415/tn_4150.html. Allow user to override - * this by setting his own classid. - */ - if (uidl.hasAttribute("classid")) { - html.append("classid=\"" - + Util.escapeAttribute(uidl.getStringAttribute("classid")) - + "\" "); - } else { - html.append("classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" "); - } - - /* - * Add codebase required for ActiveX and must be exactly this according - * to http://kb2.adobe.com/cps/415/tn_4150.html to work with the above - * given classid. Again, see more info on - * http://kb2.adobe.com/cps/415/tn_4150.html. Limiting Flash version to - * 6.0.0.0 and above. Allow user to override this by setting his own - * codebase - */ - if (uidl.hasAttribute("codebase")) { - html.append("codebase=\"" - + Util.escapeAttribute(uidl.getStringAttribute("codebase")) - + "\" "); - } else { - html.append("codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0\" "); - } - - ComponentConnector paintable = ConnectorMap.get(client).getConnector( - this); - String height = paintable.getState().getHeight(); - String width = paintable.getState().getWidth(); - - // Add width and height - html.append("width=\"" + Util.escapeAttribute(width) + "\" "); - html.append("height=\"" + Util.escapeAttribute(height) + "\" "); - html.append("type=\"application/x-shockwave-flash\" "); - - // Codetype - if (uidl.hasAttribute("codetype")) { - html.append("codetype=\"" - + Util.escapeAttribute(uidl.getStringAttribute("codetype")) - + "\" "); - } - - // Standby - if (uidl.hasAttribute("standby")) { - html.append("standby=\"" - + Util.escapeAttribute(uidl.getStringAttribute("standby")) - + "\" "); - } - - // Archive - if (uidl.hasAttribute("archive")) { - html.append("archive=\"" - + Util.escapeAttribute(uidl.getStringAttribute("archive")) - + "\" "); - } - - // End object tag - html.append(">"); - - // Ensure we have an movie parameter - Map<String, String> parameters = getParameters(uidl); - if (parameters.get("movie") == null) { - parameters.put("movie", getSrc(uidl, client)); - } - - // Add parameters to OBJECT - for (String name : parameters.keySet()) { - html.append("<param "); - html.append("name=\"" + Util.escapeAttribute(name) + "\" "); - html.append("value=\"" + Util.escapeAttribute(parameters.get(name)) - + "\" "); - html.append("/>"); - } - - // Build inner EMBED tag - html.append("<embed "); - html.append("src=\"" + Util.escapeAttribute(getSrc(uidl, client)) - + "\" "); - html.append("width=\"" + Util.escapeAttribute(width) + "\" "); - html.append("height=\"" + Util.escapeAttribute(height) + "\" "); - html.append("type=\"application/x-shockwave-flash\" "); - - // Add the parameters to the Embed - for (String name : parameters.keySet()) { - html.append(Util.escapeAttribute(name)); - html.append("="); - html.append("\"" + Util.escapeAttribute(parameters.get(name)) - + "\""); - } - - // End embed tag - html.append("></embed>"); - - if (uidl.hasAttribute(EmbeddedConstants.ALTERNATE_TEXT)) { - html.append(uidl - .getStringAttribute(EmbeddedConstants.ALTERNATE_TEXT)); - } - - // End object tag - html.append("</object>"); - - return html.toString(); - } - - /** - * Returns a map (name -> value) of all parameters in the UIDL. - * - * @param uidl - * @return - */ - protected static Map<String, String> getParameters(UIDL uidl) { - Map<String, String> parameters = new HashMap<String, String>(); - - Iterator<Object> childIterator = uidl.getChildIterator(); - while (childIterator.hasNext()) { - - Object child = childIterator.next(); - if (child instanceof UIDL) { - - UIDL childUIDL = (UIDL) child; - if (childUIDL.getTag().equals("embeddedparam")) { - String name = childUIDL.getStringAttribute("name"); - String value = childUIDL.getStringAttribute("value"); - parameters.put(name, value); - } - } - - } - - return parameters; - } - - /** - * Helper to return translated src-attribute from embedded's UIDL - * - * @param uidl - * @param client - * @return - */ - protected String getSrc(UIDL uidl, ApplicationConnection client) { - String url = client.translateVaadinUri(uidl.getStringAttribute("src")); - if (url == null) { - return ""; - } - return url; - } - - @Override - protected void onDetach() { - if (BrowserInfo.get().isIE()) { - // Force browser to fire unload event when component is detached - // from the view (IE doesn't do this automatically) - if (browserElement != null) { - /* - * src was previously set to javascript:false, but this was not - * enough to overcome a bug when detaching an iframe with a pdf - * loaded in IE9. about:blank seems to cause the adobe reader - * plugin to unload properly before the iframe is removed. See - * #7855 - */ - DOM.setElementAttribute(browserElement, "src", "about:blank"); - } - } - super.onDetach(); - } - - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - if (DOM.eventGetType(event) == Event.ONLOAD) { - VConsole.log("Embeddable onload"); - Util.notifyParentOfSizeChange(this, true); - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/embeddedbrowser/EmbeddedBrowserConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/embeddedbrowser/EmbeddedBrowserConnector.java deleted file mode 100644 index 61231c4fba..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/embeddedbrowser/EmbeddedBrowserConnector.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.vaadin.terminal.gwt.client.ui.embeddedbrowser; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.embeddedbrowser.EmbeddedBrowserState; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; - -@Connect(com.vaadin.ui.EmbeddedBrowser.class) -public class EmbeddedBrowserConnector extends AbstractComponentConnector { - - @Override - protected void init() { - super.init(); - } - - @Override - public VEmbeddedBrowser getWidget() { - return (VEmbeddedBrowser) super.getWidget(); - } - - @Override - public EmbeddedBrowserState getState() { - return (EmbeddedBrowserState) super.getState(); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - - super.onStateChanged(stateChangeEvent); - - getWidget().setAlternateText(getState().getAlternateText()); - getWidget().setSource( - getState().getSource() != null ? getState().getSource() - .getURL() : null); - getWidget().setName(getConnectorId()); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/embeddedbrowser/VEmbeddedBrowser.java b/client/src/com/vaadin/terminal/gwt/client/ui/embeddedbrowser/VEmbeddedBrowser.java deleted file mode 100644 index fffbff049e..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/embeddedbrowser/VEmbeddedBrowser.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.vaadin.terminal.gwt.client.ui.embeddedbrowser; - -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.IFrameElement; -import com.google.gwt.user.client.ui.Widget; - -public class VEmbeddedBrowser extends Widget { - - protected IFrameElement iframe; - protected Element altElement; - protected String altText; - - public VEmbeddedBrowser() { - Element root = Document.get().createDivElement(); - setElement(root); - - setStylePrimaryName("v-embeddedbrowser"); - - createAltTextElement(); - } - - /** - * Always creates new iframe inside widget. Will replace previous iframe. - * - * @return - */ - protected IFrameElement createIFrameElement(String src) { - String name = null; - - // Remove alt text - if (altElement != null) { - getElement().removeChild(altElement); - altElement = null; - } - - // Remove old iframe - if (iframe != null) { - name = iframe.getAttribute("name"); - getElement().removeChild(iframe); - iframe = null; - } - - iframe = Document.get().createIFrameElement(); - iframe.setSrc(src); - iframe.setFrameBorder(0); - iframe.setAttribute("width", "100%"); - iframe.setAttribute("height", "100%"); - iframe.setAttribute("allowTransparency", "true"); - - getElement().appendChild(iframe); - - // Reset old attributes (except src) - if (name != null) { - iframe.setName(name); - } - - return iframe; - } - - protected void createAltTextElement() { - if (iframe != null) { - return; - } - - if (altElement == null) { - altElement = Document.get().createSpanElement(); - getElement().appendChild(altElement); - } - - if (altText != null) { - altElement.setInnerText(altText); - } else { - altElement.setInnerText(""); - } - } - - public void setAlternateText(String altText) { - if (this.altText != altText) { - this.altText = altText; - if (altElement != null) { - if (altText != null) { - altElement.setInnerText(altText); - } else { - altElement.setInnerText(""); - } - } - } - } - - /** - * Set the source (the "src" attribute) of iframe. Will replace old iframe - * with new. - * - * @param source - * Source of iframe. - */ - public void setSource(String source) { - - if (source == null) { - if (iframe != null) { - getElement().removeChild(iframe); - iframe = null; - } - createAltTextElement(); - setAlternateText(altText); - return; - } - - if (iframe == null || iframe.getSrc() != source) { - createIFrameElement(source); - } - } - - public void setName(String name) { - if (iframe != null) { - iframe.setName(name); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/flash/FlashConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/flash/FlashConnector.java deleted file mode 100644 index a9e7a71013..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/flash/FlashConnector.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.vaadin.terminal.gwt.client.ui.flash; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.flash.FlashState; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; - -@Connect(com.vaadin.ui.Flash.class) -public class FlashConnector extends AbstractComponentConnector { - - @Override - protected void init() { - super.init(); - } - - @Override - public VFlash getWidget() { - return (VFlash) super.getWidget(); - } - - @Override - public FlashState getState() { - return (FlashState) super.getState(); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - - super.onStateChanged(stateChangeEvent); - - getWidget().setSource( - getState().getSource() != null ? getState().getSource() - .getURL() : null); - getWidget().setArchive(getState().getArchive()); - getWidget().setClassId(getState().getClassId()); - getWidget().setCodebase(getState().getCodebase()); - getWidget().setCodetype(getState().getCodetype()); - getWidget().setStandby(getState().getStandby()); - getWidget().setAlternateText(getState().getAlternateText()); - getWidget().setEmbedParams(getState().getEmbedParams()); - - getWidget().rebuildIfNeeded(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/flash/VFlash.java b/client/src/com/vaadin/terminal/gwt/client/ui/flash/VFlash.java deleted file mode 100644 index 5d60dc66aa..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/flash/VFlash.java +++ /dev/null @@ -1,228 +0,0 @@ -package com.vaadin.terminal.gwt.client.ui.flash; - -import java.util.HashMap; -import java.util.Map; - -import com.google.gwt.user.client.ui.HTML; -import com.vaadin.terminal.gwt.client.Util; - -public class VFlash extends HTML { - - protected String source; - protected String altText; - protected String classId; - protected String codebase; - protected String codetype; - protected String standby; - protected String archive; - protected Map<String, String> embedParams = new HashMap<String, String>(); - protected boolean needsRebuild = false; - protected String width; - protected String height; - - public VFlash() { - setStylePrimaryName("v-flash"); - } - - public void setSource(String source) { - if (this.source != source) { - this.source = source; - needsRebuild = true; - } - } - - public void setAlternateText(String altText) { - if (this.altText != altText) { - this.altText = altText; - needsRebuild = true; - } - } - - public void setClassId(String classId) { - if (this.classId != classId) { - this.classId = classId; - needsRebuild = true; - } - } - - public void setCodebase(String codebase) { - if (this.codebase != codebase) { - this.codebase = codebase; - needsRebuild = true; - } - } - - public void setCodetype(String codetype) { - if (this.codetype != codetype) { - this.codetype = codetype; - needsRebuild = true; - } - } - - public void setStandby(String standby) { - if (this.standby != standby) { - this.standby = standby; - needsRebuild = true; - } - } - - public void setArchive(String archive) { - if (this.archive != archive) { - this.archive = archive; - needsRebuild = true; - } - } - - /** - * Call this after changing values of widget. It will rebuild embedding - * structure if needed. - */ - public void rebuildIfNeeded() { - if (needsRebuild) { - needsRebuild = false; - this.setHTML(createFlashEmbed()); - } - } - - @Override - public void setWidth(String width) { - // super.setWidth(height); - - if (this.width != width) { - this.width = width; - needsRebuild = true; - } - } - - @Override - public void setHeight(String height) { - // super.setHeight(height); - - if (this.height != height) { - this.height = height; - needsRebuild = true; - } - } - - public void setEmbedParams(Map<String, String> params) { - if (params == null) { - if (!embedParams.isEmpty()) { - embedParams.clear(); - needsRebuild = true; - } - return; - } - - if (!embedParams.equals(params)) { - embedParams = new HashMap<String, String>(params); - needsRebuild = true; - } - } - - protected String createFlashEmbed() { - /* - * To ensure cross-browser compatibility we are using the twice-cooked - * method to embed flash i.e. we add a OBJECT tag for IE ActiveX and - * inside it a EMBED for all other browsers. - */ - - StringBuilder html = new StringBuilder(); - - // Start the object tag - html.append("<object "); - - /* - * Add classid required for ActiveX to recognize the flash. This is a - * predefined value which ActiveX recognizes and must be the given - * value. More info can be found on - * http://kb2.adobe.com/cps/415/tn_4150.html. Allow user to override - * this by setting his own classid. - */ - if (classId != null) { - html.append("classid=\"" + Util.escapeAttribute(classId) + "\" "); - } else { - html.append("classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" "); - } - - /* - * Add codebase required for ActiveX and must be exactly this according - * to http://kb2.adobe.com/cps/415/tn_4150.html to work with the above - * given classid. Again, see more info on - * http://kb2.adobe.com/cps/415/tn_4150.html. Limiting Flash version to - * 6.0.0.0 and above. Allow user to override this by setting his own - * codebase - */ - if (codebase != null) { - html.append("codebase=\"" + Util.escapeAttribute(codebase) + "\" "); - } else { - html.append("codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0\" "); - } - - // Add width and height - html.append("width=\"" + Util.escapeAttribute(width) + "\" "); - html.append("height=\"" + Util.escapeAttribute(height) + "\" "); - html.append("type=\"application/x-shockwave-flash\" "); - - // Codetype - if (codetype != null) { - html.append("codetype=\"" + Util.escapeAttribute(codetype) + "\" "); - } - - // Standby - if (standby != null) { - html.append("standby=\"" + Util.escapeAttribute(standby) + "\" "); - } - - // Archive - if (archive != null) { - html.append("archive=\"" + Util.escapeAttribute(archive) + "\" "); - } - - // End object tag - html.append(">"); - - // Ensure we have an movie parameter - if (embedParams.get("movie") == null) { - embedParams.put("movie", source); - } - - // Add parameters to OBJECT - for (String name : embedParams.keySet()) { - html.append("<param "); - html.append("name=\"" + Util.escapeAttribute(name) + "\" "); - html.append("value=\"" - + Util.escapeAttribute(embedParams.get(name)) + "\" "); - html.append("/>"); - } - - // Build inner EMBED tag - html.append("<embed "); - html.append("src=\"" + Util.escapeAttribute(source) + "\" "); - html.append("width=\"" + Util.escapeAttribute(width) + "\" "); - html.append("height=\"" + Util.escapeAttribute(height) + "\" "); - html.append("type=\"application/x-shockwave-flash\" "); - - // Add the parameters to the Embed - for (String name : embedParams.keySet()) { - html.append(Util.escapeAttribute(name)); - html.append("="); - html.append("\"" + Util.escapeAttribute(embedParams.get(name)) - + "\""); - } - - // End embed tag - html.append("></embed>"); - - if (altText != null) { - html.append("<noembed>"); - html.append(altText); - html.append("</noembed>"); - } - - // End object tag - html.append("</object>"); - - return html.toString(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/form/FormConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/form/FormConnector.java deleted file mode 100644 index a38a67f84b..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/form/FormConnector.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.form; - -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.form.FormState; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.LayoutManager; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector; -import com.vaadin.terminal.gwt.client.ui.Icon; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler; -import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeEvent; -import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeListener; -import com.vaadin.terminal.gwt.client.ui.layout.MayScrollChildren; -import com.vaadin.ui.Form; - -@Connect(Form.class) -public class FormConnector extends AbstractComponentContainerConnector - implements Paintable, MayScrollChildren { - - private final ElementResizeListener footerResizeListener = new ElementResizeListener() { - @Override - public void onElementResize(ElementResizeEvent e) { - VForm form = getWidget(); - - int footerHeight; - if (form.footer != null) { - LayoutManager lm = getLayoutManager(); - footerHeight = lm.getOuterHeight(form.footer.getElement()); - } else { - footerHeight = 0; - } - - form.fieldContainer.getStyle().setPaddingBottom(footerHeight, - Unit.PX); - form.footerContainer.getStyle() - .setMarginTop(-footerHeight, Unit.PX); - } - }; - - @Override - public void onUnregister() { - VForm form = getWidget(); - if (form.footer != null) { - getLayoutManager().removeElementResizeListener( - form.footer.getElement(), footerResizeListener); - } - } - - @Override - public boolean delegateCaptionHandling() { - return false; - } - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - getWidget().client = client; - getWidget().id = uidl.getId(); - - if (!isRealUpdate(uidl)) { - return; - } - - boolean legendEmpty = true; - if (getState().getCaption() != null) { - getWidget().caption.setInnerText(getState().getCaption()); - legendEmpty = false; - } else { - getWidget().caption.setInnerText(""); - } - if (getState().getIcon() != null) { - if (getWidget().icon == null) { - getWidget().icon = new Icon(client); - getWidget().legend.insertFirst(getWidget().icon.getElement()); - } - getWidget().icon.setUri(getState().getIcon().getURL()); - legendEmpty = false; - } else { - if (getWidget().icon != null) { - getWidget().legend.removeChild(getWidget().icon.getElement()); - } - } - if (legendEmpty) { - getWidget().addStyleDependentName("nocaption"); - } else { - getWidget().removeStyleDependentName("nocaption"); - } - - if (null != getState().getErrorMessage()) { - getWidget().errorMessage - .updateMessage(getState().getErrorMessage()); - getWidget().errorMessage.setVisible(true); - } else { - getWidget().errorMessage.setVisible(false); - } - - if (getState().hasDescription()) { - getWidget().desc.setInnerHTML(getState().getDescription()); - if (getWidget().desc.getParentElement() == null) { - getWidget().fieldSet.insertAfter(getWidget().desc, - getWidget().legend); - } - } else { - getWidget().desc.setInnerHTML(""); - if (getWidget().desc.getParentElement() != null) { - getWidget().fieldSet.removeChild(getWidget().desc); - } - } - - // first render footer so it will be easier to handle relative height of - // main layout - if (getState().getFooter() != null) { - // render footer - ComponentConnector newFooter = (ComponentConnector) getState() - .getFooter(); - Widget newFooterWidget = newFooter.getWidget(); - if (getWidget().footer == null) { - getLayoutManager().addElementResizeListener( - newFooterWidget.getElement(), footerResizeListener); - getWidget().add(newFooter.getWidget(), - getWidget().footerContainer); - getWidget().footer = newFooterWidget; - } else if (newFooter != getWidget().footer) { - getLayoutManager().removeElementResizeListener( - getWidget().footer.getElement(), footerResizeListener); - getLayoutManager().addElementResizeListener( - newFooterWidget.getElement(), footerResizeListener); - getWidget().remove(getWidget().footer); - getWidget().add(newFooter.getWidget(), - getWidget().footerContainer); - } - getWidget().footer = newFooterWidget; - } else { - if (getWidget().footer != null) { - getLayoutManager().removeElementResizeListener( - getWidget().footer.getElement(), footerResizeListener); - getWidget().remove(getWidget().footer); - getWidget().footer = null; - } - } - - ComponentConnector newLayout = (ComponentConnector) getState() - .getLayout(); - Widget newLayoutWidget = newLayout.getWidget(); - if (getWidget().lo == null) { - // Layout not rendered before - getWidget().lo = newLayoutWidget; - getWidget().add(newLayoutWidget, getWidget().fieldContainer); - } else if (getWidget().lo != newLayoutWidget) { - // Layout has changed - getWidget().remove(getWidget().lo); - getWidget().lo = newLayoutWidget; - getWidget().add(newLayoutWidget, getWidget().fieldContainer); - } - - // also recalculates size of the footer if undefined size form - see - // #3710 - client.runDescendentsLayout(getWidget()); - - // We may have actions attached - if (uidl.getChildCount() >= 1) { - UIDL childUidl = uidl.getChildByTagName("actions"); - if (childUidl != null) { - if (getWidget().shortcutHandler == null) { - getWidget().shortcutHandler = new ShortcutActionHandler( - getConnectorId(), client); - getWidget().keyDownRegistration = getWidget() - .addDomHandler(getWidget(), KeyDownEvent.getType()); - } - getWidget().shortcutHandler.updateActionMap(childUidl); - } - } else if (getWidget().shortcutHandler != null) { - getWidget().keyDownRegistration.removeHandler(); - getWidget().shortcutHandler = null; - getWidget().keyDownRegistration = null; - } - } - - @Override - public void updateCaption(ComponentConnector component) { - // NOP form don't render caption for neither field layout nor footer - // layout - } - - @Override - public VForm getWidget() { - return (VForm) super.getWidget(); - } - - @Override - public boolean isReadOnly() { - return super.isReadOnly() || getState().isPropertyReadOnly(); - } - - @Override - public FormState getState() { - return (FormState) super.getState(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/form/VForm.java b/client/src/com/vaadin/terminal/gwt/client/ui/form/VForm.java deleted file mode 100644 index 8cd7139eed..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/form/VForm.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.form; - -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.ComplexPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.VErrorMessage; -import com.vaadin.terminal.gwt.client.ui.Icon; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler; - -public class VForm extends ComplexPanel implements KeyDownHandler { - - protected String id; - - public static final String CLASSNAME = "v-form"; - - Widget lo; - Element legend = DOM.createLegend(); - Element caption = DOM.createSpan(); - Element desc = DOM.createDiv(); - Icon icon; - VErrorMessage errorMessage = new VErrorMessage(); - - Element fieldContainer = DOM.createDiv(); - - Element footerContainer = DOM.createDiv(); - - Element fieldSet = DOM.createFieldSet(); - - Widget footer; - - ApplicationConnection client; - - ShortcutActionHandler shortcutHandler; - - HandlerRegistration keyDownRegistration; - - public VForm() { - setElement(DOM.createDiv()); - getElement().appendChild(fieldSet); - setStyleName(CLASSNAME); - fieldSet.appendChild(legend); - legend.appendChild(caption); - desc.setClassName("v-form-description"); - fieldSet.appendChild(desc); // Adding description for initial padding - // measurements, removed later if no - // description is set - fieldContainer.setClassName(CLASSNAME + "-content"); - fieldSet.appendChild(fieldContainer); - errorMessage.setVisible(false); - errorMessage.setStyleName(CLASSNAME + "-errormessage"); - fieldSet.appendChild(errorMessage.getElement()); - fieldSet.appendChild(footerContainer); - } - - @Override - public void onKeyDown(KeyDownEvent event) { - shortcutHandler.handleKeyboardEvent(Event.as(event.getNativeEvent())); - } - - @Override - protected void add(Widget child, Element container) { - // Overridden to allow VFormPaintable to call this. Should be removed - // once functionality from VFormPaintable is moved to VForm. - super.add(child, container); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java deleted file mode 100644 index cbe06244af..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.formlayout; - -import com.google.gwt.dom.client.Element; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.MarginInfo; -import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; -import com.vaadin.terminal.gwt.client.TooltipInfo; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.AbstractFieldConnector; -import com.vaadin.terminal.gwt.client.ui.AbstractLayoutConnector; -import com.vaadin.terminal.gwt.client.ui.formlayout.VFormLayout.Caption; -import com.vaadin.terminal.gwt.client.ui.formlayout.VFormLayout.ErrorFlag; -import com.vaadin.terminal.gwt.client.ui.formlayout.VFormLayout.VFormLayoutTable; -import com.vaadin.ui.FormLayout; - -@Connect(FormLayout.class) -public class FormLayoutConnector extends AbstractLayoutConnector { - - @Override - public AbstractOrderedLayoutState getState() { - return (AbstractOrderedLayoutState) super.getState(); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - VFormLayoutTable formLayoutTable = getWidget().table; - - formLayoutTable.setMargins(new MarginInfo(getState() - .getMarginsBitmask())); - formLayoutTable.setSpacing(getState().isSpacing()); - - } - - @Override - public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { - super.onConnectorHierarchyChange(event); - - VFormLayout formLayout = getWidget(); - VFormLayoutTable formLayoutTable = getWidget().table; - - int childId = 0; - - formLayoutTable.setRowCount(getChildComponents().size()); - - for (ComponentConnector child : getChildComponents()) { - Widget childWidget = child.getWidget(); - - Caption caption = formLayoutTable.getCaption(childWidget); - if (caption == null) { - caption = formLayout.new Caption(child); - caption.addClickHandler(formLayoutTable); - } - - ErrorFlag error = formLayoutTable.getError(childWidget); - if (error == null) { - error = formLayout.new ErrorFlag(child); - } - - formLayoutTable.setChild(childId, childWidget, caption, error); - childId++; - } - - for (ComponentConnector oldChild : event.getOldChildren()) { - if (oldChild.getParent() == this) { - continue; - } - - formLayoutTable.cleanReferences(oldChild.getWidget()); - } - - } - - @Override - public void updateCaption(ComponentConnector component) { - getWidget().table.updateCaption(component.getWidget(), - component.getState(), component.isEnabled()); - boolean hideErrors = false; - - // FIXME This incorrectly depends on AbstractFieldConnector - if (component instanceof AbstractFieldConnector) { - hideErrors = ((AbstractFieldConnector) component).getState() - .isHideErrors(); - } - - getWidget().table.updateError(component.getWidget(), component - .getState().getErrorMessage(), hideErrors); - } - - @Override - public VFormLayout getWidget() { - return (VFormLayout) super.getWidget(); - } - - @Override - public TooltipInfo getTooltipInfo(Element element) { - TooltipInfo info = null; - - if (element != getWidget().getElement()) { - Object node = Util.findWidget( - (com.google.gwt.user.client.Element) element, - VFormLayout.Caption.class); - - if (node != null) { - VFormLayout.Caption caption = (VFormLayout.Caption) node; - info = caption.getOwner().getTooltipInfo(element); - } else { - - node = Util.findWidget( - (com.google.gwt.user.client.Element) element, - VFormLayout.ErrorFlag.class); - - if (node != null) { - VFormLayout.ErrorFlag flag = (VFormLayout.ErrorFlag) node; - info = flag.getOwner().getTooltipInfo(element); - } - } - } - - if (info == null) { - info = super.getTooltipInfo(element); - } - - return info; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java deleted file mode 100644 index 7f211aaf9c..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.formlayout; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.FlexTable; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.SimplePanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ComponentState; -import com.vaadin.shared.ui.MarginInfo; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.Focusable; -import com.vaadin.terminal.gwt.client.StyleConstants; -import com.vaadin.terminal.gwt.client.VTooltip; -import com.vaadin.terminal.gwt.client.ui.AbstractFieldConnector; -import com.vaadin.terminal.gwt.client.ui.Icon; - -/** - * Two col Layout that places caption on left col and field on right col - */ -public class VFormLayout extends SimplePanel { - - private final static String CLASSNAME = "v-formlayout"; - - VFormLayoutTable table; - - public VFormLayout() { - super(); - setStyleName(CLASSNAME); - table = new VFormLayoutTable(); - setWidget(table); - } - - /** - * Parses the stylenames from shared state - * - * @param state - * shared state of the component - * @param enabled - * @return An array of stylenames - */ - private String[] getStylesFromState(ComponentState state, boolean enabled) { - List<String> styles = new ArrayList<String>(); - if (state.hasStyles()) { - for (String name : state.getStyles()) { - styles.add(name); - } - } - - if (!enabled) { - styles.add(ApplicationConnection.DISABLED_CLASSNAME); - } - - return styles.toArray(new String[styles.size()]); - } - - public class VFormLayoutTable extends FlexTable implements ClickHandler { - - private static final int COLUMN_CAPTION = 0; - private static final int COLUMN_ERRORFLAG = 1; - private static final int COLUMN_WIDGET = 2; - - private HashMap<Widget, Caption> widgetToCaption = new HashMap<Widget, Caption>(); - private HashMap<Widget, ErrorFlag> widgetToError = new HashMap<Widget, ErrorFlag>(); - - public VFormLayoutTable() { - DOM.setElementProperty(getElement(), "cellPadding", "0"); - DOM.setElementProperty(getElement(), "cellSpacing", "0"); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt - * .event.dom.client.ClickEvent) - */ - @Override - public void onClick(ClickEvent event) { - Caption caption = (Caption) event.getSource(); - if (caption.getOwner() != null) { - if (caption.getOwner() instanceof Focusable) { - ((Focusable) caption.getOwner()).focus(); - } else if (caption.getOwner() instanceof com.google.gwt.user.client.ui.Focusable) { - ((com.google.gwt.user.client.ui.Focusable) caption - .getOwner()).setFocus(true); - } - } - } - - public void setMargins(MarginInfo margins) { - Element margin = getElement(); - setStyleName(margin, CLASSNAME + "-" + StyleConstants.MARGIN_TOP, - margins.hasTop()); - setStyleName(margin, CLASSNAME + "-" + StyleConstants.MARGIN_RIGHT, - margins.hasRight()); - setStyleName(margin, - CLASSNAME + "-" + StyleConstants.MARGIN_BOTTOM, - margins.hasBottom()); - setStyleName(margin, CLASSNAME + "-" + StyleConstants.MARGIN_LEFT, - margins.hasLeft()); - - } - - public void setSpacing(boolean spacing) { - setStyleName(getElement(), CLASSNAME + "-" + "spacing", spacing); - - } - - public void setRowCount(int rowNr) { - for (int i = 0; i < rowNr; i++) { - prepareCell(i, COLUMN_CAPTION); - getCellFormatter().setStyleName(i, COLUMN_CAPTION, - CLASSNAME + "-captioncell"); - - prepareCell(i, 1); - getCellFormatter().setStyleName(i, COLUMN_ERRORFLAG, - CLASSNAME + "-errorcell"); - - prepareCell(i, 2); - getCellFormatter().setStyleName(i, COLUMN_WIDGET, - CLASSNAME + "-contentcell"); - - String rowstyles = CLASSNAME + "-row"; - if (i == 0) { - rowstyles += " " + CLASSNAME + "-firstrow"; - } - if (i == rowNr - 1) { - rowstyles += " " + CLASSNAME + "-lastrow"; - } - - getRowFormatter().setStyleName(i, rowstyles); - - } - while (getRowCount() != rowNr) { - removeRow(rowNr); - } - } - - public void setChild(int rowNr, Widget childWidget, Caption caption, - ErrorFlag error) { - setWidget(rowNr, COLUMN_WIDGET, childWidget); - setWidget(rowNr, COLUMN_CAPTION, caption); - setWidget(rowNr, COLUMN_ERRORFLAG, error); - - widgetToCaption.put(childWidget, caption); - widgetToError.put(childWidget, error); - - } - - public Caption getCaption(Widget childWidget) { - return widgetToCaption.get(childWidget); - } - - public ErrorFlag getError(Widget childWidget) { - return widgetToError.get(childWidget); - } - - public void cleanReferences(Widget oldChildWidget) { - widgetToError.remove(oldChildWidget); - widgetToCaption.remove(oldChildWidget); - - } - - public void updateCaption(Widget widget, ComponentState state, - boolean enabled) { - final Caption c = widgetToCaption.get(widget); - if (c != null) { - c.updateCaption(state, enabled); - } - } - - public void updateError(Widget widget, String errorMessage, - boolean hideErrors) { - final ErrorFlag e = widgetToError.get(widget); - if (e != null) { - e.updateError(errorMessage, hideErrors); - } - - } - - } - - // TODO why duplicated here? - public class Caption extends HTML { - - public static final String CLASSNAME = "v-caption"; - - private final ComponentConnector owner; - - private Element requiredFieldIndicator; - - private Icon icon; - - private Element captionText; - - /** - * - * @param component - * optional owner of caption. If not set, getOwner will - * return null - */ - public Caption(ComponentConnector component) { - super(); - owner = component; - } - - private void setStyles(String[] styles) { - String styleName = CLASSNAME; - - if (styles != null) { - for (String style : styles) { - if (ApplicationConnection.DISABLED_CLASSNAME.equals(style)) { - // Add v-disabled also without classname prefix so - // generic v-disabled CSS rules work - styleName += " " + style; - } - - styleName += " " + CLASSNAME + "-" + style; - } - } - - setStyleName(styleName); - } - - public void updateCaption(ComponentState state, boolean enabled) { - // Update styles as they might have changed when the caption changed - setStyles(getStylesFromState(state, enabled)); - - boolean isEmpty = true; - - if (state.getIcon() != null) { - if (icon == null) { - icon = new Icon(owner.getConnection()); - - DOM.insertChild(getElement(), icon.getElement(), 0); - } - icon.setUri(state.getIcon().getURL()); - isEmpty = false; - } else { - if (icon != null) { - DOM.removeChild(getElement(), icon.getElement()); - icon = null; - } - - } - - if (state.getCaption() != null) { - if (captionText == null) { - captionText = DOM.createSpan(); - DOM.insertChild(getElement(), captionText, icon == null ? 0 - : 1); - } - String c = state.getCaption(); - if (c == null) { - c = ""; - } else { - isEmpty = false; - } - DOM.setInnerText(captionText, c); - } else { - // TODO should span also be removed - } - - if (state.hasDescription() && captionText != null) { - addStyleDependentName("hasdescription"); - } else { - removeStyleDependentName("hasdescription"); - } - - boolean required = owner instanceof AbstractFieldConnector - && ((AbstractFieldConnector) owner).isRequired(); - if (required) { - if (requiredFieldIndicator == null) { - requiredFieldIndicator = DOM.createSpan(); - DOM.setInnerText(requiredFieldIndicator, "*"); - DOM.setElementProperty(requiredFieldIndicator, "className", - "v-required-field-indicator"); - DOM.appendChild(getElement(), requiredFieldIndicator); - } - } else { - if (requiredFieldIndicator != null) { - DOM.removeChild(getElement(), requiredFieldIndicator); - requiredFieldIndicator = null; - } - } - - // Workaround for IE weirdness, sometimes returns bad height in some - // circumstances when Caption is empty. See #1444 - // IE7 bugs more often. I wonder what happens when IE8 arrives... - // FIXME: This could be unnecessary for IE8+ - if (BrowserInfo.get().isIE()) { - if (isEmpty) { - setHeight("0px"); - DOM.setStyleAttribute(getElement(), "overflow", "hidden"); - } else { - setHeight(""); - DOM.setStyleAttribute(getElement(), "overflow", ""); - } - - } - - } - - /** - * Returns Paintable for which this Caption belongs to. - * - * @return owner Widget - */ - public ComponentConnector getOwner() { - return owner; - } - } - - class ErrorFlag extends HTML { - private static final String CLASSNAME = VFormLayout.CLASSNAME - + "-error-indicator"; - Element errorIndicatorElement; - - private ComponentConnector owner; - - public ErrorFlag(ComponentConnector owner) { - setStyleName(CLASSNAME); - sinkEvents(VTooltip.TOOLTIP_EVENTS); - this.owner = owner; - } - - public ComponentConnector getOwner() { - return owner; - } - - public void updateError(String errorMessage, boolean hideErrors) { - boolean showError = null != errorMessage; - if (hideErrors) { - showError = false; - } - - if (showError) { - if (errorIndicatorElement == null) { - errorIndicatorElement = DOM.createDiv(); - DOM.setInnerHTML(errorIndicatorElement, " "); - DOM.setElementProperty(errorIndicatorElement, "className", - "v-errorindicator"); - DOM.appendChild(getElement(), errorIndicatorElement); - } - - } else if (errorIndicatorElement != null) { - DOM.removeChild(getElement(), errorIndicatorElement); - errorIndicatorElement = null; - } - } - - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java deleted file mode 100644 index 9a2732e408..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.gridlayout; - -import java.util.Iterator; - -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ui.AlignmentInfo; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.LayoutClickRpc; -import com.vaadin.shared.ui.MarginInfo; -import com.vaadin.shared.ui.gridlayout.GridLayoutServerRpc; -import com.vaadin.shared.ui.gridlayout.GridLayoutState; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.DirectionalManagedLayout; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.VCaption; -import com.vaadin.terminal.gwt.client.communication.RpcProxy; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector; -import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler; -import com.vaadin.terminal.gwt.client.ui.gridlayout.VGridLayout.Cell; -import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot; -import com.vaadin.ui.GridLayout; - -@Connect(GridLayout.class) -public class GridLayoutConnector extends AbstractComponentContainerConnector - implements Paintable, DirectionalManagedLayout { - - private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler( - this) { - - @Override - protected ComponentConnector getChildComponent(Element element) { - return getWidget().getComponent(element); - } - - @Override - protected LayoutClickRpc getLayoutClickRPC() { - return rpc; - }; - - }; - - private GridLayoutServerRpc rpc; - private boolean needCaptionUpdate = false; - - @Override - public void init() { - super.init(); - rpc = RpcProxy.create(GridLayoutServerRpc.class, this); - getLayoutManager().registerDependency(this, - getWidget().spacingMeasureElement); - } - - @Override - public void onUnregister() { - VGridLayout layout = getWidget(); - getLayoutManager().unregisterDependency(this, - layout.spacingMeasureElement); - - // Unregister caption size dependencies - for (ComponentConnector child : getChildComponents()) { - Cell cell = layout.widgetToCell.get(child.getWidget()); - cell.slot.setCaption(null); - } - } - - @Override - public GridLayoutState getState() { - return (GridLayoutState) super.getState(); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - clickEventHandler.handleEventHandlerRegistration(); - - } - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - VGridLayout layout = getWidget(); - layout.client = client; - - if (!isRealUpdate(uidl)) { - return; - } - - int cols = getState().getColumns(); - int rows = getState().getRows(); - - layout.columnWidths = new int[cols]; - layout.rowHeights = new int[rows]; - - layout.setSize(rows, cols); - - final int[] alignments = uidl.getIntArrayAttribute("alignments"); - int alignmentIndex = 0; - - for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) { - final UIDL r = (UIDL) i.next(); - if ("gr".equals(r.getTag())) { - for (final Iterator<?> j = r.getChildIterator(); j.hasNext();) { - final UIDL cellUidl = (UIDL) j.next(); - if ("gc".equals(cellUidl.getTag())) { - int row = cellUidl.getIntAttribute("y"); - int col = cellUidl.getIntAttribute("x"); - - Widget previousWidget = null; - - Cell cell = layout.getCell(row, col); - if (cell != null && cell.slot != null) { - // This is an update. Track if the widget changes - // and update the caption if that happens. This - // workaround can be removed once the DOM update is - // done in onContainerHierarchyChange - previousWidget = cell.slot.getWidget(); - } - - cell = layout.createCell(row, col); - - cell.updateFromUidl(cellUidl); - - if (cell.hasContent()) { - cell.setAlignment(new AlignmentInfo( - alignments[alignmentIndex++])); - if (cell.slot.getWidget() != previousWidget) { - // Widget changed or widget moved from another - // slot. Update its caption as the widget might - // have called updateCaption when the widget was - // still in its old slot. This workaround can be - // removed once the DOM update - // is done in onContainerHierarchyChange - updateCaption(ConnectorMap.get(getConnection()) - .getConnector(cell.slot.getWidget())); - } - } - } - } - } - } - - layout.colExpandRatioArray = uidl.getIntArrayAttribute("colExpand"); - layout.rowExpandRatioArray = uidl.getIntArrayAttribute("rowExpand"); - - layout.updateMarginStyleNames(new MarginInfo(getState() - .getMarginsBitmask())); - - layout.updateSpacingStyleName(getState().isSpacing()); - - if (needCaptionUpdate) { - needCaptionUpdate = false; - - for (ComponentConnector child : getChildComponents()) { - updateCaption(child); - } - } - getLayoutManager().setNeedsLayout(this); - } - - @Override - public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { - super.onConnectorHierarchyChange(event); - - VGridLayout layout = getWidget(); - - // clean non rendered components - for (ComponentConnector oldChild : event.getOldChildren()) { - if (oldChild.getParent() == this) { - continue; - } - - Widget childWidget = oldChild.getWidget(); - layout.remove(childWidget); - - Cell cell = layout.widgetToCell.remove(childWidget); - cell.slot.setCaption(null); - cell.slot.getWrapperElement().removeFromParent(); - cell.slot = null; - } - - } - - @Override - public void updateCaption(ComponentConnector childConnector) { - if (!childConnector.delegateCaptionHandling()) { - // Check not required by interface but by workarounds in this class - // when updateCaption is explicitly called for all children. - return; - } - - VGridLayout layout = getWidget(); - Cell cell = layout.widgetToCell.get(childConnector.getWidget()); - if (cell == null) { - // workaround before updateFromUidl is removed. We currently update - // the captions at the end of updateFromUidl instead of immediately - // because the DOM has not been set up at this point (as it is done - // in updateFromUidl) - needCaptionUpdate = true; - return; - } - if (VCaption.isNeeded(childConnector.getState())) { - VLayoutSlot layoutSlot = cell.slot; - VCaption caption = layoutSlot.getCaption(); - if (caption == null) { - caption = new VCaption(childConnector, getConnection()); - - Widget widget = childConnector.getWidget(); - - layout.setCaption(widget, caption); - } - caption.updateCaption(); - } else { - layout.setCaption(childConnector.getWidget(), null); - } - } - - @Override - public VGridLayout getWidget() { - return (VGridLayout) super.getWidget(); - } - - @Override - public void layoutVertically() { - getWidget().updateHeight(); - } - - @Override - public void layoutHorizontally() { - getWidget().updateWidth(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/gridlayout/VGridLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/gridlayout/VGridLayout.java deleted file mode 100644 index ef44964da7..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/gridlayout/VGridLayout.java +++ /dev/null @@ -1,714 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.gridlayout; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; - -import com.google.gwt.dom.client.DivElement; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Position; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.ComplexPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ui.AlignmentInfo; -import com.vaadin.shared.ui.MarginInfo; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.LayoutManager; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VCaption; -import com.vaadin.terminal.gwt.client.ui.layout.ComponentConnectorLayoutSlot; -import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot; - -public class VGridLayout extends ComplexPanel { - - public static final String CLASSNAME = "v-gridlayout"; - - ApplicationConnection client; - - HashMap<Widget, Cell> widgetToCell = new HashMap<Widget, Cell>(); - - int[] columnWidths; - int[] rowHeights; - - int[] colExpandRatioArray; - - int[] rowExpandRatioArray; - - int[] minColumnWidths; - - private int[] minRowHeights; - - DivElement spacingMeasureElement; - - public VGridLayout() { - super(); - setElement(Document.get().createDivElement()); - - spacingMeasureElement = Document.get().createDivElement(); - Style spacingStyle = spacingMeasureElement.getStyle(); - spacingStyle.setPosition(Position.ABSOLUTE); - getElement().appendChild(spacingMeasureElement); - - setStyleName(CLASSNAME); - } - - private GridLayoutConnector getConnector() { - return (GridLayoutConnector) ConnectorMap.get(client) - .getConnector(this); - } - - /** - * Returns the column widths measured in pixels - * - * @return - */ - protected int[] getColumnWidths() { - return columnWidths; - } - - /** - * Returns the row heights measured in pixels - * - * @return - */ - protected int[] getRowHeights() { - return rowHeights; - } - - /** - * Returns the spacing between the cells horizontally in pixels - * - * @return - */ - protected int getHorizontalSpacing() { - return LayoutManager.get(client).getOuterWidth(spacingMeasureElement); - } - - /** - * Returns the spacing between the cells vertically in pixels - * - * @return - */ - protected int getVerticalSpacing() { - return LayoutManager.get(client).getOuterHeight(spacingMeasureElement); - } - - static int[] cloneArray(int[] toBeCloned) { - int[] clone = new int[toBeCloned.length]; - for (int i = 0; i < clone.length; i++) { - clone[i] = toBeCloned[i] * 1; - } - return clone; - } - - void expandRows() { - if (!isUndefinedHeight()) { - int usedSpace = minRowHeights[0]; - int verticalSpacing = getVerticalSpacing(); - for (int i = 1; i < minRowHeights.length; i++) { - usedSpace += verticalSpacing + minRowHeights[i]; - } - int availableSpace = LayoutManager.get(client).getInnerHeight( - getElement()); - int excessSpace = availableSpace - usedSpace; - int distributed = 0; - if (excessSpace > 0) { - for (int i = 0; i < rowHeights.length; i++) { - int ew = excessSpace * rowExpandRatioArray[i] / 1000; - rowHeights[i] = minRowHeights[i] + ew; - distributed += ew; - } - excessSpace -= distributed; - int c = 0; - while (excessSpace > 0) { - rowHeights[c % rowHeights.length]++; - excessSpace--; - c++; - } - } - } - } - - void updateHeight() { - // Detect minimum heights & calculate spans - detectRowHeights(); - - // Expand - expandRows(); - - // Position - layoutCellsVertically(); - } - - void updateWidth() { - // Detect widths & calculate spans - detectColWidths(); - // Expand - expandColumns(); - // Position - layoutCellsHorizontally(); - - } - - void expandColumns() { - if (!isUndefinedWidth()) { - int usedSpace = minColumnWidths[0]; - int horizontalSpacing = getHorizontalSpacing(); - for (int i = 1; i < minColumnWidths.length; i++) { - usedSpace += horizontalSpacing + minColumnWidths[i]; - } - - int availableSpace = LayoutManager.get(client).getInnerWidth( - getElement()); - int excessSpace = availableSpace - usedSpace; - int distributed = 0; - if (excessSpace > 0) { - for (int i = 0; i < columnWidths.length; i++) { - int ew = excessSpace * colExpandRatioArray[i] / 1000; - columnWidths[i] = minColumnWidths[i] + ew; - distributed += ew; - } - excessSpace -= distributed; - int c = 0; - while (excessSpace > 0) { - columnWidths[c % columnWidths.length]++; - excessSpace--; - c++; - } - } - } - } - - void layoutCellsVertically() { - int verticalSpacing = getVerticalSpacing(); - LayoutManager layoutManager = LayoutManager.get(client); - Element element = getElement(); - int paddingTop = layoutManager.getPaddingTop(element); - int paddingBottom = layoutManager.getPaddingBottom(element); - int y = paddingTop; - - for (int i = 0; i < cells.length; i++) { - y = paddingTop; - for (int j = 0; j < cells[i].length; j++) { - Cell cell = cells[i][j]; - if (cell != null) { - int reservedMargin; - if (cell.rowspan + j >= cells[i].length) { - // Make room for layout padding for cells reaching the - // bottom of the layout - reservedMargin = paddingBottom; - } else { - reservedMargin = 0; - } - cell.layoutVertically(y, reservedMargin); - } - y += rowHeights[j] + verticalSpacing; - } - } - - if (isUndefinedHeight()) { - int outerHeight = y - verticalSpacing - + layoutManager.getPaddingBottom(element) - + layoutManager.getBorderHeight(element); - element.getStyle().setHeight(outerHeight, Unit.PX); - getConnector().getLayoutManager().reportOuterHeight(getConnector(), - outerHeight); - } - } - - void layoutCellsHorizontally() { - LayoutManager layoutManager = LayoutManager.get(client); - Element element = getElement(); - int x = layoutManager.getPaddingLeft(element); - int paddingRight = layoutManager.getPaddingRight(element); - int horizontalSpacing = getHorizontalSpacing(); - for (int i = 0; i < cells.length; i++) { - for (int j = 0; j < cells[i].length; j++) { - Cell cell = cells[i][j]; - if (cell != null) { - int reservedMargin; - // Make room for layout padding for cells reaching the - // right edge of the layout - if (i + cell.colspan >= cells.length) { - reservedMargin = paddingRight; - } else { - reservedMargin = 0; - } - cell.layoutHorizontally(x, reservedMargin); - } - } - x += columnWidths[i] + horizontalSpacing; - } - - if (isUndefinedWidth()) { - int outerWidth = x - horizontalSpacing - + layoutManager.getPaddingRight(element) - + layoutManager.getBorderWidth(element); - element.getStyle().setWidth(outerWidth, Unit.PX); - getConnector().getLayoutManager().reportOuterWidth(getConnector(), - outerWidth); - } - } - - private boolean isUndefinedHeight() { - return getConnector().isUndefinedHeight(); - } - - private boolean isUndefinedWidth() { - return getConnector().isUndefinedWidth(); - } - - private void detectRowHeights() { - for (int i = 0; i < rowHeights.length; i++) { - rowHeights[i] = 0; - } - - // collect min rowheight from non-rowspanned cells - for (int i = 0; i < cells.length; i++) { - for (int j = 0; j < cells[i].length; j++) { - Cell cell = cells[i][j]; - if (cell != null) { - if (cell.rowspan == 1) { - if (!cell.hasRelativeHeight() - && rowHeights[j] < cell.getHeight()) { - rowHeights[j] = cell.getHeight(); - } - } else { - storeRowSpannedCell(cell); - } - } - } - } - - distributeRowSpanHeights(); - - minRowHeights = cloneArray(rowHeights); - } - - private void detectColWidths() { - // collect min colwidths from non-colspanned cells - for (int i = 0; i < columnWidths.length; i++) { - columnWidths[i] = 0; - } - - for (int i = 0; i < cells.length; i++) { - for (int j = 0; j < cells[i].length; j++) { - Cell cell = cells[i][j]; - if (cell != null) { - if (cell.colspan == 1) { - if (!cell.hasRelativeWidth() - && columnWidths[i] < cell.getWidth()) { - columnWidths[i] = cell.getWidth(); - } - } else { - storeColSpannedCell(cell); - } - } - } - } - - distributeColSpanWidths(); - - minColumnWidths = cloneArray(columnWidths); - } - - private void storeRowSpannedCell(Cell cell) { - SpanList l = null; - for (SpanList list : rowSpans) { - if (list.span < cell.rowspan) { - continue; - } else { - // insert before this - l = list; - break; - } - } - if (l == null) { - l = new SpanList(cell.rowspan); - rowSpans.add(l); - } else if (l.span != cell.rowspan) { - SpanList newL = new SpanList(cell.rowspan); - rowSpans.add(rowSpans.indexOf(l), newL); - l = newL; - } - l.cells.add(cell); - } - - /** - * Iterates colspanned cells, ensures cols have enough space to accommodate - * them - */ - void distributeColSpanWidths() { - for (SpanList list : colSpans) { - for (Cell cell : list.cells) { - // cells with relative content may return non 0 here if on - // subsequent renders - int width = cell.hasRelativeWidth() ? 0 : cell.getWidth(); - distributeSpanSize(columnWidths, cell.col, cell.colspan, - getHorizontalSpacing(), width, colExpandRatioArray); - } - } - } - - /** - * Iterates rowspanned cells, ensures rows have enough space to accommodate - * them - */ - private void distributeRowSpanHeights() { - for (SpanList list : rowSpans) { - for (Cell cell : list.cells) { - // cells with relative content may return non 0 here if on - // subsequent renders - int height = cell.hasRelativeHeight() ? 0 : cell.getHeight(); - distributeSpanSize(rowHeights, cell.row, cell.rowspan, - getVerticalSpacing(), height, rowExpandRatioArray); - } - } - } - - private static void distributeSpanSize(int[] dimensions, - int spanStartIndex, int spanSize, int spacingSize, int size, - int[] expansionRatios) { - int allocated = dimensions[spanStartIndex]; - for (int i = 1; i < spanSize; i++) { - allocated += spacingSize + dimensions[spanStartIndex + i]; - } - if (allocated < size) { - // dimensions needs to be expanded due spanned cell - int neededExtraSpace = size - allocated; - int allocatedExtraSpace = 0; - - // Divide space according to expansion ratios if any span has a - // ratio - int totalExpansion = 0; - for (int i = 0; i < spanSize; i++) { - int itemIndex = spanStartIndex + i; - totalExpansion += expansionRatios[itemIndex]; - } - - for (int i = 0; i < spanSize; i++) { - int itemIndex = spanStartIndex + i; - int expansion; - if (totalExpansion == 0) { - // Divide equally among all cells if there are no - // expansion ratios - expansion = neededExtraSpace / spanSize; - } else { - expansion = neededExtraSpace * expansionRatios[itemIndex] - / totalExpansion; - } - dimensions[itemIndex] += expansion; - allocatedExtraSpace += expansion; - } - - // We might still miss a couple of pixels because of - // rounding errors... - if (neededExtraSpace > allocatedExtraSpace) { - for (int i = 0; i < spanSize; i++) { - // Add one pixel to every cell until we have - // compensated for any rounding error - int itemIndex = spanStartIndex + i; - dimensions[itemIndex] += 1; - allocatedExtraSpace += 1; - if (neededExtraSpace == allocatedExtraSpace) { - break; - } - } - } - } - } - - private LinkedList<SpanList> colSpans = new LinkedList<SpanList>(); - private LinkedList<SpanList> rowSpans = new LinkedList<SpanList>(); - - private class SpanList { - final int span; - List<Cell> cells = new LinkedList<Cell>(); - - public SpanList(int span) { - this.span = span; - } - } - - void storeColSpannedCell(Cell cell) { - SpanList l = null; - for (SpanList list : colSpans) { - if (list.span < cell.colspan) { - continue; - } else { - // insert before this - l = list; - break; - } - } - if (l == null) { - l = new SpanList(cell.colspan); - colSpans.add(l); - } else if (l.span != cell.colspan) { - - SpanList newL = new SpanList(cell.colspan); - colSpans.add(colSpans.indexOf(l), newL); - l = newL; - } - l.cells.add(cell); - } - - Cell[][] cells; - - /** - * Private helper class. - */ - class Cell { - public Cell(int row, int col) { - this.row = row; - this.col = col; - } - - public boolean hasContent() { - return hasContent; - } - - public boolean hasRelativeHeight() { - if (slot != null) { - return slot.getChild().isRelativeHeight(); - } else { - return true; - } - } - - /** - * @return total of spanned cols - */ - private int getAvailableWidth() { - int width = columnWidths[col]; - for (int i = 1; i < colspan; i++) { - width += getHorizontalSpacing() + columnWidths[col + i]; - } - return width; - } - - /** - * @return total of spanned rows - */ - private int getAvailableHeight() { - int height = rowHeights[row]; - for (int i = 1; i < rowspan; i++) { - height += getVerticalSpacing() + rowHeights[row + i]; - } - return height; - } - - public void layoutHorizontally(int x, int marginRight) { - if (slot != null) { - slot.positionHorizontally(x, getAvailableWidth(), marginRight); - } - } - - public void layoutVertically(int y, int marginBottom) { - if (slot != null) { - slot.positionVertically(y, getAvailableHeight(), marginBottom); - } - } - - public int getWidth() { - if (slot != null) { - return slot.getUsedWidth(); - } else { - return 0; - } - } - - public int getHeight() { - if (slot != null) { - return slot.getUsedHeight(); - } else { - return 0; - } - } - - protected boolean hasRelativeWidth() { - if (slot != null) { - return slot.getChild().isRelativeWidth(); - } else { - return true; - } - } - - final int row; - final int col; - int colspan = 1; - int rowspan = 1; - - private boolean hasContent; - - private AlignmentInfo alignment; - - ComponentConnectorLayoutSlot slot; - - public void updateFromUidl(UIDL cellUidl) { - // Set cell width - colspan = cellUidl.hasAttribute("w") ? cellUidl - .getIntAttribute("w") : 1; - // Set cell height - rowspan = cellUidl.hasAttribute("h") ? cellUidl - .getIntAttribute("h") : 1; - // ensure we will lose reference to old cells, now overlapped by - // this cell - for (int i = 0; i < colspan; i++) { - for (int j = 0; j < rowspan; j++) { - if (i > 0 || j > 0) { - cells[col + i][row + j] = null; - } - } - } - - UIDL childUidl = cellUidl.getChildUIDL(0); // we are interested - // about childUidl - hasContent = childUidl != null; - if (hasContent) { - ComponentConnector childConnector = client - .getPaintable(childUidl); - - if (slot == null || slot.getChild() != childConnector) { - slot = new ComponentConnectorLayoutSlot(CLASSNAME, - childConnector, getConnector()); - if (childConnector.isRelativeWidth()) { - slot.getWrapperElement().getStyle() - .setWidth(100, Unit.PCT); - } - Element slotWrapper = slot.getWrapperElement(); - getElement().appendChild(slotWrapper); - - Widget widget = childConnector.getWidget(); - insert(widget, slotWrapper, getWidgetCount(), false); - Cell oldCell = widgetToCell.put(widget, this); - if (oldCell != null) { - oldCell.slot.getWrapperElement().removeFromParent(); - oldCell.slot = null; - } - } - - } - } - - public void setAlignment(AlignmentInfo alignmentInfo) { - slot.setAlignment(alignmentInfo); - } - } - - Cell getCell(int row, int col) { - return cells[col][row]; - } - - /** - * Creates a new Cell with the given coordinates. If an existing cell was - * found, returns that one. - * - * @param row - * @param col - * @return - */ - Cell createCell(int row, int col) { - Cell cell = getCell(row, col); - if (cell == null) { - cell = new Cell(row, col); - cells[col][row] = cell; - } - return cell; - } - - /** - * Returns the deepest nested child component which contains "element". The - * child component is also returned if "element" is part of its caption. - * - * @param element - * An element that is a nested sub element of the root element in - * this layout - * @return The Paintable which the element is a part of. Null if the element - * belongs to the layout and not to a child. - */ - ComponentConnector getComponent(Element element) { - return Util.getConnectorForElement(client, this, element); - } - - void setCaption(Widget widget, VCaption caption) { - VLayoutSlot slot = widgetToCell.get(widget).slot; - - if (caption != null) { - // Logical attach. - getChildren().add(caption); - } - - // Physical attach if not null, also removes old caption - slot.setCaption(caption); - - if (caption != null) { - // Adopt. - adopt(caption); - } - } - - private void togglePrefixedStyleName(String name, boolean enabled) { - if (enabled) { - addStyleDependentName(name); - } else { - removeStyleDependentName(name); - } - } - - void updateMarginStyleNames(MarginInfo marginInfo) { - togglePrefixedStyleName("margin-top", marginInfo.hasTop()); - togglePrefixedStyleName("margin-right", marginInfo.hasRight()); - togglePrefixedStyleName("margin-bottom", marginInfo.hasBottom()); - togglePrefixedStyleName("margin-left", marginInfo.hasLeft()); - } - - void updateSpacingStyleName(boolean spacingEnabled) { - String styleName = getStylePrimaryName(); - if (spacingEnabled) { - spacingMeasureElement.addClassName(styleName + "-spacing-on"); - spacingMeasureElement.removeClassName(styleName + "-spacing-off"); - } else { - spacingMeasureElement.removeClassName(styleName + "-spacing-on"); - spacingMeasureElement.addClassName(styleName + "-spacing-off"); - } - } - - public void setSize(int rows, int cols) { - if (cells == null) { - cells = new Cell[cols][rows]; - } else if (cells.length != cols || cells[0].length != rows) { - Cell[][] newCells = new Cell[cols][rows]; - for (int i = 0; i < cells.length; i++) { - for (int j = 0; j < cells[i].length; j++) { - if (i < cols && j < rows) { - newCells[i][j] = cells[i][j]; - } - } - } - cells = newCells; - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/image/ImageConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/image/ImageConnector.java deleted file mode 100644 index d36e224a03..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/image/ImageConnector.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.vaadin.terminal.gwt.client.ui.image; - -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.event.dom.client.LoadEvent; -import com.google.gwt.event.dom.client.LoadHandler; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.image.ImageServerRpc; -import com.vaadin.shared.ui.image.ImageState; -import com.vaadin.terminal.gwt.client.communication.RpcProxy; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; -import com.vaadin.terminal.gwt.client.ui.ClickEventHandler; - -@Connect(com.vaadin.ui.Image.class) -public class ImageConnector extends AbstractComponentConnector { - - ImageServerRpc rpc; - - @Override - protected void init() { - super.init(); - rpc = RpcProxy.create(ImageServerRpc.class, this); - getWidget().addHandler(new LoadHandler() { - - @Override - public void onLoad(LoadEvent event) { - getLayoutManager().setNeedsMeasure(ImageConnector.this); - } - - }, LoadEvent.getType()); - } - - @Override - public VImage getWidget() { - return (VImage) super.getWidget(); - } - - @Override - public ImageState getState() { - return (ImageState) super.getState(); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - clickEventHandler.handleEventHandlerRegistration(); - - getWidget().setUrl( - getState().getSource() != null ? getState().getSource() - .getURL() : null); - getWidget().setAltText(getState().getAlternateText()); - } - - protected final ClickEventHandler clickEventHandler = new ClickEventHandler( - this) { - - @Override - protected void fireClick(NativeEvent event, - MouseEventDetails mouseDetails) { - rpc.click(mouseDetails); - } - - }; - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/image/VImage.java b/client/src/com/vaadin/terminal/gwt/client/ui/image/VImage.java deleted file mode 100644 index 7e6b77ed4a..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/image/VImage.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.vaadin.terminal.gwt.client.ui.image; - -import com.google.gwt.user.client.ui.Image; - -public class VImage extends Image { - - public VImage() { - setStylePrimaryName("v-image"); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/label/LabelConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/label/LabelConnector.java deleted file mode 100644 index 57f8c16952..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/label/LabelConnector.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.label; - -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.PreElement; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.shared.ui.label.LabelState; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; -import com.vaadin.ui.Label; - -@Connect(value = Label.class, loadStyle = LoadStyle.EAGER) -public class LabelConnector extends AbstractComponentConnector { - - @Override - public LabelState getState() { - return (LabelState) super.getState(); - } - - @Override - protected void init() { - super.init(); - getWidget().setConnection(getConnection()); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - boolean sinkOnloads = false; - switch (getState().contentMode) { - case PREFORMATTED: - PreElement preElement = Document.get().createPreElement(); - preElement.setInnerText(getState().text); - // clear existing content - getWidget().setHTML(""); - // add preformatted text to dom - getWidget().getElement().appendChild(preElement); - break; - - case TEXT: - getWidget().setText(getState().text); - break; - - case XHTML: - case RAW: - sinkOnloads = true; - case XML: - getWidget().setHTML(getState().text); - break; - default: - getWidget().setText(""); - break; - - } - if (sinkOnloads) { - Util.sinkOnloadForImages(getWidget().getElement()); - } - } - - @Override - public VLabel getWidget() { - return (VLabel) super.getWidget(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java b/client/src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java deleted file mode 100644 index dc23807166..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.label; - -import com.google.gwt.dom.client.Style.Display; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.HTML; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VTooltip; - -public class VLabel extends HTML { - - public static final String CLASSNAME = "v-label"; - private static final String CLASSNAME_UNDEFINED_WIDTH = "v-label-undef-w"; - - private ApplicationConnection connection; - - public VLabel() { - super(); - setStyleName(CLASSNAME); - sinkEvents(VTooltip.TOOLTIP_EVENTS); - } - - public VLabel(String text) { - super(text); - setStyleName(CLASSNAME); - } - - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - if (event.getTypeInt() == Event.ONLOAD) { - Util.notifyParentOfSizeChange(this, true); - event.stopPropagation(); - return; - } - } - - @Override - public void setWidth(String width) { - super.setWidth(width); - if (width == null || width.equals("")) { - setStyleName(getElement(), CLASSNAME_UNDEFINED_WIDTH, true); - getElement().getStyle().setDisplay(Display.INLINE_BLOCK); - } else { - setStyleName(getElement(), CLASSNAME_UNDEFINED_WIDTH, false); - getElement().getStyle().clearDisplay(); - } - } - - @Override - public void setText(String text) { - if (BrowserInfo.get().isIE8()) { - // #3983 - IE8 incorrectly replaces \n with <br> so we do the - // escaping manually and set as HTML - super.setHTML(Util.escapeHTML(text)); - } else { - super.setText(text); - } - } - - void setConnection(ApplicationConnection client) { - connection = client; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/layout/ComponentConnectorLayoutSlot.java b/client/src/com/vaadin/terminal/gwt/client/ui/layout/ComponentConnectorLayoutSlot.java deleted file mode 100644 index b1f381c33d..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/layout/ComponentConnectorLayoutSlot.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.layout; - -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.LayoutManager; -import com.vaadin.terminal.gwt.client.VCaption; -import com.vaadin.terminal.gwt.client.ui.ManagedLayout; - -public class ComponentConnectorLayoutSlot extends VLayoutSlot { - - final ComponentConnector child; - final ManagedLayout layout; - - public ComponentConnectorLayoutSlot(String baseClassName, - ComponentConnector child, ManagedLayout layout) { - super(baseClassName, child.getWidget()); - this.child = child; - this.layout = layout; - } - - public ComponentConnector getChild() { - return child; - } - - @Override - protected int getCaptionHeight() { - VCaption caption = getCaption(); - return caption != null ? getLayoutManager().getOuterHeight( - caption.getElement()) : 0; - } - - @Override - protected int getCaptionWidth() { - VCaption caption = getCaption(); - return caption != null ? getLayoutManager().getOuterWidth( - caption.getElement()) : 0; - } - - public LayoutManager getLayoutManager() { - return layout.getLayoutManager(); - } - - @Override - public void setCaption(VCaption caption) { - VCaption oldCaption = getCaption(); - if (oldCaption != null) { - getLayoutManager().unregisterDependency(layout, - oldCaption.getElement()); - } - super.setCaption(caption); - if (caption != null) { - getLayoutManager().registerDependency( - (ManagedLayout) child.getParent(), caption.getElement()); - } - } - - @Override - protected void reportActualRelativeHeight(int allocatedHeight) { - getLayoutManager().reportOuterHeight(child, allocatedHeight); - } - - @Override - protected void reportActualRelativeWidth(int allocatedWidth) { - getLayoutManager().reportOuterWidth(child, allocatedWidth); - } - - @Override - public int getWidgetHeight() { - return getLayoutManager() - .getOuterHeight(child.getWidget().getElement()); - } - - @Override - public int getWidgetWidth() { - return getLayoutManager().getOuterWidth(child.getWidget().getElement()); - } - - @Override - public boolean isUndefinedHeight() { - return child.isUndefinedHeight(); - } - - @Override - public boolean isUndefinedWidth() { - return child.isUndefinedWidth(); - } - - @Override - public boolean isRelativeHeight() { - return child.isRelativeHeight(); - } - - @Override - public boolean isRelativeWidth() { - return child.isRelativeWidth(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/layout/ElementResizeEvent.java b/client/src/com/vaadin/terminal/gwt/client/ui/layout/ElementResizeEvent.java deleted file mode 100644 index d9733875f3..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/layout/ElementResizeEvent.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.layout; - -import com.google.gwt.dom.client.Element; -import com.vaadin.terminal.gwt.client.LayoutManager; - -public class ElementResizeEvent { - private final Element element; - private final LayoutManager layoutManager; - - public ElementResizeEvent(LayoutManager layoutManager, Element element) { - this.layoutManager = layoutManager; - this.element = element; - } - - public Element getElement() { - return element; - } - - public LayoutManager getLayoutManager() { - return layoutManager; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/layout/ElementResizeListener.java b/client/src/com/vaadin/terminal/gwt/client/ui/layout/ElementResizeListener.java deleted file mode 100644 index 15b3a5517d..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/layout/ElementResizeListener.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.layout; - -public interface ElementResizeListener { - public void onElementResize(ElementResizeEvent e); -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java b/client/src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java deleted file mode 100644 index 2bf789fd50..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java +++ /dev/null @@ -1,532 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.layout; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import com.vaadin.shared.ComponentState; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ComponentContainerConnector; -import com.vaadin.terminal.gwt.client.ServerConnector; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.ui.ManagedLayout; - -public class LayoutDependencyTree { - private class LayoutDependency { - private final ComponentConnector connector; - private final int direction; - - private boolean needsLayout = false; - private boolean needsMeasure = false; - - private boolean scrollingParentCached = false; - private ComponentConnector scrollingBoundary = null; - - private Set<ComponentConnector> measureBlockers = new HashSet<ComponentConnector>(); - private Set<ComponentConnector> layoutBlockers = new HashSet<ComponentConnector>(); - - public LayoutDependency(ComponentConnector connector, int direction) { - this.connector = connector; - this.direction = direction; - } - - private void addLayoutBlocker(ComponentConnector blocker) { - boolean blockerAdded = layoutBlockers.add(blocker); - if (blockerAdded && layoutBlockers.size() == 1) { - if (needsLayout) { - getLayoutQueue(direction).remove(connector); - } else { - // Propagation already done if needsLayout is set - propagatePotentialLayout(); - } - } - } - - private void removeLayoutBlocker(ComponentConnector blocker) { - boolean removed = layoutBlockers.remove(blocker); - if (removed && layoutBlockers.isEmpty()) { - if (needsLayout) { - getLayoutQueue(direction).add((ManagedLayout) connector); - } else { - propagateNoUpcomingLayout(); - } - } - } - - private void addMeasureBlocker(ComponentConnector blocker) { - boolean blockerAdded = measureBlockers.add(blocker); - if (blockerAdded && measureBlockers.size() == 1) { - if (needsMeasure) { - getMeasureQueue(direction).remove(connector); - } else { - propagatePotentialResize(); - } - } - } - - private void removeMeasureBlocker(ComponentConnector blocker) { - boolean removed = measureBlockers.remove(blocker); - if (removed && measureBlockers.isEmpty()) { - if (needsMeasure) { - getMeasureQueue(direction).add(connector); - } else { - propagateNoUpcomingResize(); - } - } - } - - public void setNeedsMeasure(boolean needsMeasure) { - if (needsMeasure && !this.needsMeasure) { - // If enabling needsMeasure - this.needsMeasure = needsMeasure; - - if (measureBlockers.isEmpty()) { - // Add to queue if there are no blockers - getMeasureQueue(direction).add(connector); - // Only need to propagate if not already propagated when - // setting blockers - propagatePotentialResize(); - } - } else if (!needsMeasure && this.needsMeasure - && measureBlockers.isEmpty()) { - // Only disable if there are no blockers (elements gets measured - // in both directions even if there is a blocker in one - // direction) - this.needsMeasure = needsMeasure; - getMeasureQueue(direction).remove(connector); - propagateNoUpcomingResize(); - } - } - - public void setNeedsLayout(boolean needsLayout) { - if (!(connector instanceof ManagedLayout)) { - throw new IllegalStateException( - "Only managed layouts can need layout, layout attempted for " - + Util.getConnectorString(connector)); - } - if (needsLayout && !this.needsLayout) { - // If enabling needsLayout - this.needsLayout = needsLayout; - - if (layoutBlockers.isEmpty()) { - // Add to queue if there are no blockers - getLayoutQueue(direction).add((ManagedLayout) connector); - // Only need to propagate if not already propagated when - // setting blockers - propagatePotentialLayout(); - } - } else if (!needsLayout && this.needsLayout - && layoutBlockers.isEmpty()) { - // Only disable if there are no layout blockers - // (SimpleManagedLayout gets layouted in both directions - // even if there is a blocker in one direction) - this.needsLayout = needsLayout; - getLayoutQueue(direction).remove(connector); - propagateNoUpcomingLayout(); - } - } - - private void propagatePotentialResize() { - for (ComponentConnector needsSize : getNeedsSizeForLayout()) { - LayoutDependency layoutDependency = getDependency(needsSize, - direction); - layoutDependency.addLayoutBlocker(connector); - } - } - - private Collection<ComponentConnector> getNeedsSizeForLayout() { - // Find all connectors that need the size of this connector for - // layouting - - // Parent needs size if it isn't relative? - // Connector itself needs size if it isn't undefined? - // Children doesn't care? - - ArrayList<ComponentConnector> needsSize = new ArrayList<ComponentConnector>(); - - if (!isUndefinedInDirection(connector, direction)) { - needsSize.add(connector); - } - if (!isRelativeInDirection(connector, direction)) { - ServerConnector parent = connector.getParent(); - if (parent instanceof ComponentConnector) { - needsSize.add((ComponentConnector) parent); - } - } - - return needsSize; - } - - private void propagateNoUpcomingResize() { - for (ComponentConnector mightNeedLayout : getNeedsSizeForLayout()) { - LayoutDependency layoutDependency = getDependency( - mightNeedLayout, direction); - layoutDependency.removeLayoutBlocker(connector); - } - } - - private void propagatePotentialLayout() { - for (ComponentConnector sizeMightChange : getResizedByLayout()) { - LayoutDependency layoutDependency = getDependency( - sizeMightChange, direction); - layoutDependency.addMeasureBlocker(connector); - } - } - - private Collection<ComponentConnector> getResizedByLayout() { - // Components that might get resized by a layout of this component - - // Parent never resized - // Connector itself resized if undefined - // Children resized if relative - - ArrayList<ComponentConnector> resized = new ArrayList<ComponentConnector>(); - if (isUndefinedInDirection(connector, direction)) { - resized.add(connector); - } - - if (connector instanceof ComponentContainerConnector) { - ComponentContainerConnector container = (ComponentContainerConnector) connector; - for (ComponentConnector child : container.getChildComponents()) { - if (isRelativeInDirection(child, direction)) { - resized.add(child); - } - } - } - - return resized; - } - - private void propagateNoUpcomingLayout() { - for (ComponentConnector sizeMightChange : getResizedByLayout()) { - LayoutDependency layoutDependency = getDependency( - sizeMightChange, direction); - layoutDependency.removeMeasureBlocker(connector); - } - } - - public void markSizeAsChanged() { - // When the size has changed, all that use that size should be - // layouted - for (ComponentConnector connector : getNeedsSizeForLayout()) { - LayoutDependency layoutDependency = getDependency(connector, - direction); - if (connector instanceof ManagedLayout) { - layoutDependency.setNeedsLayout(true); - } else { - // Should simulate setNeedsLayout(true) + markAsLayouted -> - // propagate needs measure - layoutDependency.propagatePostLayoutMeasure(); - } - } - - // Should also go through the hierarchy to discover appeared or - // disappeared scrollbars - ComponentConnector scrollingBoundary = getScrollingBoundary(connector); - if (scrollingBoundary != null) { - getDependency(scrollingBoundary, getOppositeDirection()) - .setNeedsMeasure(true); - } - - } - - /** - * Go up the hierarchy to find a component whose size might have changed - * in the other direction because changes to this component causes - * scrollbars to appear or disappear. - * - * @return - */ - private LayoutDependency findPotentiallyChangedScrollbar() { - ComponentConnector currentConnector = connector; - while (true) { - ServerConnector parent = currentConnector.getParent(); - if (!(parent instanceof ComponentConnector)) { - return null; - } - if (parent instanceof MayScrollChildren) { - return getDependency(currentConnector, - getOppositeDirection()); - } - currentConnector = (ComponentConnector) parent; - } - } - - private int getOppositeDirection() { - return direction == HORIZONTAL ? VERTICAL : HORIZONTAL; - } - - public void markAsLayouted() { - if (!layoutBlockers.isEmpty()) { - // Don't do anything if there are layout blockers (SimpleLayout - // gets layouted in both directions even if one direction is - // blocked) - return; - } - setNeedsLayout(false); - propagatePostLayoutMeasure(); - } - - private void propagatePostLayoutMeasure() { - for (ComponentConnector resized : getResizedByLayout()) { - LayoutDependency layoutDependency = getDependency(resized, - direction); - layoutDependency.setNeedsMeasure(true); - } - - // Special case for e.g. wrapping texts - if (direction == HORIZONTAL && !connector.isUndefinedWidth() - && connector.isUndefinedHeight()) { - LayoutDependency dependency = getDependency(connector, VERTICAL); - dependency.setNeedsMeasure(true); - } - } - - @Override - public String toString() { - String s = getCompactConnectorString(connector) + "\n"; - if (direction == VERTICAL) { - s += "Vertical"; - } else { - s += "Horizontal"; - } - ComponentState state = connector.getState(); - s += " sizing: " - + getSizeDefinition(direction == VERTICAL ? state - .getHeight() : state.getWidth()) + "\n"; - - if (needsLayout) { - s += "Needs layout\n"; - } - if (getLayoutQueue(direction).contains(connector)) { - s += "In layout queue\n"; - } - s += "Layout blockers: " + blockersToString(layoutBlockers) + "\n"; - - if (needsMeasure) { - s += "Needs measure\n"; - } - if (getMeasureQueue(direction).contains(connector)) { - s += "In measure queue\n"; - } - s += "Measure blockers: " + blockersToString(measureBlockers); - - return s; - } - - public boolean noMoreChangesExpected() { - return !needsLayout && !needsMeasure && layoutBlockers.isEmpty() - && measureBlockers.isEmpty(); - } - - } - - private static final int HORIZONTAL = 0; - private static final int VERTICAL = 1; - - private final Map<?, ?>[] dependenciesInDirection = new Map<?, ?>[] { - new HashMap<ComponentConnector, LayoutDependency>(), - new HashMap<ComponentConnector, LayoutDependency>() }; - - private final Collection<?>[] measureQueueInDirection = new HashSet<?>[] { - new HashSet<ComponentConnector>(), - new HashSet<ComponentConnector>() }; - - private final Collection<?>[] layoutQueueInDirection = new HashSet<?>[] { - new HashSet<ComponentConnector>(), - new HashSet<ComponentConnector>() }; - - public void setNeedsMeasure(ComponentConnector connector, - boolean needsMeasure) { - setNeedsHorizontalMeasure(connector, needsMeasure); - setNeedsVerticalMeasure(connector, needsMeasure); - } - - public void setNeedsHorizontalMeasure(ComponentConnector connector, - boolean needsMeasure) { - LayoutDependency dependency = getDependency(connector, HORIZONTAL); - dependency.setNeedsMeasure(needsMeasure); - } - - public void setNeedsVerticalMeasure(ComponentConnector connector, - boolean needsMeasure) { - LayoutDependency dependency = getDependency(connector, VERTICAL); - dependency.setNeedsMeasure(needsMeasure); - } - - private LayoutDependency getDependency(ComponentConnector connector, - int direction) { - @SuppressWarnings("unchecked") - Map<ComponentConnector, LayoutDependency> dependencies = (Map<ComponentConnector, LayoutDependency>) dependenciesInDirection[direction]; - LayoutDependency dependency = dependencies.get(connector); - if (dependency == null) { - dependency = new LayoutDependency(connector, direction); - dependencies.put(connector, dependency); - } - return dependency; - } - - @SuppressWarnings("unchecked") - private Collection<ManagedLayout> getLayoutQueue(int direction) { - return (Collection<ManagedLayout>) layoutQueueInDirection[direction]; - } - - @SuppressWarnings("unchecked") - private Collection<ComponentConnector> getMeasureQueue(int direction) { - return (Collection<ComponentConnector>) measureQueueInDirection[direction]; - } - - public void setNeedsHorizontalLayout(ManagedLayout layout, - boolean needsLayout) { - LayoutDependency dependency = getDependency(layout, HORIZONTAL); - dependency.setNeedsLayout(needsLayout); - } - - public void setNeedsVerticalLayout(ManagedLayout layout, boolean needsLayout) { - LayoutDependency dependency = getDependency(layout, VERTICAL); - dependency.setNeedsLayout(needsLayout); - } - - public void markAsHorizontallyLayouted(ManagedLayout layout) { - LayoutDependency dependency = getDependency(layout, HORIZONTAL); - dependency.markAsLayouted(); - } - - public void markAsVerticallyLayouted(ManagedLayout layout) { - LayoutDependency dependency = getDependency(layout, VERTICAL); - dependency.markAsLayouted(); - } - - public void markHeightAsChanged(ComponentConnector connector) { - LayoutDependency dependency = getDependency(connector, VERTICAL); - dependency.markSizeAsChanged(); - } - - public void markWidthAsChanged(ComponentConnector connector) { - LayoutDependency dependency = getDependency(connector, HORIZONTAL); - dependency.markSizeAsChanged(); - } - - private static boolean isRelativeInDirection(ComponentConnector connector, - int direction) { - if (direction == HORIZONTAL) { - return connector.isRelativeWidth(); - } else { - return connector.isRelativeHeight(); - } - } - - private static boolean isUndefinedInDirection(ComponentConnector connector, - int direction) { - if (direction == VERTICAL) { - return connector.isUndefinedHeight(); - } else { - return connector.isUndefinedWidth(); - } - } - - private static String getCompactConnectorString(ComponentConnector connector) { - return Util.getSimpleName(connector) + " (" - + connector.getConnectorId() + ")"; - } - - private static String getSizeDefinition(String size) { - if (size == null || size.length() == 0) { - return "undefined"; - } else if (size.endsWith("%")) { - return "relative"; - } else { - return "fixed"; - } - } - - private static String blockersToString( - Collection<ComponentConnector> blockers) { - StringBuilder b = new StringBuilder("["); - for (ComponentConnector blocker : blockers) { - if (b.length() != 1) { - b.append(", "); - } - b.append(getCompactConnectorString(blocker)); - } - b.append(']'); - return b.toString(); - } - - public boolean hasConnectorsToMeasure() { - return !measureQueueInDirection[HORIZONTAL].isEmpty() - || !measureQueueInDirection[VERTICAL].isEmpty(); - } - - public boolean hasHorizontalConnectorToLayout() { - return !getLayoutQueue(HORIZONTAL).isEmpty(); - } - - public boolean hasVerticaConnectorToLayout() { - return !getLayoutQueue(VERTICAL).isEmpty(); - } - - public ManagedLayout[] getHorizontalLayoutTargets() { - Collection<ManagedLayout> queue = getLayoutQueue(HORIZONTAL); - return queue.toArray(new ManagedLayout[queue.size()]); - } - - public ManagedLayout[] getVerticalLayoutTargets() { - Collection<ManagedLayout> queue = getLayoutQueue(VERTICAL); - return queue.toArray(new ManagedLayout[queue.size()]); - } - - public Collection<ComponentConnector> getMeasureTargets() { - Collection<ComponentConnector> measureTargets = new HashSet<ComponentConnector>( - getMeasureQueue(HORIZONTAL)); - measureTargets.addAll(getMeasureQueue(VERTICAL)); - return measureTargets; - } - - public void logDependencyStatus(ComponentConnector connector) { - VConsole.log("===="); - VConsole.log(getDependency(connector, HORIZONTAL).toString()); - VConsole.log(getDependency(connector, VERTICAL).toString()); - } - - public boolean noMoreChangesExpected(ComponentConnector connector) { - return getDependency(connector, HORIZONTAL).noMoreChangesExpected() - && getDependency(connector, VERTICAL).noMoreChangesExpected(); - } - - public ComponentConnector getScrollingBoundary(ComponentConnector connector) { - LayoutDependency dependency = getDependency(connector, HORIZONTAL); - if (!dependency.scrollingParentCached) { - ServerConnector parent = dependency.connector.getParent(); - if (parent instanceof MayScrollChildren) { - dependency.scrollingBoundary = connector; - } else if (parent instanceof ComponentConnector) { - dependency.scrollingBoundary = getScrollingBoundary((ComponentConnector) parent); - } else { - // No scrolling parent - } - - dependency.scrollingParentCached = true; - } - return dependency.scrollingBoundary; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/layout/Margins.java b/client/src/com/vaadin/terminal/gwt/client/ui/layout/Margins.java deleted file mode 100644 index 21e35409a0..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/layout/Margins.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.layout; - -public class Margins { - - private int marginTop; - private int marginBottom; - private int marginLeft; - private int marginRight; - - private int horizontal = 0; - private int vertical = 0; - - public Margins(int marginTop, int marginBottom, int marginLeft, - int marginRight) { - super(); - this.marginTop = marginTop; - this.marginBottom = marginBottom; - this.marginLeft = marginLeft; - this.marginRight = marginRight; - - updateHorizontal(); - updateVertical(); - } - - public int getMarginTop() { - return marginTop; - } - - public int getMarginBottom() { - return marginBottom; - } - - public int getMarginLeft() { - return marginLeft; - } - - public int getMarginRight() { - return marginRight; - } - - public int getHorizontal() { - return horizontal; - } - - public int getVertical() { - return vertical; - } - - public void setMarginTop(int marginTop) { - this.marginTop = marginTop; - updateVertical(); - } - - public void setMarginBottom(int marginBottom) { - this.marginBottom = marginBottom; - updateVertical(); - } - - public void setMarginLeft(int marginLeft) { - this.marginLeft = marginLeft; - updateHorizontal(); - } - - public void setMarginRight(int marginRight) { - this.marginRight = marginRight; - updateHorizontal(); - } - - private void updateVertical() { - vertical = marginTop + marginBottom; - } - - private void updateHorizontal() { - horizontal = marginLeft + marginRight; - } - - @Override - public String toString() { - return "Margins [marginLeft=" + marginLeft + ",marginTop=" + marginTop - + ",marginRight=" + marginRight + ",marginBottom=" - + marginBottom + "]"; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/layout/MayScrollChildren.java b/client/src/com/vaadin/terminal/gwt/client/ui/layout/MayScrollChildren.java deleted file mode 100644 index 336021dbf4..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/layout/MayScrollChildren.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.layout; - -import com.vaadin.terminal.gwt.client.ComponentContainerConnector; - -public interface MayScrollChildren extends ComponentContainerConnector { - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/layout/VLayoutSlot.java b/client/src/com/vaadin/terminal/gwt/client/ui/layout/VLayoutSlot.java deleted file mode 100644 index 715a24749e..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/layout/VLayoutSlot.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.layout; - -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Position; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ui.AlignmentInfo; -import com.vaadin.terminal.gwt.client.VCaption; - -public abstract class VLayoutSlot { - - private final Element wrapper = Document.get().createDivElement().cast(); - - private AlignmentInfo alignment; - private VCaption caption; - private final Widget widget; - - private double expandRatio; - - public VLayoutSlot(String baseClassName, Widget widget) { - this.widget = widget; - - wrapper.setClassName(baseClassName + "-slot"); - } - - public VCaption getCaption() { - return caption; - } - - public void setCaption(VCaption caption) { - if (this.caption != null) { - this.caption.removeFromParent(); - } - this.caption = caption; - if (caption != null) { - // Physical attach. - DOM.insertBefore(wrapper, caption.getElement(), widget.getElement()); - Style style = caption.getElement().getStyle(); - style.setPosition(Position.ABSOLUTE); - style.setTop(0, Unit.PX); - } - } - - public AlignmentInfo getAlignment() { - return alignment; - } - - public Widget getWidget() { - return widget; - } - - public void setAlignment(AlignmentInfo alignment) { - this.alignment = alignment; - } - - public void positionHorizontally(double currentLocation, - double allocatedSpace, double marginRight) { - Style style = wrapper.getStyle(); - - double availableWidth = allocatedSpace; - - VCaption caption = getCaption(); - Style captionStyle = caption != null ? caption.getElement().getStyle() - : null; - int captionWidth = getCaptionWidth(); - - boolean captionAboveCompnent; - if (caption == null) { - captionAboveCompnent = false; - style.clearPaddingRight(); - } else { - captionAboveCompnent = !caption.shouldBePlacedAfterComponent(); - if (!captionAboveCompnent) { - availableWidth -= captionWidth; - captionStyle.clearLeft(); - captionStyle.setRight(0, Unit.PX); - style.setPaddingRight(captionWidth, Unit.PX); - } else { - captionStyle.setLeft(0, Unit.PX); - captionStyle.clearRight(); - style.clearPaddingRight(); - } - } - - if (marginRight > 0) { - style.setMarginRight(marginRight, Unit.PX); - } else { - style.clearMarginRight(); - } - - if (isRelativeWidth()) { - style.setPropertyPx("width", (int) availableWidth); - } else { - style.clearProperty("width"); - } - - double allocatedContentWidth = 0; - if (isRelativeWidth()) { - String percentWidth = getWidget().getElement().getStyle() - .getWidth(); - double percentage = parsePercent(percentWidth); - allocatedContentWidth = availableWidth * (percentage / 100); - reportActualRelativeWidth(Math.round((float) allocatedContentWidth)); - } - - AlignmentInfo alignment = getAlignment(); - if (!alignment.isLeft()) { - double usedWidth; - if (isRelativeWidth()) { - usedWidth = allocatedContentWidth; - } else { - usedWidth = getWidgetWidth(); - } - if (alignment.isHorizontalCenter()) { - currentLocation += (allocatedSpace - usedWidth) / 2d; - if (captionAboveCompnent) { - captionStyle.setLeft( - Math.round(usedWidth - captionWidth) / 2, Unit.PX); - } - } else { - currentLocation += (allocatedSpace - usedWidth); - if (captionAboveCompnent) { - captionStyle.setLeft(Math.round(usedWidth - captionWidth), - Unit.PX); - } - } - } else { - if (captionAboveCompnent) { - captionStyle.setLeft(0, Unit.PX); - } - } - - style.setLeft(Math.round(currentLocation), Unit.PX); - } - - private double parsePercent(String size) { - return Double.parseDouble(size.replaceAll("%", "")); - } - - public void positionVertically(double currentLocation, - double allocatedSpace, double marginBottom) { - Style style = wrapper.getStyle(); - - double contentHeight = allocatedSpace; - - int captionHeight; - VCaption caption = getCaption(); - if (caption == null || caption.shouldBePlacedAfterComponent()) { - style.clearPaddingTop(); - captionHeight = 0; - } else { - captionHeight = getCaptionHeight(); - contentHeight -= captionHeight; - if (contentHeight < 0) { - contentHeight = 0; - } - style.setPaddingTop(captionHeight, Unit.PX); - } - - if (marginBottom > 0) { - style.setMarginBottom(marginBottom, Unit.PX); - } else { - style.clearMarginBottom(); - } - - if (isRelativeHeight()) { - style.setHeight(contentHeight, Unit.PX); - } else { - style.clearHeight(); - } - - double allocatedContentHeight = 0; - if (isRelativeHeight()) { - String height = getWidget().getElement().getStyle().getHeight(); - double percentage = parsePercent(height); - allocatedContentHeight = contentHeight * (percentage / 100); - reportActualRelativeHeight(Math - .round((float) allocatedContentHeight)); - } - - AlignmentInfo alignment = getAlignment(); - if (!alignment.isTop()) { - double usedHeight; - if (isRelativeHeight()) { - usedHeight = captionHeight + allocatedContentHeight; - } else { - usedHeight = getUsedHeight(); - } - if (alignment.isVerticalCenter()) { - currentLocation += (allocatedSpace - usedHeight) / 2d; - } else { - currentLocation += (allocatedSpace - usedHeight); - } - } - - style.setTop(currentLocation, Unit.PX); - } - - protected void reportActualRelativeHeight(int allocatedHeight) { - // Default implementation does nothing - } - - protected void reportActualRelativeWidth(int allocatedWidth) { - // Default implementation does nothing - } - - public void positionInDirection(double currentLocation, - double allocatedSpace, double endingMargin, boolean isVertical) { - if (isVertical) { - positionVertically(currentLocation, allocatedSpace, endingMargin); - } else { - positionHorizontally(currentLocation, allocatedSpace, endingMargin); - } - } - - public int getWidgetSizeInDirection(boolean isVertical) { - return isVertical ? getWidgetHeight() : getWidgetWidth(); - } - - public int getUsedWidth() { - int widgetWidth = getWidgetWidth(); - if (caption == null) { - return widgetWidth; - } else if (caption.shouldBePlacedAfterComponent()) { - return widgetWidth + getCaptionWidth(); - } else { - return Math.max(widgetWidth, getCaptionWidth()); - } - } - - public int getUsedHeight() { - int widgetHeight = getWidgetHeight(); - if (caption == null) { - return widgetHeight; - } else if (caption.shouldBePlacedAfterComponent()) { - return Math.max(widgetHeight, getCaptionHeight()); - } else { - return widgetHeight + getCaptionHeight(); - } - } - - public int getUsedSizeInDirection(boolean isVertical) { - return isVertical ? getUsedHeight() : getUsedWidth(); - } - - protected abstract int getCaptionHeight(); - - protected abstract int getCaptionWidth(); - - public abstract int getWidgetHeight(); - - public abstract int getWidgetWidth(); - - public abstract boolean isUndefinedHeight(); - - public abstract boolean isUndefinedWidth(); - - public boolean isUndefinedInDirection(boolean isVertical) { - return isVertical ? isUndefinedHeight() : isUndefinedWidth(); - } - - public abstract boolean isRelativeHeight(); - - public abstract boolean isRelativeWidth(); - - public boolean isRelativeInDirection(boolean isVertical) { - return isVertical ? isRelativeHeight() : isRelativeWidth(); - } - - public Element getWrapperElement() { - return wrapper; - } - - public void setExpandRatio(double expandRatio) { - this.expandRatio = expandRatio; - } - - public double getExpandRatio() { - return expandRatio; - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/link/LinkConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/link/LinkConnector.java deleted file mode 100644 index f2b8361f2b..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/link/LinkConnector.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.link; - -import com.google.gwt.user.client.DOM; -import com.vaadin.shared.ui.BorderStyle; -import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; -import com.vaadin.terminal.gwt.client.ui.Icon; -import com.vaadin.ui.Link; - -@Connect(Link.class) -public class LinkConnector extends AbstractComponentConnector implements - Paintable { - - @Override - public boolean delegateCaptionHandling() { - return false; - } - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - if (!isRealUpdate(uidl)) { - return; - } - - getWidget().client = client; - - getWidget().enabled = isEnabled(); - - if (uidl.hasAttribute("name")) { - getWidget().target = uidl.getStringAttribute("name"); - getWidget().anchor.setAttribute("target", getWidget().target); - } - if (uidl.hasAttribute("src")) { - getWidget().src = client.translateVaadinUri(uidl - .getStringAttribute("src")); - getWidget().anchor.setAttribute("href", getWidget().src); - } - - if (uidl.hasAttribute("border")) { - if ("none".equals(uidl.getStringAttribute("border"))) { - getWidget().borderStyle = BorderStyle.NONE; - } else { - getWidget().borderStyle = BorderStyle.MINIMAL; - } - } else { - getWidget().borderStyle = BorderStyle.DEFAULT; - } - - getWidget().targetHeight = uidl.hasAttribute("targetHeight") ? uidl - .getIntAttribute("targetHeight") : -1; - getWidget().targetWidth = uidl.hasAttribute("targetWidth") ? uidl - .getIntAttribute("targetWidth") : -1; - - // Set link caption - getWidget().captionElement.setInnerText(getState().getCaption()); - - // handle error - if (null != getState().getErrorMessage()) { - if (getWidget().errorIndicatorElement == null) { - getWidget().errorIndicatorElement = DOM.createDiv(); - DOM.setElementProperty(getWidget().errorIndicatorElement, - "className", "v-errorindicator"); - } - DOM.insertChild(getWidget().getElement(), - getWidget().errorIndicatorElement, 0); - } else if (getWidget().errorIndicatorElement != null) { - DOM.setStyleAttribute(getWidget().errorIndicatorElement, "display", - "none"); - } - - if (getState().getIcon() != null) { - if (getWidget().icon == null) { - getWidget().icon = new Icon(client); - getWidget().anchor.insertBefore(getWidget().icon.getElement(), - getWidget().captionElement); - } - getWidget().icon.setUri(getState().getIcon().getURL()); - } - - } - - @Override - public VLink getWidget() { - return (VLink) super.getWidget(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/link/VLink.java b/client/src/com/vaadin/terminal/gwt/client/ui/link/VLink.java deleted file mode 100644 index b0e44c9d13..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/link/VLink.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.link; - -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.HTML; -import com.vaadin.shared.ui.BorderStyle; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.Icon; - -public class VLink extends HTML implements ClickHandler { - - public static final String CLASSNAME = "v-link"; - - @Deprecated - protected static final BorderStyle BORDER_STYLE_DEFAULT = BorderStyle.DEFAULT; - - @Deprecated - protected static final BorderStyle BORDER_STYLE_MINIMAL = BorderStyle.MINIMAL; - - @Deprecated - protected static final BorderStyle BORDER_STYLE_NONE = BorderStyle.NONE; - - protected String src; - - protected String target; - - protected BorderStyle borderStyle = BorderStyle.DEFAULT; - - protected boolean enabled; - - protected int targetWidth; - - protected int targetHeight; - - protected Element errorIndicatorElement; - - protected final Element anchor = DOM.createAnchor(); - - protected final Element captionElement = DOM.createSpan(); - - protected Icon icon; - - protected ApplicationConnection client; - - public VLink() { - super(); - getElement().appendChild(anchor); - anchor.appendChild(captionElement); - addClickHandler(this); - setStyleName(CLASSNAME); - } - - @Override - public void onClick(ClickEvent event) { - if (enabled) { - if (target == null) { - target = "_self"; - } - String features; - switch (borderStyle) { - case NONE: - features = "menubar=no,location=no,status=no"; - break; - case MINIMAL: - features = "menubar=yes,location=no,status=no"; - break; - default: - features = ""; - break; - } - - if (targetWidth > 0) { - features += (features.length() > 0 ? "," : "") + "width=" - + targetWidth; - } - if (targetHeight > 0) { - features += (features.length() > 0 ? "," : "") + "height=" - + targetHeight; - } - - if (features.length() > 0) { - // if 'special features' are set, use window.open(), unless - // a modifier key is held (ctrl to open in new tab etc) - Event e = DOM.eventGetCurrentEvent(); - if (!e.getCtrlKey() && !e.getAltKey() && !e.getShiftKey() - && !e.getMetaKey()) { - Window.open(src, target, features); - e.preventDefault(); - } - } - } - } - - @Override - public void onBrowserEvent(Event event) { - final Element target = DOM.eventGetTarget(event); - if (event.getTypeInt() == Event.ONLOAD) { - Util.notifyParentOfSizeChange(this, true); - } - if (target == captionElement || target == anchor - || (icon != null && target == icon.getElement())) { - super.onBrowserEvent(event); - } - if (!enabled) { - event.preventDefault(); - } - - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/listselect/ListSelectConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/listselect/ListSelectConnector.java deleted file mode 100644 index 4d34c21546..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/listselect/ListSelectConnector.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.listselect; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.gwt.client.ui.optiongroup.OptionGroupBaseConnector; -import com.vaadin.ui.ListSelect; - -@Connect(ListSelect.class) -public class ListSelectConnector extends OptionGroupBaseConnector { - - @Override - public VListSelect getWidget() { - return (VListSelect) super.getWidget(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/listselect/VListSelect.java b/client/src/com/vaadin/terminal/gwt/client/ui/listselect/VListSelect.java deleted file mode 100644 index 06099d296c..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/listselect/VListSelect.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.listselect; - -import java.util.ArrayList; -import java.util.Iterator; - -import com.google.gwt.event.dom.client.ChangeEvent; -import com.google.gwt.user.client.ui.ListBox; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.optiongroup.VOptionGroupBase; - -public class VListSelect extends VOptionGroupBase { - - public static final String CLASSNAME = "v-select"; - - private static final int VISIBLE_COUNT = 10; - - protected ListBox select; - - private int lastSelectedIndex = -1; - - public VListSelect() { - super(new ListBox(true), CLASSNAME); - select = getOptionsContainer(); - select.addChangeHandler(this); - select.addClickHandler(this); - select.setStyleName(CLASSNAME + "-select"); - select.setVisibleItemCount(VISIBLE_COUNT); - } - - protected ListBox getOptionsContainer() { - return (ListBox) optionsContainer; - } - - @Override - protected void buildOptions(UIDL uidl) { - select.setMultipleSelect(isMultiselect()); - select.setEnabled(!isDisabled() && !isReadonly()); - select.clear(); - if (!isMultiselect() && isNullSelectionAllowed() - && !isNullSelectionItemAvailable()) { - // can't unselect last item in singleselect mode - select.addItem("", (String) null); - } - for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) { - final UIDL optionUidl = (UIDL) i.next(); - select.addItem(optionUidl.getStringAttribute("caption"), - optionUidl.getStringAttribute("key")); - if (optionUidl.hasAttribute("selected")) { - int itemIndex = select.getItemCount() - 1; - select.setItemSelected(itemIndex, true); - lastSelectedIndex = itemIndex; - } - } - if (getRows() > 0) { - select.setVisibleItemCount(getRows()); - } - } - - @Override - protected String[] getSelectedItems() { - final ArrayList<String> selectedItemKeys = new ArrayList<String>(); - for (int i = 0; i < select.getItemCount(); i++) { - if (select.isItemSelected(i)) { - selectedItemKeys.add(select.getValue(i)); - } - } - return selectedItemKeys.toArray(new String[selectedItemKeys.size()]); - } - - @Override - public void onChange(ChangeEvent event) { - final int si = select.getSelectedIndex(); - if (si == -1 && !isNullSelectionAllowed()) { - select.setSelectedIndex(lastSelectedIndex); - } else { - lastSelectedIndex = si; - if (isMultiselect()) { - client.updateVariable(paintableId, "selected", - getSelectedItems(), isImmediate()); - } else { - client.updateVariable(paintableId, "selected", - new String[] { "" + getSelectedItem() }, isImmediate()); - } - } - } - - @Override - public void setHeight(String height) { - select.setHeight(height); - super.setHeight(height); - } - - @Override - public void setWidth(String width) { - select.setWidth(width); - super.setWidth(width); - } - - @Override - protected void setTabIndex(int tabIndex) { - getOptionsContainer().setTabIndex(tabIndex); - } - - @Override - public void focus() { - select.setFocus(true); - } -}
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/menubar/MenuBar.java b/client/src/com/vaadin/terminal/gwt/client/ui/menubar/MenuBar.java deleted file mode 100644 index c69845d33b..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/menubar/MenuBar.java +++ /dev/null @@ -1,532 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.menubar; - -/* - * Copyright 2007 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -// COPIED HERE DUE package privates in GWT -import java.util.ArrayList; -import java.util.List; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.PopupListener; -import com.google.gwt.user.client.ui.PopupPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ui.VOverlay; - -/** - * A standard menu bar widget. A menu bar can contain any number of menu items, - * each of which can either fire a {@link com.google.gwt.user.client.Command} or - * open a cascaded menu bar. - * - * <p> - * <img class='gallery' src='MenuBar.png'/> - * </p> - * - * <h3>CSS Style Rules</h3> - * <ul class='css'> - * <li>.gwt-MenuBar { the menu bar itself }</li> - * <li>.gwt-MenuBar .gwt-MenuItem { menu items }</li> - * <li> - * .gwt-MenuBar .gwt-MenuItem-selected { selected menu items }</li> - * </ul> - * - * <p> - * <h3>Example</h3> - * {@example com.google.gwt.examples.MenuBarExample} - * </p> - * - * @deprecated - */ -@Deprecated -public class MenuBar extends Widget implements PopupListener { - - private final Element body; - private final ArrayList<MenuItem> items = new ArrayList<MenuItem>(); - private MenuBar parentMenu; - private PopupPanel popup; - private MenuItem selectedItem; - private MenuBar shownChildMenu; - private final boolean vertical; - private boolean autoOpen; - - /** - * Creates an empty horizontal menu bar. - */ - public MenuBar() { - this(false); - } - - /** - * Creates an empty menu bar. - * - * @param vertical - * <code>true</code> to orient the menu bar vertically - */ - public MenuBar(boolean vertical) { - super(); - - final Element table = DOM.createTable(); - body = DOM.createTBody(); - DOM.appendChild(table, body); - - if (!vertical) { - final Element tr = DOM.createTR(); - DOM.appendChild(body, tr); - } - - this.vertical = vertical; - - final Element outer = DOM.createDiv(); - DOM.appendChild(outer, table); - setElement(outer); - - sinkEvents(Event.ONCLICK | Event.ONMOUSEOVER | Event.ONMOUSEOUT); - setStyleName("gwt-MenuBar"); - } - - /** - * Adds a menu item to the bar. - * - * @param item - * the item to be added - */ - public void addItem(MenuItem item) { - Element tr; - if (vertical) { - tr = DOM.createTR(); - DOM.appendChild(body, tr); - } else { - tr = DOM.getChild(body, 0); - } - - DOM.appendChild(tr, item.getElement()); - - item.setParentMenu(this); - item.setSelectionStyle(false); - items.add(item); - } - - /** - * Adds a menu item to the bar, that will fire the given command when it is - * selected. - * - * @param text - * the item's text - * @param asHTML - * <code>true</code> to treat the specified text as html - * @param cmd - * the command to be fired - * @return the {@link MenuItem} object created - */ - public MenuItem addItem(String text, boolean asHTML, Command cmd) { - final MenuItem item = new MenuItem(text, asHTML, cmd); - addItem(item); - return item; - } - - /** - * Adds a menu item to the bar, that will open the specified menu when it is - * selected. - * - * @param text - * the item's text - * @param asHTML - * <code>true</code> to treat the specified text as html - * @param popup - * the menu to be cascaded from it - * @return the {@link MenuItem} object created - */ - public MenuItem addItem(String text, boolean asHTML, MenuBar popup) { - final MenuItem item = new MenuItem(text, asHTML, popup); - addItem(item); - return item; - } - - /** - * Adds a menu item to the bar, that will fire the given command when it is - * selected. - * - * @param text - * the item's text - * @param cmd - * the command to be fired - * @return the {@link MenuItem} object created - */ - public MenuItem addItem(String text, Command cmd) { - final MenuItem item = new MenuItem(text, cmd); - addItem(item); - return item; - } - - /** - * Adds a menu item to the bar, that will open the specified menu when it is - * selected. - * - * @param text - * the item's text - * @param popup - * the menu to be cascaded from it - * @return the {@link MenuItem} object created - */ - public MenuItem addItem(String text, MenuBar popup) { - final MenuItem item = new MenuItem(text, popup); - addItem(item); - return item; - } - - /** - * Removes all menu items from this menu bar. - */ - public void clearItems() { - final Element container = getItemContainerElement(); - while (DOM.getChildCount(container) > 0) { - DOM.removeChild(container, DOM.getChild(container, 0)); - } - items.clear(); - } - - /** - * Gets whether this menu bar's child menus will open when the mouse is - * moved over it. - * - * @return <code>true</code> if child menus will auto-open - */ - public boolean getAutoOpen() { - return autoOpen; - } - - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - - final MenuItem item = findItem(DOM.eventGetTarget(event)); - switch (DOM.eventGetType(event)) { - case Event.ONCLICK: { - // Fire an item's command when the user clicks on it. - if (item != null) { - doItemAction(item, true); - } - break; - } - - case Event.ONMOUSEOVER: { - if (item != null) { - itemOver(item); - } - break; - } - - case Event.ONMOUSEOUT: { - if (item != null) { - itemOver(null); - } - break; - } - } - } - - @Override - public void onPopupClosed(PopupPanel sender, boolean autoClosed) { - // If the menu popup was auto-closed, close all of its parents as well. - if (autoClosed) { - closeAllParents(); - } - - // When the menu popup closes, remember that no item is - // currently showing a popup menu. - onHide(); - shownChildMenu = null; - popup = null; - } - - /** - * Removes the specified menu item from the bar. - * - * @param item - * the item to be removed - */ - public void removeItem(MenuItem item) { - final int idx = items.indexOf(item); - if (idx == -1) { - return; - } - - final Element container = getItemContainerElement(); - DOM.removeChild(container, DOM.getChild(container, idx)); - items.remove(idx); - } - - /** - * Sets whether this menu bar's child menus will open when the mouse is - * moved over it. - * - * @param autoOpen - * <code>true</code> to cause child menus to auto-open - */ - public void setAutoOpen(boolean autoOpen) { - this.autoOpen = autoOpen; - } - - /** - * Returns a list containing the <code>MenuItem</code> objects in the menu - * bar. If there are no items in the menu bar, then an empty - * <code>List</code> object will be returned. - * - * @return a list containing the <code>MenuItem</code> objects in the menu - * bar - */ - public List<MenuItem> getItems() { - return items; - } - - /** - * Returns the <code>MenuItem</code> that is currently selected - * (highlighted) by the user. If none of the items in the menu are currently - * selected, then <code>null</code> will be returned. - * - * @return the <code>MenuItem</code> that is currently selected, or - * <code>null</code> if no items are currently selected - */ - public MenuItem getSelectedItem() { - return selectedItem; - } - - @Override - protected void onDetach() { - // When the menu is detached, make sure to close all of its children. - if (popup != null) { - popup.hide(); - } - - super.onDetach(); - } - - /* - * Closes all parent menu popups. - */ - void closeAllParents() { - MenuBar curMenu = this; - while (curMenu != null) { - curMenu.close(); - - if ((curMenu.parentMenu == null) && (curMenu.selectedItem != null)) { - curMenu.selectedItem.setSelectionStyle(false); - curMenu.selectedItem = null; - } - - curMenu = curMenu.parentMenu; - } - } - - /* - * Performs the action associated with the given menu item. If the item has - * a popup associated with it, the popup will be shown. If it has a command - * associated with it, and 'fireCommand' is true, then the command will be - * fired. Popups associated with other items will be hidden. - * - * @param item the item whose popup is to be shown. @param fireCommand - * <code>true</code> if the item's command should be fired, - * <code>false</code> otherwise. - */ - protected void doItemAction(final MenuItem item, boolean fireCommand) { - // If the given item is already showing its menu, we're done. - if ((shownChildMenu != null) && (item.getSubMenu() == shownChildMenu)) { - return; - } - - // If another item is showing its menu, then hide it. - if (shownChildMenu != null) { - shownChildMenu.onHide(); - popup.hide(); - } - - // If the item has no popup, optionally fire its command. - if (item.getSubMenu() == null) { - if (fireCommand) { - // Close this menu and all of its parents. - closeAllParents(); - - // Fire the item's command. - final Command cmd = item.getCommand(); - if (cmd != null) { - Scheduler.get().scheduleDeferred(cmd); - } - } - return; - } - - // Ensure that the item is selected. - selectItem(item); - - // Create a new popup for this item, and position it next to - // the item (below if this is a horizontal menu bar, to the - // right if it's a vertical bar). - popup = new VOverlay(true) { - { - setWidget(item.getSubMenu()); - item.getSubMenu().onShow(); - } - - @Override - public boolean onEventPreview(Event event) { - // Hook the popup panel's event preview. We use this to keep it - // from - // auto-hiding when the parent menu is clicked. - switch (DOM.eventGetType(event)) { - case Event.ONCLICK: - // If the event target is part of the parent menu, suppress - // the - // event altogether. - final Element target = DOM.eventGetTarget(event); - final Element parentMenuElement = item.getParentMenu() - .getElement(); - if (DOM.isOrHasChild(parentMenuElement, target)) { - return false; - } - break; - } - - return super.onEventPreview(event); - } - }; - popup.addPopupListener(this); - - if (vertical) { - popup.setPopupPosition( - item.getAbsoluteLeft() + item.getOffsetWidth(), - item.getAbsoluteTop()); - } else { - popup.setPopupPosition(item.getAbsoluteLeft(), - item.getAbsoluteTop() + item.getOffsetHeight()); - } - - shownChildMenu = item.getSubMenu(); - item.getSubMenu().parentMenu = this; - - // Show the popup, ensuring that the menubar's event preview remains on - // top - // of the popup's. - popup.show(); - } - - void itemOver(MenuItem item) { - if (item == null) { - // Don't clear selection if the currently selected item's menu is - // showing. - if ((selectedItem != null) - && (shownChildMenu == selectedItem.getSubMenu())) { - return; - } - } - - // Style the item selected when the mouse enters. - selectItem(item); - - // If child menus are being shown, or this menu is itself - // a child menu, automatically show an item's child menu - // when the mouse enters. - if (item != null) { - if ((shownChildMenu != null) || (parentMenu != null) || autoOpen) { - doItemAction(item, false); - } - } - } - - public void selectItem(MenuItem item) { - if (item == selectedItem) { - return; - } - - if (selectedItem != null) { - selectedItem.setSelectionStyle(false); - } - - if (item != null) { - item.setSelectionStyle(true); - } - - selectedItem = item; - } - - /** - * Closes this menu (if it is a popup). - */ - private void close() { - if (parentMenu != null) { - parentMenu.popup.hide(); - } - } - - private MenuItem findItem(Element hItem) { - for (int i = 0; i < items.size(); ++i) { - final MenuItem item = items.get(i); - if (DOM.isOrHasChild(item.getElement(), hItem)) { - return item; - } - } - - return null; - } - - private Element getItemContainerElement() { - if (vertical) { - return body; - } else { - return DOM.getChild(body, 0); - } - } - - /* - * This method is called when a menu bar is hidden, so that it can hide any - * child popups that are currently being shown. - */ - private void onHide() { - if (shownChildMenu != null) { - shownChildMenu.onHide(); - popup.hide(); - } - } - - /* - * This method is called when a menu bar is shown. - */ - private void onShow() { - // Select the first item when a menu is shown. - if (items.size() > 0) { - selectItem(items.get(0)); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/menubar/MenuBarConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/menubar/MenuBarConnector.java deleted file mode 100644 index 372a420203..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/menubar/MenuBarConnector.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.menubar; - -import java.util.Iterator; -import java.util.Stack; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.dom.client.Element; -import com.google.gwt.user.client.Command; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.shared.ui.menubar.MenuBarConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.TooltipInfo; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; -import com.vaadin.terminal.gwt.client.ui.Icon; -import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout; - -@Connect(value = com.vaadin.ui.MenuBar.class, loadStyle = LoadStyle.LAZY) -public class MenuBarConnector extends AbstractComponentConnector implements - Paintable, SimpleManagedLayout { - - /** - * This method must be implemented to update the client-side component from - * UIDL data received from server. - * - * This method is called when the page is loaded for the first time, and - * every time UI changes in the component are received from the server. - */ - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (!isRealUpdate(uidl)) { - return; - } - - getWidget().htmlContentAllowed = uidl - .hasAttribute(MenuBarConstants.HTML_CONTENT_ALLOWED); - - getWidget().openRootOnHover = uidl - .getBooleanAttribute(MenuBarConstants.OPEN_ROOT_MENU_ON_HOWER); - - getWidget().enabled = isEnabled(); - - // For future connections - getWidget().client = client; - getWidget().uidlId = uidl.getId(); - - // Empty the menu every time it receives new information - if (!getWidget().getItems().isEmpty()) { - getWidget().clearItems(); - } - - UIDL options = uidl.getChildUIDL(0); - - if (null != getState() && !getState().isUndefinedWidth()) { - UIDL moreItemUIDL = options.getChildUIDL(0); - StringBuffer itemHTML = new StringBuffer(); - - if (moreItemUIDL.hasAttribute("icon")) { - itemHTML.append("<img src=\"" - + Util.escapeAttribute(client - .translateVaadinUri(moreItemUIDL - .getStringAttribute("icon"))) - + "\" class=\"" + Icon.CLASSNAME + "\" alt=\"\" />"); - } - - String moreItemText = moreItemUIDL.getStringAttribute("text"); - if ("".equals(moreItemText)) { - moreItemText = "►"; - } - itemHTML.append(moreItemText); - - getWidget().moreItem = GWT.create(VMenuBar.CustomMenuItem.class); - getWidget().moreItem.setHTML(itemHTML.toString()); - getWidget().moreItem.setCommand(VMenuBar.emptyCommand); - - getWidget().collapsedRootItems = new VMenuBar(true, getWidget()); - getWidget().moreItem.setSubMenu(getWidget().collapsedRootItems); - getWidget().moreItem.addStyleName(VMenuBar.CLASSNAME - + "-more-menuitem"); - } - - UIDL uidlItems = uidl.getChildUIDL(1); - Iterator<Object> itr = uidlItems.getChildIterator(); - Stack<Iterator<Object>> iteratorStack = new Stack<Iterator<Object>>(); - Stack<VMenuBar> menuStack = new Stack<VMenuBar>(); - VMenuBar currentMenu = getWidget(); - - while (itr.hasNext()) { - UIDL item = (UIDL) itr.next(); - VMenuBar.CustomMenuItem currentItem = null; - - final int itemId = item.getIntAttribute("id"); - - boolean itemHasCommand = item.hasAttribute("command"); - boolean itemIsCheckable = item - .hasAttribute(MenuBarConstants.ATTRIBUTE_CHECKED); - - String itemHTML = getWidget().buildItemHTML(item); - - Command cmd = null; - if (!item.hasAttribute("separator")) { - if (itemHasCommand || itemIsCheckable) { - // Construct a command that fires onMenuClick(int) with the - // item's id-number - cmd = new Command() { - @Override - public void execute() { - getWidget().hostReference.onMenuClick(itemId); - } - }; - } - } - - currentItem = currentMenu.addItem(itemHTML.toString(), cmd); - currentItem.updateFromUIDL(item, client); - - if (item.getChildCount() > 0) { - menuStack.push(currentMenu); - iteratorStack.push(itr); - itr = item.getChildIterator(); - currentMenu = new VMenuBar(true, currentMenu); - client.getVTooltip().connectHandlersToWidget(currentMenu); - // this is the top-level style that also propagates to items - - // any item specific styles are set above in - // currentItem.updateFromUIDL(item, client) - if (getState().hasStyles()) { - for (String style : getState().getStyles()) { - currentMenu.addStyleDependentName(style); - } - } - currentItem.setSubMenu(currentMenu); - } - - while (!itr.hasNext() && !iteratorStack.empty()) { - boolean hasCheckableItem = false; - for (VMenuBar.CustomMenuItem menuItem : currentMenu.getItems()) { - hasCheckableItem = hasCheckableItem - || menuItem.isCheckable(); - } - if (hasCheckableItem) { - currentMenu.addStyleDependentName("check-column"); - } else { - currentMenu.removeStyleDependentName("check-column"); - } - - itr = iteratorStack.pop(); - currentMenu = menuStack.pop(); - } - }// while - - getLayoutManager().setNeedsHorizontalLayout(this); - - }// updateFromUIDL - - @Override - public VMenuBar getWidget() { - return (VMenuBar) super.getWidget(); - } - - @Override - public void layout() { - getWidget().iLayout(); - } - - @Override - public TooltipInfo getTooltipInfo(Element element) { - TooltipInfo info = null; - - // Check content of widget to find tooltip for element - if (element != getWidget().getElement()) { - - VMenuBar.CustomMenuItem item = getWidget().getMenuItemWithElement( - (com.google.gwt.user.client.Element) element); - if (item != null) { - info = item.getTooltip(); - } - } - - // Use default tooltip if nothing found from DOM three - if (info == null) { - info = super.getTooltipInfo(element); - } - - return info; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/menubar/MenuItem.java b/client/src/com/vaadin/terminal/gwt/client/ui/menubar/MenuItem.java deleted file mode 100644 index 9579f5a9b0..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/menubar/MenuItem.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.menubar; - -/* - * Copyright 2007 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -// COPIED HERE DUE package privates in GWT -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.ui.HasHTML; -import com.google.gwt.user.client.ui.UIObject; - -/** - * A widget that can be placed in a - * {@link com.google.gwt.user.client.ui.MenuBar}. Menu items can either fire a - * {@link com.google.gwt.user.client.Command} when they are clicked, or open a - * cascading sub-menu. - * - * @deprecated - */ -@Deprecated -public class MenuItem extends UIObject implements HasHTML { - - private static final String DEPENDENT_STYLENAME_SELECTED_ITEM = "selected"; - - private Command command; - private MenuBar parentMenu, subMenu; - - /** - * Constructs a new menu item that fires a command when it is selected. - * - * @param text - * the item's text - * @param cmd - * the command to be fired when it is selected - */ - public MenuItem(String text, Command cmd) { - this(text, false); - setCommand(cmd); - } - - /** - * Constructs a new menu item that fires a command when it is selected. - * - * @param text - * the item's text - * @param asHTML - * <code>true</code> to treat the specified text as html - * @param cmd - * the command to be fired when it is selected - */ - public MenuItem(String text, boolean asHTML, Command cmd) { - this(text, asHTML); - setCommand(cmd); - } - - /** - * Constructs a new menu item that cascades to a sub-menu when it is - * selected. - * - * @param text - * the item's text - * @param subMenu - * the sub-menu to be displayed when it is selected - */ - public MenuItem(String text, MenuBar subMenu) { - this(text, false); - setSubMenu(subMenu); - } - - /** - * Constructs a new menu item that cascades to a sub-menu when it is - * selected. - * - * @param text - * the item's text - * @param asHTML - * <code>true</code> to treat the specified text as html - * @param subMenu - * the sub-menu to be displayed when it is selected - */ - public MenuItem(String text, boolean asHTML, MenuBar subMenu) { - this(text, asHTML); - setSubMenu(subMenu); - } - - MenuItem(String text, boolean asHTML) { - setElement(DOM.createTD()); - setSelectionStyle(false); - - if (asHTML) { - setHTML(text); - } else { - setText(text); - } - setStyleName("gwt-MenuItem"); - } - - /** - * Gets the command associated with this item. - * - * @return this item's command, or <code>null</code> if none exists - */ - public Command getCommand() { - return command; - } - - @Override - public String getHTML() { - return DOM.getInnerHTML(getElement()); - } - - /** - * Gets the menu that contains this item. - * - * @return the parent menu, or <code>null</code> if none exists. - */ - public MenuBar getParentMenu() { - return parentMenu; - } - - /** - * Gets the sub-menu associated with this item. - * - * @return this item's sub-menu, or <code>null</code> if none exists - */ - public MenuBar getSubMenu() { - return subMenu; - } - - @Override - public String getText() { - return DOM.getInnerText(getElement()); - } - - /** - * Sets the command associated with this item. - * - * @param cmd - * the command to be associated with this item - */ - public void setCommand(Command cmd) { - command = cmd; - } - - @Override - public void setHTML(String html) { - DOM.setInnerHTML(getElement(), html); - } - - /** - * Sets the sub-menu associated with this item. - * - * @param subMenu - * this item's new sub-menu - */ - public void setSubMenu(MenuBar subMenu) { - this.subMenu = subMenu; - } - - @Override - public void setText(String text) { - DOM.setInnerText(getElement(), text); - } - - void setParentMenu(MenuBar parentMenu) { - this.parentMenu = parentMenu; - } - - void setSelectionStyle(boolean selected) { - if (selected) { - addStyleDependentName(DEPENDENT_STYLENAME_SELECTED_ITEM); - } else { - removeStyleDependentName(DEPENDENT_STYLENAME_SELECTED_ITEM); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java b/client/src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java deleted file mode 100644 index fe47fcca66..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java +++ /dev/null @@ -1,1463 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.menubar; - -import java.util.ArrayList; -import java.util.List; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Overflow; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.event.logical.shared.CloseEvent; -import com.google.gwt.event.logical.shared.CloseHandler; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.ui.HasHTML; -import com.google.gwt.user.client.ui.PopupPanel; -import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ui.menubar.MenuBarConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.LayoutManager; -import com.vaadin.terminal.gwt.client.TooltipInfo; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.Icon; -import com.vaadin.terminal.gwt.client.ui.SimpleFocusablePanel; -import com.vaadin.terminal.gwt.client.ui.SubPartAware; -import com.vaadin.terminal.gwt.client.ui.VLazyExecutor; -import com.vaadin.terminal.gwt.client.ui.VOverlay; - -public class VMenuBar extends SimpleFocusablePanel implements -CloseHandler<PopupPanel>, KeyPressHandler, KeyDownHandler, -FocusHandler, SubPartAware { - - // The hierarchy of VMenuBar is a bit weird as VMenuBar is the Paintable, - // used for the root menu but also used for the sub menus. - - /** Set the CSS class name to allow styling. */ - public static final String CLASSNAME = "v-menubar"; - - /** For server connections **/ - protected String uidlId; - protected ApplicationConnection client; - - protected final VMenuBar hostReference = this; - protected CustomMenuItem moreItem = null; - - // Only used by the root menu bar - protected VMenuBar collapsedRootItems; - - // Construct an empty command to be used when the item has no command - // associated - protected static final Command emptyCommand = null; - - /** Widget fields **/ - protected boolean subMenu; - protected ArrayList<CustomMenuItem> items; - protected Element containerElement; - protected VOverlay popup; - protected VMenuBar visibleChildMenu; - protected boolean menuVisible = false; - protected VMenuBar parentMenu; - protected CustomMenuItem selected; - - boolean enabled = true; - - private VLazyExecutor iconLoadedExecutioner = new VLazyExecutor(100, - new ScheduledCommand() { - - @Override - public void execute() { - iLayout(true); - } - }); - - boolean openRootOnHover; - - boolean htmlContentAllowed; - - public VMenuBar() { - // Create an empty horizontal menubar - this(false, null); - - // Navigation is only handled by the root bar - addFocusHandler(this); - - /* - * Firefox auto-repeat works correctly only if we use a key press - * handler, other browsers handle it correctly when using a key down - * handler - */ - if (BrowserInfo.get().isGecko()) { - addKeyPressHandler(this); - } else { - addKeyDownHandler(this); - } - } - - public VMenuBar(boolean subMenu, VMenuBar parentMenu) { - - items = new ArrayList<CustomMenuItem>(); - popup = null; - visibleChildMenu = null; - - containerElement = getElement(); - - if (!subMenu) { - setStyleName(CLASSNAME); - } else { - setStyleName(CLASSNAME + "-submenu"); - this.parentMenu = parentMenu; - } - this.subMenu = subMenu; - - sinkEvents(Event.ONCLICK | Event.ONMOUSEOVER | Event.ONMOUSEOUT - | Event.ONLOAD); - } - - @Override - protected void onDetach() { - super.onDetach(); - if (!subMenu) { - setSelected(null); - hideChildren(); - menuVisible = false; - } - } - - void updateSize() { - // Take from setWidth - if (!subMenu) { - // Only needed for root level menu - hideChildren(); - setSelected(null); - menuVisible = false; - } - } - - /** - * Build the HTML content for a menu item. - * - * @param item - * @return - */ - protected String buildItemHTML(UIDL item) { - // Construct html from the text and the optional icon - StringBuffer itemHTML = new StringBuffer(); - if (item.hasAttribute("separator")) { - itemHTML.append("<span>---</span>"); - } else { - // Add submenu indicator - if (item.getChildCount() > 0) { - String bgStyle = ""; - itemHTML.append("<span class=\"" + CLASSNAME - + "-submenu-indicator\"" + bgStyle + ">►</span>"); - } - - itemHTML.append("<span class=\"" + CLASSNAME - + "-menuitem-caption\">"); - if (item.hasAttribute("icon")) { - itemHTML.append("<img src=\"" - + Util.escapeAttribute(client.translateVaadinUri(item - .getStringAttribute("icon"))) + "\" class=\"" - + Icon.CLASSNAME + "\" alt=\"\" />"); - } - String itemText = item.getStringAttribute("text"); - if (!htmlContentAllowed) { - itemText = Util.escapeHTML(itemText); - } - itemHTML.append(itemText); - itemHTML.append("</span>"); - } - return itemHTML.toString(); - } - - /** - * This is called by the items in the menu and it communicates the - * information to the server - * - * @param clickedItemId - * id of the item that was clicked - */ - public void onMenuClick(int clickedItemId) { - // Updating the state to the server can not be done before - // the server connection is known, i.e., before updateFromUIDL() - // has been called. - if (uidlId != null && client != null) { - // Communicate the user interaction parameters to server. This call - // will initiate an AJAX request to the server. - client.updateVariable(uidlId, "clickedId", clickedItemId, true); - } - } - - /** Widget methods **/ - - /** - * Returns a list of items in this menu - */ - public List<CustomMenuItem> getItems() { - return items; - } - - /** - * Remove all the items in this menu - */ - public void clearItems() { - Element e = getContainerElement(); - while (DOM.getChildCount(e) > 0) { - DOM.removeChild(e, DOM.getChild(e, 0)); - } - items.clear(); - } - - /** - * Returns the containing element of the menu - * - * @return - */ - @Override - public Element getContainerElement() { - return containerElement; - } - - /** - * Add a new item to this menu - * - * @param html - * items text - * @param cmd - * items command - * @return the item created - */ - public CustomMenuItem addItem(String html, Command cmd) { - CustomMenuItem item = GWT.create(CustomMenuItem.class); - item.setHTML(html); - item.setCommand(cmd); - - addItem(item); - return item; - } - - /** - * Add a new item to this menu - * - * @param item - */ - public void addItem(CustomMenuItem item) { - if (items.contains(item)) { - return; - } - DOM.appendChild(getContainerElement(), item.getElement()); - item.setParentMenu(this); - item.setSelected(false); - items.add(item); - } - - public void addItem(CustomMenuItem item, int index) { - if (items.contains(item)) { - return; - } - DOM.insertChild(getContainerElement(), item.getElement(), index); - item.setParentMenu(this); - item.setSelected(false); - items.add(index, item); - } - - /** - * Remove the given item from this menu - * - * @param item - */ - public void removeItem(CustomMenuItem item) { - if (items.contains(item)) { - int index = items.indexOf(item); - - DOM.removeChild(getContainerElement(), - DOM.getChild(getContainerElement(), index)); - items.remove(index); - } - } - - /* - * @see - * com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt.user - * .client.Event) - */ - @Override - public void onBrowserEvent(Event e) { - super.onBrowserEvent(e); - - // Handle onload events (icon loaded, size changes) - if (DOM.eventGetType(e) == Event.ONLOAD) { - VMenuBar parent = getParentMenu(); - if (parent != null) { - // The onload event for an image in a popup should be sent to - // the parent, which owns the popup - parent.iconLoaded(); - } else { - // Onload events for images in the root menu are handled by the - // root menu itself - iconLoaded(); - } - return; - } - - Element targetElement = DOM.eventGetTarget(e); - CustomMenuItem targetItem = null; - for (int i = 0; i < items.size(); i++) { - CustomMenuItem item = items.get(i); - if (DOM.isOrHasChild(item.getElement(), targetElement)) { - targetItem = item; - } - } - - if (targetItem != null) { - switch (DOM.eventGetType(e)) { - - case Event.ONCLICK: - if (isEnabled() && targetItem.isEnabled()) { - itemClick(targetItem); - } - if (subMenu) { - // Prevent moving keyboard focus to child menus - VMenuBar parent = parentMenu; - while (parent.getParentMenu() != null) { - parent = parent.getParentMenu(); - } - parent.setFocus(true); - } - - break; - - case Event.ONMOUSEOVER: - LazyCloser.cancelClosing(); - - if (isEnabled() && targetItem.isEnabled()) { - itemOver(targetItem); - } - break; - - case Event.ONMOUSEOUT: - itemOut(targetItem); - LazyCloser.schedule(); - break; - } - } else if (subMenu && DOM.eventGetType(e) == Event.ONCLICK && subMenu) { - // Prevent moving keyboard focus to child menus - VMenuBar parent = parentMenu; - while (parent.getParentMenu() != null) { - parent = parent.getParentMenu(); - } - parent.setFocus(true); - } - } - - private boolean isEnabled() { - return enabled; - } - - private void iconLoaded() { - iconLoadedExecutioner.trigger(); - } - - /** - * When an item is clicked - * - * @param item - */ - public void itemClick(CustomMenuItem item) { - if (item.getCommand() != null) { - setSelected(null); - - if (visibleChildMenu != null) { - visibleChildMenu.hideChildren(); - } - - hideParents(true); - menuVisible = false; - Scheduler.get().scheduleDeferred(item.getCommand()); - - } else { - if (item.getSubMenu() != null - && item.getSubMenu() != visibleChildMenu) { - setSelected(item); - showChildMenu(item); - menuVisible = true; - } else if (!subMenu) { - setSelected(null); - hideChildren(); - menuVisible = false; - } - } - } - - /** - * When the user hovers the mouse over the item - * - * @param item - */ - public void itemOver(CustomMenuItem item) { - if ((openRootOnHover || subMenu || menuVisible) && !item.isSeparator()) { - setSelected(item); - if (!subMenu && openRootOnHover && !menuVisible) { - menuVisible = true; // start opening menus - LazyCloser.prepare(this); - } - } - - if (menuVisible && visibleChildMenu != item.getSubMenu() - && popup != null) { - popup.hide(); - } - - if (menuVisible && item.getSubMenu() != null - && visibleChildMenu != item.getSubMenu()) { - showChildMenu(item); - } - } - - /** - * When the mouse is moved away from an item - * - * @param item - */ - public void itemOut(CustomMenuItem item) { - if (visibleChildMenu != item.getSubMenu()) { - hideChildMenu(item); - setSelected(null); - } else if (visibleChildMenu == null) { - setSelected(null); - } - } - - /** - * Used to autoclose submenus when they the menu is in a mode which opens - * root menus on mouse hover. - */ - private static class LazyCloser extends Timer { - static LazyCloser INSTANCE; - private VMenuBar activeRoot; - - @Override - public void run() { - activeRoot.hideChildren(); - activeRoot.setSelected(null); - activeRoot.menuVisible = false; - activeRoot = null; - } - - public static void cancelClosing() { - if (INSTANCE != null) { - INSTANCE.cancel(); - } - } - - public static void prepare(VMenuBar vMenuBar) { - if (INSTANCE == null) { - INSTANCE = new LazyCloser(); - } - if (INSTANCE.activeRoot == vMenuBar) { - INSTANCE.cancel(); - } else if (INSTANCE.activeRoot != null) { - INSTANCE.cancel(); - INSTANCE.run(); - } - INSTANCE.activeRoot = vMenuBar; - } - - public static void schedule() { - if (INSTANCE != null && INSTANCE.activeRoot != null) { - INSTANCE.schedule(750); - } - } - - } - - /** - * Shows the child menu of an item. The caller must ensure that the item has - * a submenu. - * - * @param item - */ - public void showChildMenu(CustomMenuItem item) { - - int left = 0; - int top = 0; - if (subMenu) { - left = item.getParentMenu().getAbsoluteLeft() - + item.getParentMenu().getOffsetWidth(); - top = item.getAbsoluteTop(); - } else { - left = item.getAbsoluteLeft(); - top = item.getParentMenu().getAbsoluteTop() - + item.getParentMenu().getOffsetHeight(); - } - showChildMenuAt(item, top, left); - } - - protected void showChildMenuAt(CustomMenuItem item, int top, int left) { - final int shadowSpace = 10; - - popup = new VOverlay(true, false, true); - - // Setting owner and handlers to support tooltips. Needed for tooltip - // handling of overlay widgets (will direct queries to parent menu) - if (parentMenu == null) { - popup.setOwner(this); - } else { - VMenuBar parent = parentMenu; - while (parent.getParentMenu() != null) { - parent = parent.getParentMenu(); - } - popup.setOwner(parent); - } - if (client != null) { - client.getVTooltip().connectHandlersToWidget(popup); - } - - popup.setStyleName(CLASSNAME + "-popup"); - popup.setWidget(item.getSubMenu()); - popup.addCloseHandler(this); - popup.addAutoHidePartner(item.getElement()); - - // at 0,0 because otherwise IE7 add extra scrollbars (#5547) - popup.setPopupPosition(0, 0); - - item.getSubMenu().onShow(); - visibleChildMenu = item.getSubMenu(); - item.getSubMenu().setParentMenu(this); - - popup.show(); - - if (left + popup.getOffsetWidth() >= RootPanel.getBodyElement() - .getOffsetWidth() - shadowSpace) { - if (subMenu) { - left = item.getParentMenu().getAbsoluteLeft() - - popup.getOffsetWidth() - shadowSpace; - } else { - left = RootPanel.getBodyElement().getOffsetWidth() - - popup.getOffsetWidth() - shadowSpace; - } - // Accommodate space for shadow - if (left < shadowSpace) { - left = shadowSpace; - } - } - - top = adjustPopupHeight(top, shadowSpace); - - popup.setPopupPosition(left, top); - - } - - private int adjustPopupHeight(int top, final int shadowSpace) { - // Check that the popup will fit the screen - int availableHeight = RootPanel.getBodyElement().getOffsetHeight() - - top - shadowSpace; - int missingHeight = popup.getOffsetHeight() - availableHeight; - if (missingHeight > 0) { - // First move the top of the popup to get more space - // Don't move above top of screen, don't move more than needed - int moveUpBy = Math.min(top - shadowSpace, missingHeight); - - // Update state - top -= moveUpBy; - missingHeight -= moveUpBy; - availableHeight += moveUpBy; - - if (missingHeight > 0) { - int contentWidth = visibleChildMenu.getOffsetWidth(); - - // If there's still not enough room, limit height to fit and add - // a scroll bar - Style style = popup.getElement().getStyle(); - style.setHeight(availableHeight, Unit.PX); - style.setOverflowY(Overflow.SCROLL); - - // Make room for the scroll bar by adjusting the width of the - // popup - style.setWidth(contentWidth + Util.getNativeScrollbarSize(), - Unit.PX); - popup.positionOrSizeUpdated(); - } - } - return top; - } - - /** - * Hides the submenu of an item - * - * @param item - */ - public void hideChildMenu(CustomMenuItem item) { - if (visibleChildMenu != null - && !(visibleChildMenu == item.getSubMenu())) { - popup.hide(); - } - } - - /** - * When the menu is shown. - */ - public void onShow() { - // remove possible previous selection - if (selected != null) { - selected.setSelected(false); - selected = null; - } - menuVisible = true; - } - - /** - * Listener method, fired when this menu is closed - */ - @Override - public void onClose(CloseEvent<PopupPanel> event) { - hideChildren(); - if (event.isAutoClosed()) { - hideParents(true); - menuVisible = false; - } - visibleChildMenu = null; - popup = null; - } - - /** - * Recursively hide all child menus - */ - public void hideChildren() { - if (visibleChildMenu != null) { - visibleChildMenu.hideChildren(); - popup.hide(); - } - } - - /** - * Recursively hide all parent menus - */ - public void hideParents(boolean autoClosed) { - if (visibleChildMenu != null) { - popup.hide(); - setSelected(null); - menuVisible = !autoClosed; - } - - if (getParentMenu() != null) { - getParentMenu().hideParents(autoClosed); - } - } - - /** - * Returns the parent menu of this menu, or null if this is the top-level - * menu - * - * @return - */ - public VMenuBar getParentMenu() { - return parentMenu; - } - - /** - * Set the parent menu of this menu - * - * @param parent - */ - public void setParentMenu(VMenuBar parent) { - parentMenu = parent; - } - - /** - * Returns the currently selected item of this menu, or null if nothing is - * selected - * - * @return - */ - public CustomMenuItem getSelected() { - return selected; - } - - /** - * Set the currently selected item of this menu - * - * @param item - */ - public void setSelected(CustomMenuItem item) { - // If we had something selected, unselect - if (item != selected && selected != null) { - selected.setSelected(false); - } - // If we have a valid selection, select it - if (item != null) { - item.setSelected(true); - } - - selected = item; - } - - /** - * - * A class to hold information on menu items - * - */ - public static class CustomMenuItem extends Widget implements HasHTML { - - protected String html = null; - protected Command command = null; - protected VMenuBar subMenu = null; - protected VMenuBar parentMenu = null; - protected boolean enabled = true; - protected boolean isSeparator = false; - protected boolean checkable = false; - protected boolean checked = false; - protected String description = null; - - /** - * Default menu item {@link Widget} constructor for GWT.create(). - * - * Use {@link #setHTML(String)} and {@link #setCommand(Command)} after - * constructing a menu item. - */ - public CustomMenuItem() { - this("", null); - } - - /** - * Creates a menu item {@link Widget}. - * - * @param html - * @param cmd - * @deprecated use the default constructor and {@link #setHTML(String)} - * and {@link #setCommand(Command)} instead - */ - @Deprecated - public CustomMenuItem(String html, Command cmd) { - // We need spans to allow inline-block in IE - setElement(DOM.createSpan()); - - setHTML(html); - setCommand(cmd); - setSelected(false); - setStyleName(CLASSNAME + "-menuitem"); - - } - - public void setSelected(boolean selected) { - if (selected && isSelectable()) { - addStyleDependentName("selected"); - // needed for IE6 to have a single style name to match for an - // element - // TODO Can be optimized now that IE6 is not supported any more - if (checkable) { - if (checked) { - removeStyleDependentName("selected-unchecked"); - addStyleDependentName("selected-checked"); - } else { - removeStyleDependentName("selected-checked"); - addStyleDependentName("selected-unchecked"); - } - } - } else { - removeStyleDependentName("selected"); - // needed for IE6 to have a single style name to match for an - // element - removeStyleDependentName("selected-checked"); - removeStyleDependentName("selected-unchecked"); - } - } - - public void setChecked(boolean checked) { - if (checkable && !isSeparator) { - this.checked = checked; - - if (checked) { - addStyleDependentName("checked"); - removeStyleDependentName("unchecked"); - } else { - addStyleDependentName("unchecked"); - removeStyleDependentName("checked"); - } - } else { - this.checked = false; - } - } - - public boolean isChecked() { - return checked; - } - - public void setCheckable(boolean checkable) { - if (checkable && !isSeparator) { - this.checkable = true; - } else { - setChecked(false); - this.checkable = false; - } - } - - public boolean isCheckable() { - return checkable; - } - - /* - * setters and getters for the fields - */ - - public void setSubMenu(VMenuBar subMenu) { - this.subMenu = subMenu; - } - - public VMenuBar getSubMenu() { - return subMenu; - } - - public void setParentMenu(VMenuBar parentMenu) { - this.parentMenu = parentMenu; - } - - public VMenuBar getParentMenu() { - return parentMenu; - } - - public void setCommand(Command command) { - this.command = command; - } - - public Command getCommand() { - return command; - } - - @Override - public String getHTML() { - return html; - } - - @Override - public void setHTML(String html) { - this.html = html; - DOM.setInnerHTML(getElement(), html); - - // Sink the onload event for any icons. The onload - // events are handled by the parent VMenuBar. - Util.sinkOnloadForImages(getElement()); - } - - @Override - public String getText() { - return html; - } - - @Override - public void setText(String text) { - setHTML(Util.escapeHTML(text)); - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - if (enabled) { - removeStyleDependentName("disabled"); - } else { - addStyleDependentName("disabled"); - } - } - - public boolean isEnabled() { - return enabled; - } - - private void setSeparator(boolean separator) { - isSeparator = separator; - if (separator) { - setStyleName(CLASSNAME + "-separator"); - } else { - setStyleName(CLASSNAME + "-menuitem"); - setEnabled(enabled); - } - } - - public boolean isSeparator() { - return isSeparator; - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - setSeparator(uidl.hasAttribute("separator")); - setEnabled(!uidl - .hasAttribute(MenuBarConstants.ATTRIBUTE_ITEM_DISABLED)); - - if (!isSeparator() - && uidl.hasAttribute(MenuBarConstants.ATTRIBUTE_CHECKED)) { - // if the selected attribute is present (either true or false), - // the item is selectable - setCheckable(true); - setChecked(uidl - .getBooleanAttribute(MenuBarConstants.ATTRIBUTE_CHECKED)); - } else { - setCheckable(false); - } - - if (uidl.hasAttribute(MenuBarConstants.ATTRIBUTE_ITEM_STYLE)) { - String itemStyle = uidl - .getStringAttribute(MenuBarConstants.ATTRIBUTE_ITEM_STYLE); - addStyleDependentName(itemStyle); - } - - if (uidl.hasAttribute(MenuBarConstants.ATTRIBUTE_ITEM_DESCRIPTION)) { - description = uidl - .getStringAttribute(MenuBarConstants.ATTRIBUTE_ITEM_DESCRIPTION); - } - } - - public TooltipInfo getTooltip() { - if (description == null) { - return null; - } - - return new TooltipInfo(description); - } - - /** - * Checks if the item can be selected. - * - * @return true if it is possible to select this item, false otherwise - */ - public boolean isSelectable() { - return !isSeparator() && isEnabled(); - } - - } - - /** - * @author Jouni Koivuviita / Vaadin Ltd. - */ - public void iLayout() { - iLayout(false); - updateSize(); - } - - public void iLayout(boolean iconLoadEvent) { - // Only collapse if there is more than one item in the root menu and the - // menu has an explicit size - if ((getItems().size() > 1 || (collapsedRootItems != null && collapsedRootItems - .getItems().size() > 0)) - && getElement().getStyle().getProperty("width") != null - && moreItem != null) { - - // Measure the width of the "more" item - final boolean morePresent = getItems().contains(moreItem); - addItem(moreItem); - final int moreItemWidth = moreItem.getOffsetWidth(); - if (!morePresent) { - removeItem(moreItem); - } - - int availableWidth = LayoutManager.get(client).getInnerWidth( - getElement()); - - // Used width includes the "more" item if present - int usedWidth = getConsumedWidth(); - int diff = availableWidth - usedWidth; - removeItem(moreItem); - - if (diff < 0) { - // Too many items: collapse last items from root menu - int widthNeeded = usedWidth - availableWidth; - if (!morePresent) { - widthNeeded += moreItemWidth; - } - int widthReduced = 0; - - while (widthReduced < widthNeeded && getItems().size() > 0) { - // Move last root menu item to collapsed menu - CustomMenuItem collapse = getItems().get( - getItems().size() - 1); - widthReduced += collapse.getOffsetWidth(); - removeItem(collapse); - collapsedRootItems.addItem(collapse, 0); - } - } else if (collapsedRootItems.getItems().size() > 0) { - // Space available for items: expand first items from collapsed - // menu - int widthAvailable = diff + moreItemWidth; - int widthGrowth = 0; - - while (widthAvailable > widthGrowth - && collapsedRootItems.getItems().size() > 0) { - // Move first item from collapsed menu to the root menu - CustomMenuItem expand = collapsedRootItems.getItems() - .get(0); - collapsedRootItems.removeItem(expand); - addItem(expand); - widthGrowth += expand.getOffsetWidth(); - if (collapsedRootItems.getItems().size() > 0) { - widthAvailable -= moreItemWidth; - } - if (widthGrowth > widthAvailable) { - removeItem(expand); - collapsedRootItems.addItem(expand, 0); - } else { - widthAvailable = diff + moreItemWidth; - } - } - } - if (collapsedRootItems.getItems().size() > 0) { - addItem(moreItem); - } - } - - // If a popup is open we might need to adjust the shadow as well if an - // icon shown in that popup was loaded - if (popup != null) { - // Forces a recalculation of the shadow size - popup.show(); - } - if (iconLoadEvent) { - // Size have changed if the width is undefined - Util.notifyParentOfSizeChange(this, false); - } - } - - private int getConsumedWidth() { - int w = 0; - for (CustomMenuItem item : getItems()) { - if (!collapsedRootItems.getItems().contains(item)) { - w += item.getOffsetWidth(); - } - } - return w; - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.KeyPressHandler#onKeyPress(com.google - * .gwt.event.dom.client.KeyPressEvent) - */ - @Override - public void onKeyPress(KeyPressEvent event) { - if (handleNavigation(event.getNativeEvent().getKeyCode(), - event.isControlKeyDown() || event.isMetaKeyDown(), - event.isShiftKeyDown())) { - event.preventDefault(); - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt - * .event.dom.client.KeyDownEvent) - */ - @Override - public void onKeyDown(KeyDownEvent event) { - if (handleNavigation(event.getNativeEvent().getKeyCode(), - event.isControlKeyDown() || event.isMetaKeyDown(), - event.isShiftKeyDown())) { - event.preventDefault(); - } - } - - /** - * Get the key that moves the selection upwards. By default it is the up - * arrow key but by overriding this you can change the key to whatever you - * want. - * - * @return The keycode of the key - */ - protected int getNavigationUpKey() { - return KeyCodes.KEY_UP; - } - - /** - * Get the key that moves the selection downwards. By default it is the down - * arrow key but by overriding this you can change the key to whatever you - * want. - * - * @return The keycode of the key - */ - protected int getNavigationDownKey() { - return KeyCodes.KEY_DOWN; - } - - /** - * Get the key that moves the selection left. By default it is the left - * arrow key but by overriding this you can change the key to whatever you - * want. - * - * @return The keycode of the key - */ - protected int getNavigationLeftKey() { - return KeyCodes.KEY_LEFT; - } - - /** - * Get the key that moves the selection right. By default it is the right - * arrow key but by overriding this you can change the key to whatever you - * want. - * - * @return The keycode of the key - */ - protected int getNavigationRightKey() { - return KeyCodes.KEY_RIGHT; - } - - /** - * Get the key that selects a menu item. By default it is the Enter key but - * by overriding this you can change the key to whatever you want. - * - * @return - */ - protected int getNavigationSelectKey() { - return KeyCodes.KEY_ENTER; - } - - /** - * Get the key that closes the menu. By default it is the escape key but by - * overriding this yoy can change the key to whatever you want. - * - * @return - */ - protected int getCloseMenuKey() { - return KeyCodes.KEY_ESCAPE; - } - - /** - * Handles the keyboard events handled by the MenuBar - * - * @param event - * The keyboard event received - * @return true iff the navigation event was handled - */ - public boolean handleNavigation(int keycode, boolean ctrl, boolean shift) { - - // If tab or shift+tab close menus - if (keycode == KeyCodes.KEY_TAB) { - setSelected(null); - hideChildren(); - menuVisible = false; - return false; - } - - if (ctrl || shift || !isEnabled()) { - // Do not handle tab key, nor ctrl keys - return false; - } - - if (keycode == getNavigationLeftKey()) { - if (getSelected() == null) { - // If nothing is selected then select the last item - setSelected(items.get(items.size() - 1)); - if (!getSelected().isSelectable()) { - handleNavigation(keycode, ctrl, shift); - } - } else if (visibleChildMenu == null && getParentMenu() == null) { - // If this is the root menu then move to the left - int idx = items.indexOf(getSelected()); - if (idx > 0) { - setSelected(items.get(idx - 1)); - } else { - setSelected(items.get(items.size() - 1)); - } - - if (!getSelected().isSelectable()) { - handleNavigation(keycode, ctrl, shift); - } - } else if (visibleChildMenu != null) { - // Redirect all navigation to the submenu - visibleChildMenu.handleNavigation(keycode, ctrl, shift); - - } else if (getParentMenu().getParentMenu() == null) { - // Inside a sub menu, whose parent is a root menu item - VMenuBar root = getParentMenu(); - - root.getSelected().getSubMenu().setSelected(null); - root.hideChildren(); - - // Get the root menus items and select the previous one - int idx = root.getItems().indexOf(root.getSelected()); - idx = idx > 0 ? idx : root.getItems().size(); - CustomMenuItem selected = root.getItems().get(--idx); - - while (selected.isSeparator() || !selected.isEnabled()) { - idx = idx > 0 ? idx : root.getItems().size(); - selected = root.getItems().get(--idx); - } - - root.setSelected(selected); - openMenuAndFocusFirstIfPossible(selected); - } else { - getParentMenu().getSelected().getSubMenu().setSelected(null); - getParentMenu().hideChildren(); - } - - return true; - - } else if (keycode == getNavigationRightKey()) { - - if (getSelected() == null) { - // If nothing is selected then select the first item - setSelected(items.get(0)); - if (!getSelected().isSelectable()) { - handleNavigation(keycode, ctrl, shift); - } - } else if (visibleChildMenu == null && getParentMenu() == null) { - // If this is the root menu then move to the right - int idx = items.indexOf(getSelected()); - - if (idx < items.size() - 1) { - setSelected(items.get(idx + 1)); - } else { - setSelected(items.get(0)); - } - - if (!getSelected().isSelectable()) { - handleNavigation(keycode, ctrl, shift); - } - } else if (visibleChildMenu == null - && getSelected().getSubMenu() != null) { - // If the item has a submenu then show it and move the selection - // there - showChildMenu(getSelected()); - menuVisible = true; - visibleChildMenu.handleNavigation(keycode, ctrl, shift); - } else if (visibleChildMenu == null) { - - // Get the root menu - VMenuBar root = getParentMenu(); - while (root.getParentMenu() != null) { - root = root.getParentMenu(); - } - - // Hide the submenu - root.hideChildren(); - - // Get the root menus items and select the next one - int idx = root.getItems().indexOf(root.getSelected()); - idx = idx < root.getItems().size() - 1 ? idx : -1; - CustomMenuItem selected = root.getItems().get(++idx); - - while (selected.isSeparator() || !selected.isEnabled()) { - idx = idx < root.getItems().size() - 1 ? idx : -1; - selected = root.getItems().get(++idx); - } - - root.setSelected(selected); - openMenuAndFocusFirstIfPossible(selected); - } else if (visibleChildMenu != null) { - // Redirect all navigation to the submenu - visibleChildMenu.handleNavigation(keycode, ctrl, shift); - } - - return true; - - } else if (keycode == getNavigationUpKey()) { - - if (getSelected() == null) { - // If nothing is selected then select the last item - setSelected(items.get(items.size() - 1)); - if (!getSelected().isSelectable()) { - handleNavigation(keycode, ctrl, shift); - } - } else if (visibleChildMenu != null) { - // Redirect all navigation to the submenu - visibleChildMenu.handleNavigation(keycode, ctrl, shift); - } else { - // Select the previous item if possible or loop to the last item - int idx = items.indexOf(getSelected()); - if (idx > 0) { - setSelected(items.get(idx - 1)); - } else { - setSelected(items.get(items.size() - 1)); - } - - if (!getSelected().isSelectable()) { - handleNavigation(keycode, ctrl, shift); - } - } - - return true; - - } else if (keycode == getNavigationDownKey()) { - - if (getSelected() == null) { - // If nothing is selected then select the first item - selectFirstItem(); - } else if (visibleChildMenu == null && getParentMenu() == null) { - // If this is the root menu the show the child menu with arrow - // down, if there is a child menu - openMenuAndFocusFirstIfPossible(getSelected()); - } else if (visibleChildMenu != null) { - // Redirect all navigation to the submenu - visibleChildMenu.handleNavigation(keycode, ctrl, shift); - } else { - // Select the next item if possible or loop to the first item - int idx = items.indexOf(getSelected()); - if (idx < items.size() - 1) { - setSelected(items.get(idx + 1)); - } else { - setSelected(items.get(0)); - } - - if (!getSelected().isSelectable()) { - handleNavigation(keycode, ctrl, shift); - } - } - return true; - - } else if (keycode == getCloseMenuKey()) { - setSelected(null); - hideChildren(); - menuVisible = false; - - } else if (keycode == getNavigationSelectKey()) { - if (getSelected() == null) { - // If nothing is selected then select the first item - selectFirstItem(); - } else if (visibleChildMenu != null) { - // Redirect all navigation to the submenu - visibleChildMenu.handleNavigation(keycode, ctrl, shift); - menuVisible = false; - } else if (visibleChildMenu == null - && getSelected().getSubMenu() != null) { - // If the item has a sub menu then show it and move the - // selection there - openMenuAndFocusFirstIfPossible(getSelected()); - } else { - Command command = getSelected().getCommand(); - if (command != null) { - command.execute(); - } - - setSelected(null); - hideParents(true); - } - } - - return false; - } - - private void selectFirstItem() { - for (int i = 0; i < items.size(); i++) { - CustomMenuItem item = items.get(i); - if (item.isSelectable()) { - setSelected(item); - break; - } - } - } - - private void openMenuAndFocusFirstIfPossible(CustomMenuItem menuItem) { - VMenuBar subMenu = menuItem.getSubMenu(); - if (subMenu == null) { - // No child menu? Nothing to do - return; - } - - VMenuBar parentMenu = menuItem.getParentMenu(); - parentMenu.showChildMenu(menuItem); - - menuVisible = true; - // Select the first item in the newly open submenu - subMenu.selectFirstItem(); - - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event - * .dom.client.FocusEvent) - */ - @Override - public void onFocus(FocusEvent event) { - - } - - private final String SUBPART_PREFIX = "item"; - - @Override - public Element getSubPartElement(String subPart) { - int index = Integer - .parseInt(subPart.substring(SUBPART_PREFIX.length())); - CustomMenuItem item = getItems().get(index); - - return item.getElement(); - } - - @Override - public String getSubPartName(Element subElement) { - if (!getElement().isOrHasChild(subElement)) { - return null; - } - - Element menuItemRoot = subElement; - while (menuItemRoot != null && menuItemRoot.getParentElement() != null - && menuItemRoot.getParentElement() != getElement()) { - menuItemRoot = menuItemRoot.getParentElement().cast(); - } - // "menuItemRoot" is now the root of the menu item - - final int itemCount = getItems().size(); - for (int i = 0; i < itemCount; i++) { - if (getItems().get(i).getElement() == menuItemRoot) { - String name = SUBPART_PREFIX + i; - return name; - } - } - return null; - } - - /** - * Get menu item with given DOM element - * - * @param element - * Element used in search - * @return Menu item or null if not found - */ - public CustomMenuItem getMenuItemWithElement(Element element) { - for (int i = 0; i < items.size(); i++) { - CustomMenuItem item = items.get(i); - if (DOM.isOrHasChild(item.getElement(), element)) { - return item; - } - - if (item.getSubMenu() != null) { - item = item.getSubMenu().getMenuItemWithElement(element); - if (item != null) { - return item; - } - } - } - - return null; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/nativebutton/NativeButtonConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/nativebutton/NativeButtonConnector.java deleted file mode 100644 index 2f2c66d1ed..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/nativebutton/NativeButtonConnector.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.nativebutton; - -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.DOM; -import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.button.ButtonServerRpc; -import com.vaadin.shared.ui.button.ButtonState; -import com.vaadin.terminal.gwt.client.EventHelper; -import com.vaadin.terminal.gwt.client.communication.RpcProxy; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; -import com.vaadin.terminal.gwt.client.ui.Icon; -import com.vaadin.ui.NativeButton; - -@Connect(NativeButton.class) -public class NativeButtonConnector extends AbstractComponentConnector implements - BlurHandler, FocusHandler { - - private HandlerRegistration focusHandlerRegistration; - private HandlerRegistration blurHandlerRegistration; - - private FocusAndBlurServerRpc focusBlurRpc = RpcProxy.create( - FocusAndBlurServerRpc.class, this); - - @Override - public void init() { - super.init(); - - getWidget().buttonRpcProxy = RpcProxy.create(ButtonServerRpc.class, - this); - getWidget().client = getConnection(); - getWidget().paintableId = getConnectorId(); - } - - @Override - public boolean delegateCaptionHandling() { - return false; - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - getWidget().disableOnClick = getState().isDisableOnClick(); - focusHandlerRegistration = EventHelper.updateFocusHandler(this, - focusHandlerRegistration); - blurHandlerRegistration = EventHelper.updateBlurHandler(this, - blurHandlerRegistration); - - // Set text - if (getState().isHtmlContentAllowed()) { - getWidget().setHTML(getState().getCaption()); - } else { - getWidget().setText(getState().getCaption()); - } - - // handle error - if (null != getState().getErrorMessage()) { - if (getWidget().errorIndicatorElement == null) { - getWidget().errorIndicatorElement = DOM.createSpan(); - getWidget().errorIndicatorElement - .setClassName("v-errorindicator"); - } - getWidget().getElement().insertBefore( - getWidget().errorIndicatorElement, - getWidget().captionElement); - - } else if (getWidget().errorIndicatorElement != null) { - getWidget().getElement().removeChild( - getWidget().errorIndicatorElement); - getWidget().errorIndicatorElement = null; - } - - if (getState().getIcon() != null) { - if (getWidget().icon == null) { - getWidget().icon = new Icon(getConnection()); - getWidget().getElement().insertBefore( - getWidget().icon.getElement(), - getWidget().captionElement); - } - getWidget().icon.setUri(getState().getIcon().getURL()); - } else { - if (getWidget().icon != null) { - getWidget().getElement().removeChild( - getWidget().icon.getElement()); - getWidget().icon = null; - } - } - - } - - @Override - public VNativeButton getWidget() { - return (VNativeButton) super.getWidget(); - } - - @Override - public ButtonState getState() { - return (ButtonState) super.getState(); - } - - @Override - public void onFocus(FocusEvent event) { - // EventHelper.updateFocusHandler ensures that this is called only when - // there is a listener on server side - focusBlurRpc.focus(); - } - - @Override - public void onBlur(BlurEvent event) { - // EventHelper.updateFocusHandler ensures that this is called only when - // there is a listener on server side - focusBlurRpc.blur(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java b/client/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java deleted file mode 100644 index 1ab16eccc4..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.nativebutton; - -import com.google.gwt.dom.client.Element; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.Button; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.button.ButtonServerRpc; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.Icon; - -public class VNativeButton extends Button implements ClickHandler { - - public static final String CLASSNAME = "v-nativebutton"; - - protected String width = null; - - protected String paintableId; - - protected ApplicationConnection client; - - ButtonServerRpc buttonRpcProxy; - - protected Element errorIndicatorElement; - - protected final Element captionElement = DOM.createSpan(); - - protected Icon icon; - - /** - * Helper flag to handle special-case where the button is moved from under - * mouse while clicking it. In this case mouse leaves the button without - * moving. - */ - private boolean clickPending; - - protected boolean disableOnClick = false; - - public VNativeButton() { - setStyleName(CLASSNAME); - - getElement().appendChild(captionElement); - captionElement.setClassName(getStyleName() + "-caption"); - - addClickHandler(this); - - sinkEvents(Event.ONMOUSEDOWN); - sinkEvents(Event.ONMOUSEUP); - } - - @Override - public void setText(String text) { - captionElement.setInnerText(text); - } - - @Override - public void setHTML(String html) { - captionElement.setInnerHTML(html); - } - - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - - if (DOM.eventGetType(event) == Event.ONLOAD) { - Util.notifyParentOfSizeChange(this, true); - - } else if (DOM.eventGetType(event) == Event.ONMOUSEDOWN - && event.getButton() == Event.BUTTON_LEFT) { - clickPending = true; - } else if (DOM.eventGetType(event) == Event.ONMOUSEMOVE) { - clickPending = false; - } else if (DOM.eventGetType(event) == Event.ONMOUSEOUT) { - if (clickPending) { - click(); - } - clickPending = false; - } - } - - @Override - public void setWidth(String width) { - this.width = width; - super.setWidth(width); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event - * .dom.client.ClickEvent) - */ - @Override - public void onClick(ClickEvent event) { - if (paintableId == null || client == null) { - return; - } - - if (BrowserInfo.get().isSafari()) { - VNativeButton.this.setFocus(true); - } - if (disableOnClick) { - setEnabled(false); - buttonRpcProxy.disableOnClick(); - } - - // Add mouse details - MouseEventDetails details = MouseEventDetailsBuilder - .buildMouseEventDetails(event.getNativeEvent(), getElement()); - buttonRpcProxy.click(details); - - clickPending = false; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/nativeselect/NativeSelectConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/nativeselect/NativeSelectConnector.java deleted file mode 100644 index e88ed8b2f3..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/nativeselect/NativeSelectConnector.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.nativeselect; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.gwt.client.ui.optiongroup.OptionGroupBaseConnector; -import com.vaadin.ui.NativeSelect; - -@Connect(NativeSelect.class) -public class NativeSelectConnector extends OptionGroupBaseConnector { - - @Override - public VNativeSelect getWidget() { - return (VNativeSelect) super.getWidget(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/nativeselect/VNativeSelect.java b/client/src/com/vaadin/terminal/gwt/client/ui/nativeselect/VNativeSelect.java deleted file mode 100644 index eb77f5f113..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/nativeselect/VNativeSelect.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.nativeselect; - -import java.util.ArrayList; -import java.util.Iterator; - -import com.google.gwt.event.dom.client.ChangeEvent; -import com.google.gwt.user.client.ui.ListBox; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.Field; -import com.vaadin.terminal.gwt.client.ui.optiongroup.VOptionGroupBase; - -public class VNativeSelect extends VOptionGroupBase implements Field { - - public static final String CLASSNAME = "v-select"; - - protected ListBox select; - - private boolean firstValueIsTemporaryNullItem = false; - - public VNativeSelect() { - super(new ListBox(false), CLASSNAME); - select = getOptionsContainer(); - select.setVisibleItemCount(1); - select.addChangeHandler(this); - select.setStyleName(CLASSNAME + "-select"); - - } - - protected ListBox getOptionsContainer() { - return (ListBox) optionsContainer; - } - - @Override - protected void buildOptions(UIDL uidl) { - select.setEnabled(!isDisabled() && !isReadonly()); - select.clear(); - firstValueIsTemporaryNullItem = false; - - if (isNullSelectionAllowed() && !isNullSelectionItemAvailable()) { - // can't unselect last item in singleselect mode - select.addItem("", (String) null); - } - boolean selected = false; - for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) { - final UIDL optionUidl = (UIDL) i.next(); - select.addItem(optionUidl.getStringAttribute("caption"), - optionUidl.getStringAttribute("key")); - if (optionUidl.hasAttribute("selected")) { - select.setItemSelected(select.getItemCount() - 1, true); - selected = true; - } - } - if (!selected && !isNullSelectionAllowed()) { - // null-select not allowed, but value not selected yet; add null and - // remove when something is selected - select.insertItem("", (String) null, 0); - select.setItemSelected(0, true); - firstValueIsTemporaryNullItem = true; - } - } - - @Override - protected String[] getSelectedItems() { - final ArrayList<String> selectedItemKeys = new ArrayList<String>(); - for (int i = 0; i < select.getItemCount(); i++) { - if (select.isItemSelected(i)) { - selectedItemKeys.add(select.getValue(i)); - } - } - return selectedItemKeys.toArray(new String[selectedItemKeys.size()]); - } - - @Override - public void onChange(ChangeEvent event) { - - if (select.isMultipleSelect()) { - client.updateVariable(paintableId, "selected", getSelectedItems(), - isImmediate()); - } else { - client.updateVariable(paintableId, "selected", new String[] { "" - + getSelectedItem() }, isImmediate()); - } - if (firstValueIsTemporaryNullItem) { - // remove temporary empty item - select.removeItem(0); - firstValueIsTemporaryNullItem = false; - } - } - - @Override - public void setHeight(String height) { - select.setHeight(height); - super.setHeight(height); - } - - @Override - public void setWidth(String width) { - select.setWidth(width); - super.setWidth(width); - } - - @Override - protected void setTabIndex(int tabIndex) { - getOptionsContainer().setTabIndex(tabIndex); - } - - @Override - public void focus() { - select.setFocus(true); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java b/client/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java deleted file mode 100644 index b668c9a88c..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.notification; - -import java.util.ArrayList; -import java.util.Date; -import java.util.EventObject; -import java.util.Iterator; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.Position; -import com.vaadin.shared.ui.ui.UIConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.VOverlay; - -public class VNotification extends VOverlay { - - public static final Position CENTERED = Position.MIDDLE_CENTER; - public static final Position CENTERED_TOP = Position.TOP_CENTER; - public static final Position CENTERED_BOTTOM = Position.BOTTOM_CENTER; - public static final Position TOP_LEFT = Position.TOP_LEFT; - public static final Position TOP_RIGHT = Position.TOP_RIGHT; - public static final Position BOTTOM_LEFT = Position.BOTTOM_LEFT; - public static final Position BOTTOM_RIGHT = Position.BOTTOM_RIGHT; - - public static final int DELAY_FOREVER = -1; - public static final int DELAY_NONE = 0; - - private static final String STYLENAME = "v-Notification"; - private static final int mouseMoveThreshold = 7; - private static final int Z_INDEX_BASE = 20000; - public static final String STYLE_SYSTEM = "system"; - private static final int FADE_ANIMATION_INTERVAL = 50; // == 20 fps - - private static final ArrayList<VNotification> notifications = new ArrayList<VNotification>(); - - private int startOpacity = 90; - private int fadeMsec = 400; - private int delayMsec = 1000; - - private Timer fader; - private Timer delay; - - private int x = -1; - private int y = -1; - - private String temporaryStyle; - - private ArrayList<EventListener> listeners; - private static final int TOUCH_DEVICE_IDLE_DELAY = 1000; - - /** - * Default constructor. You should use GWT.create instead. - */ - public VNotification() { - setStyleName(STYLENAME); - sinkEvents(Event.ONCLICK); - DOM.setStyleAttribute(getElement(), "zIndex", "" + Z_INDEX_BASE); - } - - /** - * @deprecated Use static {@link #createNotification(int)} instead to enable - * GWT deferred binding. - * - * @param delayMsec - */ - @Deprecated - public VNotification(int delayMsec) { - this(); - this.delayMsec = delayMsec; - if (BrowserInfo.get().isTouchDevice()) { - new Timer() { - @Override - public void run() { - if (isAttached()) { - fade(); - } - } - }.schedule(delayMsec + TOUCH_DEVICE_IDLE_DELAY); - } - } - - /** - * @deprecated Use static {@link #createNotification(int, int, int)} instead - * to enable GWT deferred binding. - * - * @param delayMsec - * @param fadeMsec - * @param startOpacity - */ - @Deprecated - public VNotification(int delayMsec, int fadeMsec, int startOpacity) { - this(delayMsec); - this.fadeMsec = fadeMsec; - this.startOpacity = startOpacity; - } - - public void startDelay() { - DOM.removeEventPreview(this); - if (delayMsec > 0) { - if (delay == null) { - delay = new Timer() { - @Override - public void run() { - fade(); - } - }; - delay.schedule(delayMsec); - } - } else if (delayMsec == 0) { - fade(); - } - } - - @Override - public void show() { - show(CENTERED); - } - - public void show(String style) { - show(CENTERED, style); - } - - public void show(com.vaadin.shared.Position position) { - show(position, null); - } - - public void show(Widget widget, Position position, String style) { - setWidget(widget); - show(position, style); - } - - public void show(String html, Position position, String style) { - setWidget(new HTML(html)); - show(position, style); - } - - public void show(Position position, String style) { - setOpacity(getElement(), startOpacity); - if (style != null) { - temporaryStyle = style; - addStyleName(style); - addStyleDependentName(style); - } - super.show(); - notifications.add(this); - setPosition(position); - positionOrSizeUpdated(); - /** - * Android 4 fails to render notifications correctly without a little - * nudge (#8551) - */ - if (BrowserInfo.get().isAndroid()) { - Util.setStyleTemporarily(getElement(), "display", "none"); - } - } - - @Override - public void hide() { - DOM.removeEventPreview(this); - cancelDelay(); - cancelFade(); - if (temporaryStyle != null) { - removeStyleName(temporaryStyle); - removeStyleDependentName(temporaryStyle); - temporaryStyle = null; - } - super.hide(); - notifications.remove(this); - fireEvent(new HideEvent(this)); - } - - public void fade() { - DOM.removeEventPreview(this); - cancelDelay(); - if (fader == null) { - fader = new Timer() { - private final long start = new Date().getTime(); - - @Override - public void run() { - /* - * To make animation smooth, don't count that event happens - * on time. Reduce opacity according to the actual time - * spent instead of fixed decrement. - */ - long now = new Date().getTime(); - long timeEplaced = now - start; - float remainingFraction = 1 - timeEplaced - / (float) fadeMsec; - int opacity = (int) (startOpacity * remainingFraction); - if (opacity <= 0) { - cancel(); - hide(); - if (BrowserInfo.get().isOpera()) { - // tray notification on opera needs to explicitly - // define - // size, reset it - DOM.setStyleAttribute(getElement(), "width", ""); - DOM.setStyleAttribute(getElement(), "height", ""); - } - } else { - setOpacity(getElement(), opacity); - } - } - }; - fader.scheduleRepeating(FADE_ANIMATION_INTERVAL); - } - } - - public void setPosition(com.vaadin.shared.Position position) { - final Element el = getElement(); - DOM.setStyleAttribute(el, "top", ""); - DOM.setStyleAttribute(el, "left", ""); - DOM.setStyleAttribute(el, "bottom", ""); - DOM.setStyleAttribute(el, "right", ""); - switch (position) { - case TOP_LEFT: - DOM.setStyleAttribute(el, "top", "0px"); - DOM.setStyleAttribute(el, "left", "0px"); - break; - case TOP_RIGHT: - DOM.setStyleAttribute(el, "top", "0px"); - DOM.setStyleAttribute(el, "right", "0px"); - break; - case BOTTOM_RIGHT: - DOM.setStyleAttribute(el, "position", "absolute"); - if (BrowserInfo.get().isOpera()) { - // tray notification on opera needs explicitly defined size - DOM.setStyleAttribute(el, "width", getOffsetWidth() + "px"); - DOM.setStyleAttribute(el, "height", getOffsetHeight() + "px"); - } - DOM.setStyleAttribute(el, "bottom", "0px"); - DOM.setStyleAttribute(el, "right", "0px"); - break; - case BOTTOM_LEFT: - DOM.setStyleAttribute(el, "bottom", "0px"); - DOM.setStyleAttribute(el, "left", "0px"); - break; - case TOP_CENTER: - center(); - DOM.setStyleAttribute(el, "top", "0px"); - break; - case BOTTOM_CENTER: - center(); - DOM.setStyleAttribute(el, "top", ""); - DOM.setStyleAttribute(el, "bottom", "0px"); - break; - default: - case MIDDLE_CENTER: - center(); - break; - } - } - - private void cancelFade() { - if (fader != null) { - fader.cancel(); - fader = null; - } - } - - private void cancelDelay() { - if (delay != null) { - delay.cancel(); - delay = null; - } - } - - private void setOpacity(Element el, int opacity) { - DOM.setStyleAttribute(el, "opacity", "" + (opacity / 100.0)); - if (BrowserInfo.get().isIE()) { - DOM.setStyleAttribute(el, "filter", "Alpha(opacity=" + opacity - + ")"); - } - } - - @Override - public void onBrowserEvent(Event event) { - DOM.removeEventPreview(this); - if (fader == null) { - fade(); - } - } - - @Override - public boolean onEventPreview(Event event) { - int type = DOM.eventGetType(event); - // "modal" - if (delayMsec == -1 || temporaryStyle == STYLE_SYSTEM) { - if (type == Event.ONCLICK) { - if (DOM.isOrHasChild(getElement(), DOM.eventGetTarget(event))) { - fade(); - return false; - } - } else if (type == Event.ONKEYDOWN - && event.getKeyCode() == KeyCodes.KEY_ESCAPE) { - fade(); - return false; - } - if (temporaryStyle == STYLE_SYSTEM) { - return true; - } else { - return false; - } - } - // default - switch (type) { - case Event.ONMOUSEMOVE: - - if (x < 0) { - x = DOM.eventGetClientX(event); - y = DOM.eventGetClientY(event); - } else if (Math.abs(DOM.eventGetClientX(event) - x) > mouseMoveThreshold - || Math.abs(DOM.eventGetClientY(event) - y) > mouseMoveThreshold) { - startDelay(); - } - break; - case Event.ONMOUSEDOWN: - case Event.ONMOUSEWHEEL: - case Event.ONSCROLL: - startDelay(); - break; - case Event.ONKEYDOWN: - if (event.getRepeat()) { - return true; - } - startDelay(); - break; - default: - break; - } - return true; - } - - public void addEventListener(EventListener listener) { - if (listeners == null) { - listeners = new ArrayList<EventListener>(); - } - listeners.add(listener); - } - - public void removeEventListener(EventListener listener) { - if (listeners == null) { - return; - } - listeners.remove(listener); - } - - private void fireEvent(HideEvent event) { - if (listeners != null) { - for (Iterator<EventListener> it = listeners.iterator(); it - .hasNext();) { - EventListener l = it.next(); - l.notificationHidden(event); - } - } - } - - public static void showNotification(ApplicationConnection client, - final UIDL notification) { - boolean onlyPlainText = notification - .hasAttribute(UIConstants.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED); - String html = ""; - if (notification - .hasAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_ICON)) { - final String parsedUri = client - .translateVaadinUri(notification - .getStringAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_ICON)); - html += "<img src=\"" + Util.escapeAttribute(parsedUri) + "\" />"; - } - if (notification - .hasAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_CAPTION)) { - String caption = notification - .getStringAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_CAPTION); - if (onlyPlainText) { - caption = Util.escapeHTML(caption); - caption = caption.replaceAll("\\n", "<br />"); - } - html += "<h1>" + caption + "</h1>"; - } - if (notification - .hasAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_MESSAGE)) { - String message = notification - .getStringAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_MESSAGE); - if (onlyPlainText) { - message = Util.escapeHTML(message); - message = message.replaceAll("\\n", "<br />"); - } - html += "<p>" + message + "</p>"; - } - - final String style = notification - .hasAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_STYLE) ? notification - .getStringAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_STYLE) - : null; - - final int pos = notification - .getIntAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_POSITION); - Position position = Position.values()[pos]; - - final int delay = notification - .getIntAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_DELAY); - createNotification(delay).show(html, position, style); - } - - public static VNotification createNotification(int delayMsec) { - final VNotification notification = GWT.create(VNotification.class); - notification.delayMsec = delayMsec; - if (BrowserInfo.get().isTouchDevice()) { - new Timer() { - @Override - public void run() { - if (notification.isAttached()) { - notification.fade(); - } - } - }.schedule(notification.delayMsec + TOUCH_DEVICE_IDLE_DELAY); - } - return notification; - } - - public class HideEvent extends EventObject { - - public HideEvent(Object source) { - super(source); - } - } - - public interface EventListener extends java.util.EventListener { - public void notificationHidden(HideEvent event); - } - - /** - * Moves currently visible notifications to the top of the event preview - * stack. Can be called when opening other overlays such as subwindows to - * ensure the notifications receive the events they need and don't linger - * indefinitely. See #7136. - * - * TODO Should this be a generic Overlay feature instead? - */ - public static void bringNotificationsToFront() { - for (VNotification notification : notifications) { - DOM.removeEventPreview(notification); - DOM.addEventPreview(notification); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/optiongroup/OptionGroupBaseConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/optiongroup/OptionGroupBaseConnector.java deleted file mode 100644 index 4eabdabb36..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/optiongroup/OptionGroupBaseConnector.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.optiongroup; - -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.AbstractFieldConnector; -import com.vaadin.terminal.gwt.client.ui.nativebutton.VNativeButton; -import com.vaadin.terminal.gwt.client.ui.textfield.VTextField; - -public abstract class OptionGroupBaseConnector extends AbstractFieldConnector - implements Paintable { - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - // Save details - getWidget().client = client; - getWidget().paintableId = uidl.getId(); - - if (!isRealUpdate(uidl)) { - return; - } - - getWidget().selectedKeys = uidl.getStringArrayVariableAsSet("selected"); - - getWidget().readonly = isReadOnly(); - getWidget().disabled = !isEnabled(); - getWidget().multiselect = "multi".equals(uidl - .getStringAttribute("selectmode")); - getWidget().immediate = getState().isImmediate(); - getWidget().nullSelectionAllowed = uidl - .getBooleanAttribute("nullselect"); - getWidget().nullSelectionItemAvailable = uidl - .getBooleanAttribute("nullselectitem"); - - if (uidl.hasAttribute("cols")) { - getWidget().cols = uidl.getIntAttribute("cols"); - } - if (uidl.hasAttribute("rows")) { - getWidget().rows = uidl.getIntAttribute("rows"); - } - - final UIDL ops = uidl.getChildUIDL(0); - - if (getWidget().getColumns() > 0) { - getWidget().container.setWidth(getWidget().getColumns() + "em"); - if (getWidget().container != getWidget().optionsContainer) { - getWidget().optionsContainer.setWidth("100%"); - } - } - - getWidget().buildOptions(ops); - - if (uidl.getBooleanAttribute("allownewitem")) { - if (getWidget().newItemField == null) { - getWidget().newItemButton = new VNativeButton(); - getWidget().newItemButton.setText("+"); - getWidget().newItemButton.addClickHandler(getWidget()); - getWidget().newItemField = new VTextField(); - getWidget().newItemField.addKeyPressHandler(getWidget()); - } - getWidget().newItemField.setEnabled(!getWidget().disabled - && !getWidget().readonly); - getWidget().newItemButton.setEnabled(!getWidget().disabled - && !getWidget().readonly); - - if (getWidget().newItemField == null - || getWidget().newItemField.getParent() != getWidget().container) { - getWidget().container.add(getWidget().newItemField); - getWidget().container.add(getWidget().newItemButton); - final int w = getWidget().container.getOffsetWidth() - - getWidget().newItemButton.getOffsetWidth(); - getWidget().newItemField.setWidth(Math.max(w, 0) + "px"); - } - } else if (getWidget().newItemField != null) { - getWidget().container.remove(getWidget().newItemField); - getWidget().container.remove(getWidget().newItemButton); - } - - getWidget().setTabIndex( - uidl.hasAttribute("tabindex") ? uidl - .getIntAttribute("tabindex") : 0); - - } - - @Override - public VOptionGroupBase getWidget() { - return (VOptionGroupBase) super.getWidget(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/optiongroup/OptionGroupConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/optiongroup/OptionGroupConnector.java deleted file mode 100644 index a15ad3b163..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/optiongroup/OptionGroupConnector.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.optiongroup; - -import java.util.ArrayList; - -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.ui.CheckBox; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.EventId; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.optiongroup.OptionGroupConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.ui.OptionGroup; - -@Connect(OptionGroup.class) -public class OptionGroupConnector extends OptionGroupBaseConnector { - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - getWidget().htmlContentAllowed = uidl - .hasAttribute(OptionGroupConstants.HTML_CONTENT_ALLOWED); - - super.updateFromUIDL(uidl, client); - - getWidget().sendFocusEvents = client.hasEventListeners(this, - EventId.FOCUS); - getWidget().sendBlurEvents = client.hasEventListeners(this, - EventId.BLUR); - - if (getWidget().focusHandlers != null) { - for (HandlerRegistration reg : getWidget().focusHandlers) { - reg.removeHandler(); - } - getWidget().focusHandlers.clear(); - getWidget().focusHandlers = null; - - for (HandlerRegistration reg : getWidget().blurHandlers) { - reg.removeHandler(); - } - getWidget().blurHandlers.clear(); - getWidget().blurHandlers = null; - } - - if (getWidget().sendFocusEvents || getWidget().sendBlurEvents) { - getWidget().focusHandlers = new ArrayList<HandlerRegistration>(); - getWidget().blurHandlers = new ArrayList<HandlerRegistration>(); - - // add focus and blur handlers to checkboxes / radio buttons - for (Widget wid : getWidget().panel) { - if (wid instanceof CheckBox) { - getWidget().focusHandlers.add(((CheckBox) wid) - .addFocusHandler(getWidget())); - getWidget().blurHandlers.add(((CheckBox) wid) - .addBlurHandler(getWidget())); - } - } - } - } - - @Override - public VOptionGroup getWidget() { - return (VOptionGroup) super.getWidget(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/optiongroup/VOptionGroup.java b/client/src/com/vaadin/terminal/gwt/client/ui/optiongroup/VOptionGroup.java deleted file mode 100644 index 710a1c8e63..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/optiongroup/VOptionGroup.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.optiongroup; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.LoadEvent; -import com.google.gwt.event.dom.client.LoadHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.ui.CheckBox; -import com.google.gwt.user.client.ui.FocusWidget; -import com.google.gwt.user.client.ui.Focusable; -import com.google.gwt.user.client.ui.Panel; -import com.google.gwt.user.client.ui.RadioButton; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.EventId; -import com.vaadin.shared.ui.optiongroup.OptionGroupConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.Icon; -import com.vaadin.terminal.gwt.client.ui.checkbox.VCheckBox; - -public class VOptionGroup extends VOptionGroupBase implements FocusHandler, - BlurHandler { - - public static final String CLASSNAME = "v-select-optiongroup"; - - protected final Panel panel; - - private final Map<CheckBox, String> optionsToKeys; - - protected boolean sendFocusEvents = false; - protected boolean sendBlurEvents = false; - protected List<HandlerRegistration> focusHandlers = null; - protected List<HandlerRegistration> blurHandlers = null; - - private final LoadHandler iconLoadHandler = new LoadHandler() { - @Override - public void onLoad(LoadEvent event) { - Util.notifyParentOfSizeChange(VOptionGroup.this, true); - } - }; - - /** - * used to check whether a blur really was a blur of the complete - * optiongroup: if a control inside this optiongroup gains focus right after - * blur of another control inside this optiongroup (meaning: if onFocus - * fires after onBlur has fired), the blur and focus won't be sent to the - * server side as only a focus change inside this optiongroup occured - */ - private boolean blurOccured = false; - - protected boolean htmlContentAllowed = false; - - public VOptionGroup() { - super(CLASSNAME); - panel = (Panel) optionsContainer; - optionsToKeys = new HashMap<CheckBox, String>(); - } - - /* - * Return true if no elements were changed, false otherwise. - */ - @Override - protected void buildOptions(UIDL uidl) { - panel.clear(); - for (final Iterator<?> it = uidl.getChildIterator(); it.hasNext();) { - final UIDL opUidl = (UIDL) it.next(); - CheckBox op; - - String itemHtml = opUidl.getStringAttribute("caption"); - if (!htmlContentAllowed) { - itemHtml = Util.escapeHTML(itemHtml); - } - - String icon = opUidl.getStringAttribute("icon"); - if (icon != null && icon.length() != 0) { - String iconUrl = client.translateVaadinUri(icon); - itemHtml = "<img src=\"" + iconUrl + "\" class=\"" - + Icon.CLASSNAME + "\" alt=\"\" />" + itemHtml; - } - - if (isMultiselect()) { - op = new VCheckBox(); - op.setHTML(itemHtml); - } else { - op = new RadioButton(paintableId, itemHtml, true); - op.setStyleName("v-radiobutton"); - } - - if (icon != null && icon.length() != 0) { - Util.sinkOnloadForImages(op.getElement()); - op.addHandler(iconLoadHandler, LoadEvent.getType()); - } - - op.addStyleName(CLASSNAME_OPTION); - op.setValue(opUidl.getBooleanAttribute("selected")); - boolean enabled = !opUidl - .getBooleanAttribute(OptionGroupConstants.ATTRIBUTE_OPTION_DISABLED) - && !isReadonly() && !isDisabled(); - op.setEnabled(enabled); - setStyleName(op.getElement(), - ApplicationConnection.DISABLED_CLASSNAME, !enabled); - op.addClickHandler(this); - optionsToKeys.put(op, opUidl.getStringAttribute("key")); - panel.add(op); - } - } - - @Override - protected String[] getSelectedItems() { - return selectedKeys.toArray(new String[selectedKeys.size()]); - } - - @Override - public void onClick(ClickEvent event) { - super.onClick(event); - if (event.getSource() instanceof CheckBox) { - final boolean selected = ((CheckBox) event.getSource()).getValue(); - final String key = optionsToKeys.get(event.getSource()); - if (!isMultiselect()) { - selectedKeys.clear(); - } - if (selected) { - selectedKeys.add(key); - } else { - selectedKeys.remove(key); - } - client.updateVariable(paintableId, "selected", getSelectedItems(), - isImmediate()); - } - } - - @Override - protected void setTabIndex(int tabIndex) { - for (Iterator<Widget> iterator = panel.iterator(); iterator.hasNext();) { - FocusWidget widget = (FocusWidget) iterator.next(); - widget.setTabIndex(tabIndex); - } - } - - @Override - public void focus() { - Iterator<Widget> iterator = panel.iterator(); - if (iterator.hasNext()) { - ((Focusable) iterator.next()).setFocus(true); - } - } - - @Override - public void onFocus(FocusEvent arg0) { - if (!blurOccured) { - // no blur occured before this focus event - // panel was blurred => fire the event to the server side if - // requested by server side - if (sendFocusEvents) { - client.updateVariable(paintableId, EventId.FOCUS, "", true); - } - } else { - // blur occured before this focus event - // another control inside the panel (checkbox / radio box) was - // blurred => do not fire the focus and set blurOccured to false, so - // blur will not be fired, too - blurOccured = false; - } - } - - @Override - public void onBlur(BlurEvent arg0) { - blurOccured = true; - if (sendBlurEvents) { - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - // check whether blurOccured still is true and then send the - // event out to the server - if (blurOccured) { - client.updateVariable(paintableId, EventId.BLUR, "", - true); - blurOccured = false; - } - } - }); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/optiongroup/VOptionGroupBase.java b/client/src/com/vaadin/terminal/gwt/client/ui/optiongroup/VOptionGroupBase.java deleted file mode 100644 index e416e85696..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/optiongroup/VOptionGroupBase.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.optiongroup; - -import java.util.Set; - -import com.google.gwt.event.dom.client.ChangeEvent; -import com.google.gwt.event.dom.client.ChangeHandler; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.Panel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Focusable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.Field; -import com.vaadin.terminal.gwt.client.ui.nativebutton.VNativeButton; -import com.vaadin.terminal.gwt.client.ui.textfield.VTextField; - -public abstract class VOptionGroupBase extends Composite implements Field, - ClickHandler, ChangeHandler, KeyPressHandler, Focusable { - - public static final String CLASSNAME_OPTION = "v-select-option"; - - protected ApplicationConnection client; - - protected String paintableId; - - protected Set<String> selectedKeys; - - protected boolean immediate; - - protected boolean multiselect; - - protected boolean disabled; - - protected boolean readonly; - - protected int cols = 0; - - protected int rows = 0; - - protected boolean nullSelectionAllowed = true; - - protected boolean nullSelectionItemAvailable = false; - - /** - * Widget holding the different options (e.g. ListBox or Panel for radio - * buttons) (optional, fallbacks to container Panel) - */ - protected Widget optionsContainer; - - /** - * Panel containing the component - */ - protected final Panel container; - - protected VTextField newItemField; - - protected VNativeButton newItemButton; - - public VOptionGroupBase(String classname) { - container = new FlowPanel(); - initWidget(container); - optionsContainer = container; - container.setStyleName(classname); - immediate = false; - multiselect = false; - } - - /* - * Call this if you wish to specify your own container for the option - * elements (e.g. SELECT) - */ - public VOptionGroupBase(Widget w, String classname) { - this(classname); - optionsContainer = w; - container.add(optionsContainer); - } - - protected boolean isImmediate() { - return immediate; - } - - protected boolean isMultiselect() { - return multiselect; - } - - protected boolean isDisabled() { - return disabled; - } - - protected boolean isReadonly() { - return readonly; - } - - protected boolean isNullSelectionAllowed() { - return nullSelectionAllowed; - } - - protected boolean isNullSelectionItemAvailable() { - return nullSelectionItemAvailable; - } - - /** - * @return "cols" specified in uidl, 0 if not specified - */ - protected int getColumns() { - return cols; - } - - /** - * @return "rows" specified in uidl, 0 if not specified - */ - - protected int getRows() { - return rows; - } - - abstract protected void setTabIndex(int tabIndex); - - @Override - public void onClick(ClickEvent event) { - if (event.getSource() == newItemButton - && !newItemField.getText().equals("")) { - client.updateVariable(paintableId, "newitem", - newItemField.getText(), true); - newItemField.setText(""); - } - } - - @Override - public void onChange(ChangeEvent event) { - if (multiselect) { - client.updateVariable(paintableId, "selected", getSelectedItems(), - immediate); - } else { - client.updateVariable(paintableId, "selected", new String[] { "" - + getSelectedItem() }, immediate); - } - } - - @Override - public void onKeyPress(KeyPressEvent event) { - if (event.getSource() == newItemField - && event.getCharCode() == KeyCodes.KEY_ENTER) { - newItemButton.click(); - } - } - - protected abstract void buildOptions(UIDL uidl); - - protected abstract String[] getSelectedItems(); - - protected String getSelectedItem() { - final String[] sel = getSelectedItems(); - if (sel.length > 0) { - return sel[0]; - } else { - return null; - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java deleted file mode 100644 index 122547ddb4..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.orderedlayout; - -import java.util.List; - -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ui.AlignmentInfo; -import com.vaadin.shared.ui.LayoutClickRpc; -import com.vaadin.shared.ui.MarginInfo; -import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutServerRpc; -import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; -import com.vaadin.terminal.gwt.client.DirectionalManagedLayout; -import com.vaadin.terminal.gwt.client.LayoutManager; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VCaption; -import com.vaadin.terminal.gwt.client.communication.RpcProxy; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.AbstractLayoutConnector; -import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler; -import com.vaadin.terminal.gwt.client.ui.layout.ComponentConnectorLayoutSlot; -import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot; - -public abstract class AbstractOrderedLayoutConnector extends - AbstractLayoutConnector implements DirectionalManagedLayout { - - AbstractOrderedLayoutServerRpc rpc; - - private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler( - this) { - - @Override - protected ComponentConnector getChildComponent(Element element) { - return Util.getConnectorForElement(getConnection(), getWidget(), - element); - } - - @Override - protected LayoutClickRpc getLayoutClickRPC() { - return rpc; - }; - - }; - - @Override - public void init() { - super.init(); - rpc = RpcProxy.create(AbstractOrderedLayoutServerRpc.class, this); - getLayoutManager().registerDependency(this, - getWidget().spacingMeasureElement); - } - - @Override - public void onUnregister() { - LayoutManager lm = getLayoutManager(); - - VMeasuringOrderedLayout layout = getWidget(); - lm.unregisterDependency(this, layout.spacingMeasureElement); - - // Unregister child caption listeners - for (ComponentConnector child : getChildComponents()) { - VLayoutSlot slot = layout.getSlotForChild(child.getWidget()); - slot.setCaption(null); - } - } - - @Override - public AbstractOrderedLayoutState getState() { - return (AbstractOrderedLayoutState) super.getState(); - } - - @Override - public void updateCaption(ComponentConnector component) { - VMeasuringOrderedLayout layout = getWidget(); - if (VCaption.isNeeded(component.getState())) { - VLayoutSlot layoutSlot = layout.getSlotForChild(component - .getWidget()); - VCaption caption = layoutSlot.getCaption(); - if (caption == null) { - caption = new VCaption(component, getConnection()); - - Widget widget = component.getWidget(); - - layout.setCaption(widget, caption); - } - caption.updateCaption(); - } else { - layout.setCaption(component.getWidget(), null); - getLayoutManager().setNeedsLayout(this); - } - } - - @Override - public VMeasuringOrderedLayout getWidget() { - return (VMeasuringOrderedLayout) super.getWidget(); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - clickEventHandler.handleEventHandlerRegistration(); - - VMeasuringOrderedLayout layout = getWidget(); - - for (ComponentConnector child : getChildComponents()) { - VLayoutSlot slot = layout.getSlotForChild(child.getWidget()); - - AlignmentInfo alignment = new AlignmentInfo(getState() - .getChildData().get(child).getAlignmentBitmask()); - slot.setAlignment(alignment); - - double expandRatio = getState().getChildData().get(child) - .getExpandRatio(); - slot.setExpandRatio(expandRatio); - } - - layout.updateMarginStyleNames(new MarginInfo(getState() - .getMarginsBitmask())); - layout.updateSpacingStyleName(getState().isSpacing()); - - getLayoutManager().setNeedsLayout(this); - } - - private int getSizeForInnerSize(int size, boolean isVertical) { - LayoutManager layoutManager = getLayoutManager(); - Element element = getWidget().getElement(); - if (isVertical) { - return size + layoutManager.getBorderHeight(element) - + layoutManager.getPaddingHeight(element); - } else { - return size + layoutManager.getBorderWidth(element) - + layoutManager.getPaddingWidth(element); - } - } - - private static String getSizeProperty(boolean isVertical) { - return isVertical ? "height" : "width"; - } - - private boolean isUndefinedInDirection(boolean isVertical) { - if (isVertical) { - return isUndefinedHeight(); - } else { - return isUndefinedWidth(); - } - } - - private int getInnerSizeInDirection(boolean isVertical) { - if (isVertical) { - return getLayoutManager().getInnerHeight(getWidget().getElement()); - } else { - return getLayoutManager().getInnerWidth(getWidget().getElement()); - } - } - - private void layoutPrimaryDirection() { - VMeasuringOrderedLayout layout = getWidget(); - boolean isVertical = layout.isVertical; - boolean isUndefined = isUndefinedInDirection(isVertical); - - int startPadding = getStartPadding(isVertical); - int endPadding = getEndPadding(isVertical); - int spacingSize = getSpacingInDirection(isVertical); - int allocatedSize; - - if (isUndefined) { - allocatedSize = -1; - } else { - allocatedSize = getInnerSizeInDirection(isVertical); - } - - allocatedSize = layout.layoutPrimaryDirection(spacingSize, - allocatedSize, startPadding, endPadding); - - Style ownStyle = getWidget().getElement().getStyle(); - if (isUndefined) { - int outerSize = getSizeForInnerSize(allocatedSize, isVertical); - ownStyle.setPropertyPx(getSizeProperty(isVertical), outerSize); - reportUndefinedSize(outerSize, isVertical); - } else { - ownStyle.setProperty(getSizeProperty(isVertical), - getDefinedSize(isVertical)); - } - } - - private void reportUndefinedSize(int outerSize, boolean isVertical) { - if (isVertical) { - getLayoutManager().reportOuterHeight(this, outerSize); - } else { - getLayoutManager().reportOuterWidth(this, outerSize); - } - } - - private int getSpacingInDirection(boolean isVertical) { - if (isVertical) { - return getLayoutManager().getOuterHeight( - getWidget().spacingMeasureElement); - } else { - return getLayoutManager().getOuterWidth( - getWidget().spacingMeasureElement); - } - } - - private void layoutSecondaryDirection() { - VMeasuringOrderedLayout layout = getWidget(); - boolean isVertical = layout.isVertical; - boolean isUndefined = isUndefinedInDirection(!isVertical); - - int startPadding = getStartPadding(!isVertical); - int endPadding = getEndPadding(!isVertical); - - int allocatedSize; - if (isUndefined) { - allocatedSize = -1; - } else { - allocatedSize = getInnerSizeInDirection(!isVertical); - } - - allocatedSize = layout.layoutSecondaryDirection(allocatedSize, - startPadding, endPadding); - - Style ownStyle = getWidget().getElement().getStyle(); - - if (isUndefined) { - int outerSize = getSizeForInnerSize(allocatedSize, - !getWidget().isVertical); - ownStyle.setPropertyPx(getSizeProperty(!getWidget().isVertical), - outerSize); - reportUndefinedSize(outerSize, !isVertical); - } else { - ownStyle.setProperty(getSizeProperty(!getWidget().isVertical), - getDefinedSize(!getWidget().isVertical)); - } - } - - private String getDefinedSize(boolean isVertical) { - if (isVertical) { - return getState().getHeight(); - } else { - return getState().getWidth(); - } - } - - private int getStartPadding(boolean isVertical) { - if (isVertical) { - return getLayoutManager().getPaddingTop(getWidget().getElement()); - } else { - return getLayoutManager().getPaddingLeft(getWidget().getElement()); - } - } - - private int getEndPadding(boolean isVertical) { - if (isVertical) { - return getLayoutManager() - .getPaddingBottom(getWidget().getElement()); - } else { - return getLayoutManager().getPaddingRight(getWidget().getElement()); - } - } - - @Override - public void layoutHorizontally() { - if (getWidget().isVertical) { - layoutSecondaryDirection(); - } else { - layoutPrimaryDirection(); - } - } - - @Override - public void layoutVertically() { - if (getWidget().isVertical) { - layoutPrimaryDirection(); - } else { - layoutSecondaryDirection(); - } - } - - @Override - public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { - super.onConnectorHierarchyChange(event); - List<ComponentConnector> previousChildren = event.getOldChildren(); - int currentIndex = 0; - VMeasuringOrderedLayout layout = getWidget(); - - for (ComponentConnector child : getChildComponents()) { - Widget childWidget = child.getWidget(); - VLayoutSlot slot = layout.getSlotForChild(childWidget); - - if (childWidget.getParent() != layout) { - // If the child widget was previously attached to another - // AbstractOrderedLayout a slot might be found that belongs to - // another AbstractOrderedLayout. In this case we discard it and - // create a new slot. - slot = new ComponentConnectorLayoutSlot(getWidget() - .getStylePrimaryName(), child, this); - } - layout.addOrMove(slot, currentIndex++); - if (child.isRelativeWidth()) { - slot.getWrapperElement().getStyle().setWidth(100, Unit.PCT); - } - } - - for (ComponentConnector child : previousChildren) { - if (child.getParent() != this) { - // Remove slot if the connector is no longer a child of this - // layout - layout.removeSlotForWidget(child.getWidget()); - } - } - - }; - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/HorizontalLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/HorizontalLayoutConnector.java deleted file mode 100644 index 195622854d..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/HorizontalLayoutConnector.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.orderedlayout; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.ui.HorizontalLayout; - -@Connect(value = HorizontalLayout.class, loadStyle = LoadStyle.EAGER) -public class HorizontalLayoutConnector extends AbstractOrderedLayoutConnector { - - @Override - public VHorizontalLayout getWidget() { - return (VHorizontalLayout) super.getWidget(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VHorizontalLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VHorizontalLayout.java deleted file mode 100644 index 917384e72d..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VHorizontalLayout.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.orderedlayout; - -public class VHorizontalLayout extends VMeasuringOrderedLayout { - - public static final String CLASSNAME = "v-horizontallayout"; - - public VHorizontalLayout() { - super(CLASSNAME, false); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VMeasuringOrderedLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VMeasuringOrderedLayout.java deleted file mode 100644 index ee55bc07ba..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VMeasuringOrderedLayout.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.orderedlayout; - -import java.util.HashMap; -import java.util.Map; - -import com.google.gwt.dom.client.DivElement; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Node; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Position; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.ComplexPanel; -import com.google.gwt.user.client.ui.Widget; -import com.google.gwt.user.client.ui.WidgetCollection; -import com.vaadin.shared.ui.MarginInfo; -import com.vaadin.terminal.gwt.client.VCaption; -import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot; - -public class VMeasuringOrderedLayout extends ComplexPanel { - - final boolean isVertical; - - final DivElement spacingMeasureElement; - - private Map<Widget, VLayoutSlot> widgetToSlot = new HashMap<Widget, VLayoutSlot>(); - - protected VMeasuringOrderedLayout(String className, boolean isVertical) { - DivElement element = Document.get().createDivElement(); - setElement(element); - - spacingMeasureElement = Document.get().createDivElement(); - Style spacingStyle = spacingMeasureElement.getStyle(); - spacingStyle.setPosition(Position.ABSOLUTE); - getElement().appendChild(spacingMeasureElement); - - setStyleName(className); - this.isVertical = isVertical; - } - - public void addOrMove(VLayoutSlot layoutSlot, int index) { - Widget widget = layoutSlot.getWidget(); - Element wrapperElement = layoutSlot.getWrapperElement(); - - Element containerElement = getElement(); - Node childAtIndex = containerElement.getChild(index); - if (childAtIndex != wrapperElement) { - // Insert at correct location not attached or at wrong location - containerElement.insertBefore(wrapperElement, childAtIndex); - insert(widget, wrapperElement, index, false); - } - - widgetToSlot.put(widget, layoutSlot); - } - - private void togglePrefixedStyleName(String name, boolean enabled) { - if (enabled) { - addStyleDependentName(name); - } else { - removeStyleDependentName(name); - } - } - - void updateMarginStyleNames(MarginInfo marginInfo) { - togglePrefixedStyleName("margin-top", marginInfo.hasTop()); - togglePrefixedStyleName("margin-right", marginInfo.hasRight()); - togglePrefixedStyleName("margin-bottom", marginInfo.hasBottom()); - togglePrefixedStyleName("margin-left", marginInfo.hasLeft()); - } - - void updateSpacingStyleName(boolean spacingEnabled) { - String styleName = getStylePrimaryName(); - if (spacingEnabled) { - spacingMeasureElement.addClassName(styleName + "-spacing-on"); - spacingMeasureElement.removeClassName(styleName + "-spacing-off"); - } else { - spacingMeasureElement.removeClassName(styleName + "-spacing-on"); - spacingMeasureElement.addClassName(styleName + "-spacing-off"); - } - } - - public void removeSlotForWidget(Widget widget) { - VLayoutSlot slot = getSlotForChild(widget); - VCaption caption = slot.getCaption(); - if (caption != null) { - // Must remove using setCaption to ensure dependencies (layout -> - // caption) are unregistered - slot.setCaption(null); - } - - remove(slot.getWidget()); - getElement().removeChild(slot.getWrapperElement()); - widgetToSlot.remove(widget); - } - - public VLayoutSlot getSlotForChild(Widget widget) { - return widgetToSlot.get(widget); - } - - public void setCaption(Widget child, VCaption caption) { - VLayoutSlot slot = getSlotForChild(child); - - if (caption != null) { - // Logical attach. - getChildren().add(caption); - } - - // Physical attach if not null, also removes old caption - slot.setCaption(caption); - - if (caption != null) { - // Adopt. - adopt(caption); - } - } - - public int layoutPrimaryDirection(int spacingSize, int allocatedSize, - int startPadding, int endPadding) { - int actuallyAllocated = 0; - double totalExpand = 0; - - int childCount = 0; - for (Widget child : this) { - if (child instanceof VCaption) { - continue; - } - childCount++; - - VLayoutSlot slot = getSlotForChild(child); - totalExpand += slot.getExpandRatio(); - - if (!slot.isRelativeInDirection(isVertical)) { - actuallyAllocated += slot.getUsedSizeInDirection(isVertical); - } - } - - actuallyAllocated += spacingSize * (childCount - 1); - - if (allocatedSize == -1) { - allocatedSize = actuallyAllocated; - } - - double unallocatedSpace = Math - .max(0, allocatedSize - actuallyAllocated); - - double currentLocation = startPadding; - - WidgetCollection children = getChildren(); - for (int i = 0; i < children.size(); i++) { - Widget child = children.get(i); - if (child instanceof VCaption) { - continue; - } - - VLayoutSlot slot = getSlotForChild(child); - - double childExpandRatio; - if (totalExpand == 0) { - childExpandRatio = 1d / childCount; - } else { - childExpandRatio = slot.getExpandRatio() / totalExpand; - } - - double extraPixels = unallocatedSpace * childExpandRatio; - double endLocation = currentLocation + extraPixels; - if (!slot.isRelativeInDirection(isVertical)) { - endLocation += slot.getUsedSizeInDirection(isVertical); - } - - /* - * currentLocation and allocatedSpace are used with full precision - * to avoid missing pixels in the end. The pixel dimensions passed - * to the DOM are still rounded. Otherwise e.g. 10.5px start - * position + 10.5px space might be cause the component to go 1px - * beyond the edge as the effect of the browser's rounding may cause - * something similar to 11px + 11px. - * - * It's most efficient to use doubles all the way because native - * javascript emulates other number types using doubles. - */ - double roundedLocation = Math.round(currentLocation); - - /* - * Space is calculated as the difference between rounded start and - * end locations. Just rounding the space would cause e.g. 10.5px + - * 10.5px = 21px -> 11px + 11px = 22px but in this way we get 11px + - * 10px = 21px. - */ - double roundedSpace = Math.round(endLocation) - roundedLocation; - - // Reserve room for the padding if we're at the end - double slotEndMargin; - if (i == children.size() - 1) { - slotEndMargin = endPadding; - } else { - slotEndMargin = 0; - } - - slot.positionInDirection(roundedLocation, roundedSpace, - slotEndMargin, isVertical); - - currentLocation = endLocation + spacingSize; - } - - return allocatedSize; - } - - public int layoutSecondaryDirection(int allocatedSize, int startPadding, - int endPadding) { - int maxSize = 0; - for (Widget child : this) { - if (child instanceof VCaption) { - continue; - } - - VLayoutSlot slot = getSlotForChild(child); - if (!slot.isRelativeInDirection(!isVertical)) { - maxSize = Math.max(maxSize, - slot.getUsedSizeInDirection(!isVertical)); - } - } - - if (allocatedSize == -1) { - allocatedSize = maxSize; - } - - for (Widget child : this) { - if (child instanceof VCaption) { - continue; - } - - VLayoutSlot slot = getSlotForChild(child); - slot.positionInDirection(startPadding, allocatedSize, endPadding, - !isVertical); - } - - return allocatedSize; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VVerticalLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VVerticalLayout.java deleted file mode 100644 index 5c396882f9..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VVerticalLayout.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.orderedlayout; - -public class VVerticalLayout extends VMeasuringOrderedLayout { - - public static final String CLASSNAME = "v-verticallayout"; - - public VVerticalLayout() { - super(CLASSNAME, true); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VerticalLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VerticalLayoutConnector.java deleted file mode 100644 index 441ba9c156..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VerticalLayoutConnector.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.orderedlayout; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.ui.VerticalLayout; - -@Connect(value = VerticalLayout.class, loadStyle = LoadStyle.EAGER) -public class VerticalLayoutConnector extends AbstractOrderedLayoutConnector { - - @Override - public VVerticalLayout getWidget() { - return (VVerticalLayout) super.getWidget(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java deleted file mode 100644 index c6a695bc2e..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.panel; - -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.panel.PanelServerRpc; -import com.vaadin.shared.ui.panel.PanelState; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; -import com.vaadin.terminal.gwt.client.LayoutManager; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.communication.RpcProxy; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector; -import com.vaadin.terminal.gwt.client.ui.ClickEventHandler; -import com.vaadin.terminal.gwt.client.ui.PostLayoutListener; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler; -import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout; -import com.vaadin.terminal.gwt.client.ui.layout.MayScrollChildren; -import com.vaadin.ui.Panel; - -@Connect(Panel.class) -public class PanelConnector extends AbstractComponentContainerConnector - implements Paintable, SimpleManagedLayout, PostLayoutListener, - MayScrollChildren { - - private Integer uidlScrollTop; - - private ClickEventHandler clickEventHandler = new ClickEventHandler(this) { - - @Override - protected void fireClick(NativeEvent event, - MouseEventDetails mouseDetails) { - rpc.click(mouseDetails); - } - }; - - private Integer uidlScrollLeft; - - private PanelServerRpc rpc; - - @Override - public void init() { - super.init(); - rpc = RpcProxy.create(PanelServerRpc.class, this); - VPanel panel = getWidget(); - LayoutManager layoutManager = getLayoutManager(); - - layoutManager.registerDependency(this, panel.captionNode); - layoutManager.registerDependency(this, panel.bottomDecoration); - layoutManager.registerDependency(this, panel.contentNode); - } - - @Override - public void onUnregister() { - VPanel panel = getWidget(); - LayoutManager layoutManager = getLayoutManager(); - - layoutManager.unregisterDependency(this, panel.captionNode); - layoutManager.unregisterDependency(this, panel.bottomDecoration); - layoutManager.unregisterDependency(this, panel.contentNode); - } - - @Override - public boolean delegateCaptionHandling() { - return false; - } - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (isRealUpdate(uidl)) { - - // Handle caption displaying and style names, prior generics. - // Affects size calculations - - // Restore default stylenames - getWidget().contentNode.setClassName(VPanel.CLASSNAME + "-content"); - getWidget().bottomDecoration.setClassName(VPanel.CLASSNAME - + "-deco"); - getWidget().captionNode.setClassName(VPanel.CLASSNAME + "-caption"); - boolean hasCaption = false; - if (getState().getCaption() != null - && !"".equals(getState().getCaption())) { - getWidget().setCaption(getState().getCaption()); - hasCaption = true; - } else { - getWidget().setCaption(""); - getWidget().captionNode.setClassName(VPanel.CLASSNAME - + "-nocaption"); - } - - // Add proper stylenames for all elements. This way we can prevent - // unwanted CSS selector inheritance. - final String captionBaseClass = VPanel.CLASSNAME - + (hasCaption ? "-caption" : "-nocaption"); - final String contentBaseClass = VPanel.CLASSNAME + "-content"; - final String decoBaseClass = VPanel.CLASSNAME + "-deco"; - String captionClass = captionBaseClass; - String contentClass = contentBaseClass; - String decoClass = decoBaseClass; - if (getState().hasStyles()) { - for (String style : getState().getStyles()) { - captionClass += " " + captionBaseClass + "-" + style; - contentClass += " " + contentBaseClass + "-" + style; - decoClass += " " + decoBaseClass + "-" + style; - } - } - getWidget().captionNode.setClassName(captionClass); - getWidget().contentNode.setClassName(contentClass); - getWidget().bottomDecoration.setClassName(decoClass); - - getWidget().makeScrollable(); - } - - if (!isRealUpdate(uidl)) { - return; - } - - clickEventHandler.handleEventHandlerRegistration(); - - getWidget().client = client; - getWidget().id = uidl.getId(); - - if (getState().getIcon() != null) { - getWidget().setIconUri(getState().getIcon().getURL(), client); - } else { - getWidget().setIconUri(null, client); - } - - getWidget().setErrorIndicatorVisible( - null != getState().getErrorMessage()); - - // We may have actions attached to this panel - if (uidl.getChildCount() > 0) { - final int cnt = uidl.getChildCount(); - for (int i = 0; i < cnt; i++) { - UIDL childUidl = uidl.getChildUIDL(i); - if (childUidl.getTag().equals("actions")) { - if (getWidget().shortcutHandler == null) { - getWidget().shortcutHandler = new ShortcutActionHandler( - getConnectorId(), client); - } - getWidget().shortcutHandler.updateActionMap(childUidl); - } - } - } - - if (getState().getScrollTop() != getWidget().scrollTop) { - // Sizes are not yet up to date, so changing the scroll position - // is deferred to after the layout phase - uidlScrollTop = getState().getScrollTop(); - } - - if (getState().getScrollLeft() != getWidget().scrollLeft) { - // Sizes are not yet up to date, so changing the scroll position - // is deferred to after the layout phase - uidlScrollLeft = getState().getScrollLeft(); - } - - // And apply tab index - getWidget().contentNode.setTabIndex(getState().getTabIndex()); - } - - @Override - public void updateCaption(ComponentConnector component) { - // NOP: layouts caption, errors etc not rendered in Panel - } - - @Override - public VPanel getWidget() { - return (VPanel) super.getWidget(); - } - - @Override - public void layout() { - updateSizes(); - } - - void updateSizes() { - VPanel panel = getWidget(); - - LayoutManager layoutManager = getLayoutManager(); - int top = layoutManager.getOuterHeight(panel.captionNode); - int bottom = layoutManager.getInnerHeight(panel.bottomDecoration); - - Style style = panel.getElement().getStyle(); - panel.captionNode.getParentElement().getStyle() - .setMarginTop(-top, Unit.PX); - panel.bottomDecoration.getStyle().setMarginBottom(-bottom, Unit.PX); - style.setPaddingTop(top, Unit.PX); - style.setPaddingBottom(bottom, Unit.PX); - - // Update scroll positions - panel.contentNode.setScrollTop(panel.scrollTop); - panel.contentNode.setScrollLeft(panel.scrollLeft); - // Read actual value back to ensure update logic is correct - panel.scrollTop = panel.contentNode.getScrollTop(); - panel.scrollLeft = panel.contentNode.getScrollLeft(); - } - - @Override - public void postLayout() { - VPanel panel = getWidget(); - if (uidlScrollTop != null) { - panel.contentNode.setScrollTop(uidlScrollTop.intValue()); - // Read actual value back to ensure update logic is correct - // TODO Does this trigger reflows? - panel.scrollTop = panel.contentNode.getScrollTop(); - uidlScrollTop = null; - } - - if (uidlScrollLeft != null) { - panel.contentNode.setScrollLeft(uidlScrollLeft.intValue()); - // Read actual value back to ensure update logic is correct - // TODO Does this trigger reflows? - panel.scrollLeft = panel.contentNode.getScrollLeft(); - uidlScrollLeft = null; - } - } - - @Override - public PanelState getState() { - return (PanelState) super.getState(); - } - - @Override - public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { - super.onConnectorHierarchyChange(event); - // We always have 1 child, unless the child is hidden - Widget newChildWidget = null; - if (getChildComponents().size() == 1) { - ComponentConnector newChild = getChildComponents().get(0); - newChildWidget = newChild.getWidget(); - } - - getWidget().setWidget(newChildWidget); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java b/client/src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java deleted file mode 100644 index b7a9f3f7c2..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.panel; - -import com.google.gwt.dom.client.DivElement; -import com.google.gwt.dom.client.Document; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.SimplePanel; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Focusable; -import com.vaadin.terminal.gwt.client.ui.Icon; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner; -import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate; -import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate.TouchScrollHandler; - -public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner, - Focusable { - - public static final String CLASSNAME = "v-panel"; - - ApplicationConnection client; - - String id; - - final Element captionNode = DOM.createDiv(); - - private final Element captionText = DOM.createSpan(); - - private Icon icon; - - final Element bottomDecoration = DOM.createDiv(); - - final Element contentNode = DOM.createDiv(); - - private Element errorIndicatorElement; - - ShortcutActionHandler shortcutHandler; - - int scrollTop; - - int scrollLeft; - - private TouchScrollHandler touchScrollHandler; - - public VPanel() { - super(); - DivElement captionWrap = Document.get().createDivElement(); - captionWrap.appendChild(captionNode); - captionNode.appendChild(captionText); - - captionWrap.setClassName(CLASSNAME + "-captionwrap"); - captionNode.setClassName(CLASSNAME + "-caption"); - contentNode.setClassName(CLASSNAME + "-content"); - bottomDecoration.setClassName(CLASSNAME + "-deco"); - - getElement().appendChild(captionWrap); - - /* - * Make contentNode focusable only by using the setFocus() method. This - * behaviour can be changed by invoking setTabIndex() in the serverside - * implementation - */ - contentNode.setTabIndex(-1); - - getElement().appendChild(contentNode); - - getElement().appendChild(bottomDecoration); - setStyleName(CLASSNAME); - DOM.sinkEvents(getElement(), Event.ONKEYDOWN); - DOM.sinkEvents(contentNode, Event.ONSCROLL | Event.TOUCHEVENTS); - - contentNode.getStyle().setProperty("position", "relative"); - getElement().getStyle().setProperty("overflow", "hidden"); - - makeScrollable(); - } - - /** - * Sets the keyboard focus on the Panel - * - * @param focus - * Should the panel have focus or not. - */ - public void setFocus(boolean focus) { - if (focus) { - getContainerElement().focus(); - } else { - getContainerElement().blur(); - } - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.Focusable#focus() - */ - - @Override - public void focus() { - setFocus(true); - - } - - @Override - protected Element getContainerElement() { - return contentNode; - } - - void setCaption(String text) { - DOM.setInnerHTML(captionText, text); - } - - void setErrorIndicatorVisible(boolean showError) { - if (showError) { - if (errorIndicatorElement == null) { - errorIndicatorElement = DOM.createSpan(); - DOM.setElementProperty(errorIndicatorElement, "className", - "v-errorindicator"); - DOM.sinkEvents(errorIndicatorElement, Event.MOUSEEVENTS); - sinkEvents(Event.MOUSEEVENTS); - } - DOM.insertBefore(captionNode, errorIndicatorElement, captionText); - } else if (errorIndicatorElement != null) { - DOM.removeChild(captionNode, errorIndicatorElement); - errorIndicatorElement = null; - } - } - - void setIconUri(String iconUri, ApplicationConnection client) { - if (iconUri == null) { - if (icon != null) { - DOM.removeChild(captionNode, icon.getElement()); - icon = null; - } - } else { - if (icon == null) { - icon = new Icon(client); - DOM.insertChild(captionNode, icon.getElement(), 0); - } - icon.setUri(iconUri); - } - } - - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - - final Element target = DOM.eventGetTarget(event); - final int type = DOM.eventGetType(event); - if (type == Event.ONKEYDOWN && shortcutHandler != null) { - shortcutHandler.handleKeyboardEvent(event); - return; - } - if (type == Event.ONSCROLL) { - int newscrollTop = DOM.getElementPropertyInt(contentNode, - "scrollTop"); - int newscrollLeft = DOM.getElementPropertyInt(contentNode, - "scrollLeft"); - if (client != null - && (newscrollLeft != scrollLeft || newscrollTop != scrollTop)) { - scrollLeft = newscrollLeft; - scrollTop = newscrollTop; - client.updateVariable(id, "scrollTop", scrollTop, false); - client.updateVariable(id, "scrollLeft", scrollLeft, false); - } - } - } - - @Override - public ShortcutActionHandler getShortcutActionHandler() { - return shortcutHandler; - } - - /** - * Ensures the panel is scrollable eg. after style name changes - */ - void makeScrollable() { - if (touchScrollHandler == null) { - touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this); - } - touchScrollHandler.addElement(contentNode); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/passwordfield/PasswordFieldConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/passwordfield/PasswordFieldConnector.java deleted file mode 100644 index e8aa32f78b..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/passwordfield/PasswordFieldConnector.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.passwordfield; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.gwt.client.ui.textfield.TextFieldConnector; -import com.vaadin.ui.PasswordField; - -@Connect(PasswordField.class) -public class PasswordFieldConnector extends TextFieldConnector { - - @Override - public VPasswordField getWidget() { - return (VPasswordField) super.getWidget(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/passwordfield/VPasswordField.java b/client/src/com/vaadin/terminal/gwt/client/ui/passwordfield/VPasswordField.java deleted file mode 100644 index fc131909b2..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/passwordfield/VPasswordField.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.passwordfield; - -import com.google.gwt.user.client.DOM; -import com.vaadin.terminal.gwt.client.ui.textfield.VTextField; - -/** - * This class represents a password field. - * - * @author Vaadin Ltd. - * - */ -public class VPasswordField extends VTextField { - - public VPasswordField() { - super(DOM.createInputPassword()); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/popupview/PopupViewConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/popupview/PopupViewConnector.java deleted file mode 100644 index 398e257375..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/popupview/PopupViewConnector.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.popupview; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.VCaption; -import com.vaadin.terminal.gwt.client.VCaptionWrapper; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector; -import com.vaadin.terminal.gwt.client.ui.PostLayoutListener; -import com.vaadin.ui.PopupView; - -@Connect(PopupView.class) -public class PopupViewConnector extends AbstractComponentContainerConnector - implements Paintable, PostLayoutListener { - - private boolean centerAfterLayout = false; - - @Override - public boolean delegateCaptionHandling() { - return false; - } - - /** - * - * - * @see com.vaadin.terminal.gwt.client.ComponentConnector#updateFromUIDL(com.vaadin.terminal.gwt.client.UIDL, - * com.vaadin.terminal.gwt.client.ApplicationConnection) - */ - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (!isRealUpdate(uidl)) { - return; - } - // These are for future server connections - getWidget().client = client; - getWidget().uidlId = uidl.getId(); - - getWidget().hostPopupVisible = uidl - .getBooleanVariable("popupVisibility"); - - getWidget().setHTML(uidl.getStringAttribute("html")); - - if (uidl.hasAttribute("hideOnMouseOut")) { - getWidget().popup.setHideOnMouseOut(uidl - .getBooleanAttribute("hideOnMouseOut")); - } - - // Render the popup if visible and show it. - if (getWidget().hostPopupVisible) { - UIDL popupUIDL = uidl.getChildUIDL(0); - - // showPopupOnTop(popup, hostReference); - getWidget().preparePopup(getWidget().popup); - getWidget().popup.updateFromUIDL(popupUIDL, client); - if (getState().hasStyles()) { - final StringBuffer styleBuf = new StringBuffer(); - final String primaryName = getWidget().popup - .getStylePrimaryName(); - styleBuf.append(primaryName); - for (String style : getState().getStyles()) { - styleBuf.append(" "); - styleBuf.append(primaryName); - styleBuf.append("-"); - styleBuf.append(style); - } - getWidget().popup.setStyleName(styleBuf.toString()); - } else { - getWidget().popup.setStyleName(getWidget().popup - .getStylePrimaryName()); - } - getWidget().showPopup(getWidget().popup); - centerAfterLayout = true; - - // The popup shouldn't be visible, try to hide it. - } else { - getWidget().popup.hide(); - } - }// updateFromUIDL - - @Override - public void updateCaption(ComponentConnector component) { - if (VCaption.isNeeded(component.getState())) { - if (getWidget().popup.captionWrapper != null) { - getWidget().popup.captionWrapper.updateCaption(); - } else { - getWidget().popup.captionWrapper = new VCaptionWrapper( - component, getConnection()); - getWidget().popup.setWidget(getWidget().popup.captionWrapper); - getWidget().popup.captionWrapper.updateCaption(); - } - } else { - if (getWidget().popup.captionWrapper != null) { - getWidget().popup - .setWidget(getWidget().popup.popupComponentWidget); - } - } - } - - @Override - public VPopupView getWidget() { - return (VPopupView) super.getWidget(); - } - - @Override - public void postLayout() { - if (centerAfterLayout) { - centerAfterLayout = false; - getWidget().center(); - } - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/popupview/VPopupView.java b/client/src/com/vaadin/terminal/gwt/client/ui/popupview/VPopupView.java deleted file mode 100644 index df373c59ba..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/popupview/VPopupView.java +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.popupview; - -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.logical.shared.CloseEvent; -import com.google.gwt.event.logical.shared.CloseHandler; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.Focusable; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.HasWidgets; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.PopupPanel; -import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.VCaptionWrapper; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner; -import com.vaadin.terminal.gwt.client.ui.VOverlay; -import com.vaadin.terminal.gwt.client.ui.richtextarea.VRichTextArea; - -public class VPopupView extends HTML { - - public static final String CLASSNAME = "v-popupview"; - - /** For server-client communication */ - String uidlId; - ApplicationConnection client; - - /** This variable helps to communicate popup visibility to the server */ - boolean hostPopupVisible; - - final CustomPopup popup; - private final Label loading = new Label(); - - /** - * loading constructor - */ - public VPopupView() { - super(); - popup = new CustomPopup(); - - setStyleName(CLASSNAME); - popup.setStyleName(CLASSNAME + "-popup"); - loading.setStyleName(CLASSNAME + "-loading"); - - setHTML(""); - popup.setWidget(loading); - - // When we click to open the popup... - addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - updateState(true); - } - }); - - // ..and when we close it - popup.addCloseHandler(new CloseHandler<PopupPanel>() { - @Override - public void onClose(CloseEvent<PopupPanel> event) { - updateState(false); - } - }); - - popup.setAnimationEnabled(true); - } - - /** - * Update popup visibility to server - * - * @param visibility - */ - private void updateState(boolean visible) { - // If we know the server connection - // then update the current situation - if (uidlId != null && client != null && isAttached()) { - client.updateVariable(uidlId, "popupVisibility", visible, true); - } - } - - void preparePopup(final CustomPopup popup) { - popup.setVisible(false); - popup.show(); - } - - /** - * Determines the correct position for a popup and displays the popup at - * that position. - * - * By default, the popup is shown centered relative to its host component, - * ensuring it is visible on the screen if possible. - * - * Can be overridden to customize the popup position. - * - * @param popup - */ - protected void showPopup(final CustomPopup popup) { - popup.setPopupPosition(0, 0); - - popup.setVisible(true); - } - - void center() { - int windowTop = RootPanel.get().getAbsoluteTop(); - int windowLeft = RootPanel.get().getAbsoluteLeft(); - int windowRight = windowLeft + RootPanel.get().getOffsetWidth(); - int windowBottom = windowTop + RootPanel.get().getOffsetHeight(); - - int offsetWidth = popup.getOffsetWidth(); - int offsetHeight = popup.getOffsetHeight(); - - int hostHorizontalCenter = VPopupView.this.getAbsoluteLeft() - + VPopupView.this.getOffsetWidth() / 2; - int hostVerticalCenter = VPopupView.this.getAbsoluteTop() - + VPopupView.this.getOffsetHeight() / 2; - - int left = hostHorizontalCenter - offsetWidth / 2; - int top = hostVerticalCenter - offsetHeight / 2; - - // Don't show the popup outside the screen. - if ((left + offsetWidth) > windowRight) { - left -= (left + offsetWidth) - windowRight; - } - - if ((top + offsetHeight) > windowBottom) { - top -= (top + offsetHeight) - windowBottom; - } - - if (left < 0) { - left = 0; - } - - if (top < 0) { - top = 0; - } - - popup.setPopupPosition(left, top); - } - - /** - * Make sure that we remove the popup when the main widget is removed. - * - * @see com.google.gwt.user.client.ui.Widget#onUnload() - */ - @Override - protected void onDetach() { - popup.hide(); - super.onDetach(); - } - - private static native void nativeBlur(Element e) - /*-{ - if(e && e.blur) { - e.blur(); - } - }-*/; - - /** - * This class is only protected to enable overriding showPopup, and is - * currently not intended to be extended or otherwise used directly. Its API - * (other than it being a VOverlay) is to be considered private and - * potentially subject to change. - */ - protected class CustomPopup extends VOverlay { - - private ComponentConnector popupComponentPaintable = null; - Widget popupComponentWidget = null; - VCaptionWrapper captionWrapper = null; - - private boolean hasHadMouseOver = false; - private boolean hideOnMouseOut = true; - private final Set<Element> activeChildren = new HashSet<Element>(); - private boolean hiding = false; - - private ShortcutActionHandler shortcutActionHandler; - - public CustomPopup() { - super(true, false, true); // autoHide, not modal, dropshadow - - // Delegate popup keyboard events to the relevant handler. The - // events do not propagate automatically because the popup is - // directly attached to the RootPanel. - addDomHandler(new KeyDownHandler() { - @Override - public void onKeyDown(KeyDownEvent event) { - if (shortcutActionHandler != null) { - shortcutActionHandler.handleKeyboardEvent(Event - .as(event.getNativeEvent())); - } - } - }, KeyDownEvent.getType()); - } - - // For some reason ONMOUSEOUT events are not always received, so we have - // to use ONMOUSEMOVE that doesn't target the popup - @Override - public boolean onEventPreview(Event event) { - Element target = DOM.eventGetTarget(event); - boolean eventTargetsPopup = DOM.isOrHasChild(getElement(), target); - int type = DOM.eventGetType(event); - - // Catch children that use keyboard, so we can unfocus them when - // hiding - if (eventTargetsPopup && type == Event.ONKEYPRESS) { - activeChildren.add(target); - } - - if (eventTargetsPopup && type == Event.ONMOUSEMOVE) { - hasHadMouseOver = true; - } - - if (!eventTargetsPopup && type == Event.ONMOUSEMOVE) { - if (hasHadMouseOver && hideOnMouseOut) { - hide(); - return true; - } - } - - // Was the TAB key released outside of our popup? - if (!eventTargetsPopup && type == Event.ONKEYUP - && event.getKeyCode() == KeyCodes.KEY_TAB) { - // Should we hide on focus out (mouse out)? - if (hideOnMouseOut) { - hide(); - return true; - } - } - - return super.onEventPreview(event); - } - - @Override - public void hide(boolean autoClosed) { - VConsole.log("Hiding popupview"); - hiding = true; - syncChildren(); - if (popupComponentWidget != null && popupComponentWidget != loading) { - remove(popupComponentWidget); - } - hasHadMouseOver = false; - shortcutActionHandler = null; - super.hide(autoClosed); - } - - @Override - public void show() { - hiding = false; - - // Find the shortcut action handler that should handle keyboard - // events from the popup. The events do not propagate automatically - // because the popup is directly attached to the RootPanel. - Widget widget = VPopupView.this; - while (shortcutActionHandler == null && widget != null) { - if (widget instanceof ShortcutActionHandlerOwner) { - shortcutActionHandler = ((ShortcutActionHandlerOwner) widget) - .getShortcutActionHandler(); - } - widget = widget.getParent(); - } - - super.show(); - } - - /** - * Try to sync all known active child widgets to server - */ - public void syncChildren() { - // Notify children with focus - if ((popupComponentWidget instanceof Focusable)) { - ((Focusable) popupComponentWidget).setFocus(false); - } else { - - checkForRTE(popupComponentWidget); - } - - // Notify children that have used the keyboard - for (Element e : activeChildren) { - try { - nativeBlur(e); - } catch (Exception ignored) { - } - } - activeChildren.clear(); - } - - private void checkForRTE(Widget popupComponentWidget2) { - if (popupComponentWidget2 instanceof VRichTextArea) { - ((VRichTextArea) popupComponentWidget2) - .synchronizeContentToServer(); - } else if (popupComponentWidget2 instanceof HasWidgets) { - HasWidgets hw = (HasWidgets) popupComponentWidget2; - Iterator<Widget> iterator = hw.iterator(); - while (iterator.hasNext()) { - checkForRTE(iterator.next()); - } - } - } - - @Override - public boolean remove(Widget w) { - - popupComponentPaintable = null; - popupComponentWidget = null; - captionWrapper = null; - - return super.remove(w); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - ComponentConnector newPopupComponent = client.getPaintable(uidl - .getChildUIDL(0)); - - if (newPopupComponent != popupComponentPaintable) { - Widget newWidget = newPopupComponent.getWidget(); - setWidget(newWidget); - popupComponentWidget = newWidget; - popupComponentPaintable = newPopupComponent; - } - - } - - public void setHideOnMouseOut(boolean hideOnMouseOut) { - this.hideOnMouseOut = hideOnMouseOut; - } - - /* - * - * We need a hack make popup act as a child of VPopupView in Vaadin's - * component tree, but work in default GWT manner when closing or - * opening. - * - * (non-Javadoc) - * - * @see com.google.gwt.user.client.ui.Widget#getParent() - */ - @Override - public Widget getParent() { - if (!isAttached() || hiding) { - return super.getParent(); - } else { - return VPopupView.this; - } - } - - @Override - protected void onDetach() { - super.onDetach(); - hiding = false; - } - - @Override - public Element getContainerElement() { - return super.getContainerElement(); - } - - }// class CustomPopup - -}// class VPopupView diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/progressindicator/ProgressIndicatorConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/progressindicator/ProgressIndicatorConnector.java deleted file mode 100644 index e99a03f01d..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/progressindicator/ProgressIndicatorConnector.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.progressindicator; - -import com.google.gwt.user.client.DOM; -import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.AbstractFieldConnector; -import com.vaadin.ui.ProgressIndicator; - -@Connect(ProgressIndicator.class) -public class ProgressIndicatorConnector extends AbstractFieldConnector - implements Paintable { - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - if (!isRealUpdate(uidl)) { - return; - } - - // Save details - getWidget().client = client; - - getWidget().indeterminate = uidl.getBooleanAttribute("indeterminate"); - - if (getWidget().indeterminate) { - String basename = VProgressIndicator.CLASSNAME + "-indeterminate"; - getWidget().addStyleName(basename); - if (!isEnabled()) { - getWidget().addStyleName(basename + "-disabled"); - } else { - getWidget().removeStyleName(basename + "-disabled"); - } - } else { - try { - final float f = Float.parseFloat(uidl - .getStringAttribute("state")); - final int size = Math.round(100 * f); - DOM.setStyleAttribute(getWidget().indicator, "width", size - + "%"); - } catch (final Exception e) { - } - } - - if (isEnabled()) { - getWidget().interval = uidl.getIntAttribute("pollinginterval"); - getWidget().poller.scheduleRepeating(getWidget().interval); - } - } - - @Override - public VProgressIndicator getWidget() { - return (VProgressIndicator) super.getWidget(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/progressindicator/VProgressIndicator.java b/client/src/com/vaadin/terminal/gwt/client/ui/progressindicator/VProgressIndicator.java deleted file mode 100644 index 5d39389d5b..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/progressindicator/VProgressIndicator.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.progressindicator; - -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Util; - -public class VProgressIndicator extends Widget { - - public static final String CLASSNAME = "v-progressindicator"; - Element wrapper = DOM.createDiv(); - Element indicator = DOM.createDiv(); - protected ApplicationConnection client; - protected final Poller poller; - protected boolean indeterminate = false; - private boolean pollerSuspendedDueDetach; - protected int interval; - - public VProgressIndicator() { - setElement(DOM.createDiv()); - getElement().appendChild(wrapper); - setStyleName(CLASSNAME); - wrapper.appendChild(indicator); - indicator.setClassName(CLASSNAME + "-indicator"); - wrapper.setClassName(CLASSNAME + "-wrapper"); - poller = new Poller(); - } - - @Override - protected void onAttach() { - super.onAttach(); - if (pollerSuspendedDueDetach) { - poller.scheduleRepeating(interval); - } - } - - @Override - protected void onDetach() { - super.onDetach(); - if (interval > 0) { - poller.cancel(); - pollerSuspendedDueDetach = true; - } - } - - @Override - public void setVisible(boolean visible) { - super.setVisible(visible); - if (!visible) { - poller.cancel(); - } - } - - class Poller extends Timer { - - @Override - public void run() { - if (!client.hasActiveRequest() - && Util.isAttachedAndDisplayed(VProgressIndicator.this)) { - client.sendPendingVariableChanges(); - } - } - - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/RichTextAreaConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/RichTextAreaConnector.java deleted file mode 100644 index 9726d43297..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/RichTextAreaConnector.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.richtextarea; - -import com.google.gwt.user.client.Event; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.AbstractFieldConnector; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutActionListener; -import com.vaadin.ui.RichTextArea; - -@Connect(value = RichTextArea.class, loadStyle = LoadStyle.LAZY) -public class RichTextAreaConnector extends AbstractFieldConnector implements - Paintable, BeforeShortcutActionListener { - - @Override - public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) { - getWidget().client = client; - getWidget().id = uidl.getId(); - - if (uidl.hasVariable("text")) { - getWidget().currentValue = uidl.getStringVariable("text"); - if (getWidget().rta.isAttached()) { - getWidget().rta.setHTML(getWidget().currentValue); - } else { - getWidget().html.setHTML(getWidget().currentValue); - } - } - if (isRealUpdate(uidl)) { - getWidget().setEnabled(isEnabled()); - } - - if (!isRealUpdate(uidl)) { - return; - } - - getWidget().setReadOnly(isReadOnly()); - getWidget().immediate = getState().isImmediate(); - int newMaxLength = uidl.hasAttribute("maxLength") ? uidl - .getIntAttribute("maxLength") : -1; - if (newMaxLength >= 0) { - if (getWidget().maxLength == -1) { - getWidget().keyPressHandler = getWidget().rta - .addKeyPressHandler(getWidget()); - } - getWidget().maxLength = newMaxLength; - } else if (getWidget().maxLength != -1) { - getWidget().getElement().setAttribute("maxlength", ""); - getWidget().maxLength = -1; - getWidget().keyPressHandler.removeHandler(); - } - - if (uidl.hasAttribute("selectAll")) { - getWidget().selectAll(); - } - - } - - @Override - public void onBeforeShortcutAction(Event e) { - getWidget().synchronizeContentToServer(); - } - - @Override - public VRichTextArea getWidget() { - return (VRichTextArea) super.getWidget(); - }; - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextArea.java b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextArea.java deleted file mode 100644 index cdd5025e64..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextArea.java +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.richtextarea; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.ChangeEvent; -import com.google.gwt.event.dom.client.ChangeHandler; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.Focusable; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.RichTextArea; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.Field; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner; -import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate; - -/** - * This class implements a basic client side rich text editor component. - * - * @author Vaadin Ltd. - * - */ -public class VRichTextArea extends Composite implements Field, ChangeHandler, - BlurHandler, KeyPressHandler, KeyDownHandler, Focusable { - - /** - * The input node CSS classname. - */ - public static final String CLASSNAME = "v-richtextarea"; - - protected String id; - - protected ApplicationConnection client; - - boolean immediate = false; - - RichTextArea rta; - - private VRichTextToolbar formatter; - - HTML html = new HTML(); - - private final FlowPanel fp = new FlowPanel(); - - private boolean enabled = true; - - private int extraHorizontalPixels = -1; - private int extraVerticalPixels = -1; - - int maxLength = -1; - - private int toolbarNaturalWidth = 500; - - HandlerRegistration keyPressHandler; - - private ShortcutActionHandlerOwner hasShortcutActionHandler; - - String currentValue = ""; - - private boolean readOnly = false; - - public VRichTextArea() { - createRTAComponents(); - fp.add(formatter); - fp.add(rta); - - initWidget(fp); - setStyleName(CLASSNAME); - - TouchScrollDelegate.enableTouchScrolling(html, html.getElement()); - } - - private void createRTAComponents() { - rta = new RichTextArea(); - rta.setWidth("100%"); - rta.addBlurHandler(this); - rta.addKeyDownHandler(this); - formatter = new VRichTextToolbar(rta); - } - - public void setEnabled(boolean enabled) { - if (this.enabled != enabled) { - // rta.setEnabled(enabled); - swapEditableArea(); - this.enabled = enabled; - } - } - - /** - * Swaps html to rta and visa versa. - */ - private void swapEditableArea() { - if (html.isAttached()) { - fp.remove(html); - if (BrowserInfo.get().isWebkit()) { - fp.remove(formatter); - createRTAComponents(); // recreate new RTA to bypass #5379 - fp.add(formatter); - } - rta.setHTML(currentValue); - fp.add(rta); - } else { - html.setHTML(currentValue); - fp.remove(rta); - fp.add(html); - } - } - - void selectAll() { - /* - * There is a timing issue if trying to select all immediately on first - * render. Simple deferred command is not enough. Using Timer with - * moderated timeout. If this appears to fail on many (most likely slow) - * environments, consider increasing the timeout. - * - * FF seems to require the most time to stabilize its RTA. On Vaadin - * tiergarden test machines, 200ms was not enough always (about 50% - * success rate) - 300 ms was 100% successful. This however was not - * enough on a sluggish old non-virtualized XP test machine. A bullet - * proof solution would be nice, GWT 2.1 might however solve these. At - * least setFocus has a workaround for this kind of issue. - */ - new Timer() { - @Override - public void run() { - rta.getFormatter().selectAll(); - } - }.schedule(320); - } - - void setReadOnly(boolean b) { - if (isReadOnly() != b) { - swapEditableArea(); - readOnly = b; - } - // reset visibility in case enabled state changed and the formatter was - // recreated - formatter.setVisible(!readOnly); - } - - private boolean isReadOnly() { - return readOnly; - } - - // TODO is this really used, or does everything go via onBlur() only? - @Override - public void onChange(ChangeEvent event) { - synchronizeContentToServer(); - } - - /** - * Method is public to let popupview force synchronization on close. - */ - public void synchronizeContentToServer() { - if (client != null && id != null) { - final String html = rta.getHTML(); - if (!html.equals(currentValue)) { - client.updateVariable(id, "text", html, immediate); - currentValue = html; - } - } - } - - @Override - public void onBlur(BlurEvent event) { - synchronizeContentToServer(); - // TODO notify possible server side blur/focus listeners - } - - /** - * @return space used by components paddings and borders - */ - private int getExtraHorizontalPixels() { - if (extraHorizontalPixels < 0) { - detectExtraSizes(); - } - return extraHorizontalPixels; - } - - /** - * @return space used by components paddings and borders - */ - private int getExtraVerticalPixels() { - if (extraVerticalPixels < 0) { - detectExtraSizes(); - } - return extraVerticalPixels; - } - - /** - * Detects space used by components paddings and borders. - */ - private void detectExtraSizes() { - Element clone = Util.cloneNode(getElement(), false); - DOM.setElementAttribute(clone, "id", ""); - DOM.setStyleAttribute(clone, "visibility", "hidden"); - DOM.setStyleAttribute(clone, "position", "absolute"); - // due FF3 bug set size to 10px and later subtract it from extra pixels - DOM.setStyleAttribute(clone, "width", "10px"); - DOM.setStyleAttribute(clone, "height", "10px"); - DOM.appendChild(DOM.getParent(getElement()), clone); - extraHorizontalPixels = DOM.getElementPropertyInt(clone, "offsetWidth") - 10; - extraVerticalPixels = DOM.getElementPropertyInt(clone, "offsetHeight") - 10; - - DOM.removeChild(DOM.getParent(getElement()), clone); - } - - @Override - public void setHeight(String height) { - if (height.endsWith("px")) { - int h = Integer.parseInt(height.substring(0, height.length() - 2)); - h -= getExtraVerticalPixels(); - if (h < 0) { - h = 0; - } - - super.setHeight(h + "px"); - } else { - super.setHeight(height); - } - - if (height == null || height.equals("")) { - rta.setHeight(""); - } else { - /* - * The formatter height will be initially calculated wrong so we - * delay the height setting so the DOM has had time to stabilize. - */ - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - int editorHeight = getOffsetHeight() - - getExtraVerticalPixels() - - formatter.getOffsetHeight(); - if (editorHeight < 0) { - editorHeight = 0; - } - rta.setHeight(editorHeight + "px"); - } - }); - } - } - - @Override - public void setWidth(String width) { - if (width.endsWith("px")) { - int w = Integer.parseInt(width.substring(0, width.length() - 2)); - w -= getExtraHorizontalPixels(); - if (w < 0) { - w = 0; - } - - super.setWidth(w + "px"); - } else if (width.equals("")) { - /* - * IE cannot calculate the width of the 100% iframe correctly if - * there is no width specified for the parent. In this case we would - * use the toolbar but IE cannot calculate the width of that one - * correctly either in all cases. So we end up using a default width - * for a RichTextArea with no width definition in all browsers (for - * compatibility). - */ - - super.setWidth(toolbarNaturalWidth + "px"); - } else { - super.setWidth(width); - } - } - - @Override - public void onKeyPress(KeyPressEvent event) { - if (maxLength >= 0) { - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - if (rta.getHTML().length() > maxLength) { - rta.setHTML(rta.getHTML().substring(0, maxLength)); - } - } - }); - } - } - - @Override - public void onKeyDown(KeyDownEvent event) { - // delegate to closest shortcut action handler - // throw event from the iframe forward to the shortcuthandler - ShortcutActionHandler shortcutHandler = getShortcutHandlerOwner() - .getShortcutActionHandler(); - if (shortcutHandler != null) { - shortcutHandler - .handleKeyboardEvent(com.google.gwt.user.client.Event - .as(event.getNativeEvent()), - ConnectorMap.get(client).getConnector(this)); - } - } - - private ShortcutActionHandlerOwner getShortcutHandlerOwner() { - if (hasShortcutActionHandler == null) { - Widget parent = getParent(); - while (parent != null) { - if (parent instanceof ShortcutActionHandlerOwner) { - break; - } - parent = parent.getParent(); - } - hasShortcutActionHandler = (ShortcutActionHandlerOwner) parent; - } - return hasShortcutActionHandler; - } - - @Override - public int getTabIndex() { - return rta.getTabIndex(); - } - - @Override - public void setAccessKey(char key) { - rta.setAccessKey(key); - } - - @Override - public void setFocus(boolean focused) { - /* - * Similar issue as with selectAll. Focusing must happen before possible - * selectall, so keep the timeout here lower. - */ - new Timer() { - - @Override - public void run() { - rta.setFocus(true); - } - }.schedule(300); - } - - @Override - public void setTabIndex(int index) { - rta.setTabIndex(index); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextToolbar$Strings.properties b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextToolbar$Strings.properties deleted file mode 100644 index 363b704584..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextToolbar$Strings.properties +++ /dev/null @@ -1,35 +0,0 @@ -bold = Toggle Bold -createLink = Create Link -hr = Insert Horizontal Rule -indent = Indent Right -insertImage = Insert Image -italic = Toggle Italic -justifyCenter = Center -justifyLeft = Left Justify -justifyRight = Right Justify -ol = Insert Ordered List -outdent = Indent Left -removeFormat = Remove Formatting -removeLink = Remove Link -strikeThrough = Toggle Strikethrough -subscript = Toggle Subscript -superscript = Toggle Superscript -ul = Insert Unordered List -underline = Toggle Underline -color = Color -black = Black -white = White -red = Red -green = Green -yellow = Yellow -blue = Blue -font = Font -normal = Normal -size = Size -xxsmall = XX-Small -xsmall = X-Small -small = Small -medium = Medium -large = Large -xlarge = X-Large -xxlarge = XX-Large
\ No newline at end of file diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextToolbar.java b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextToolbar.java deleted file mode 100644 index 3128b4d842..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextToolbar.java +++ /dev/null @@ -1,476 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -/* - * Copyright 2007 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.richtextarea; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.event.dom.client.ChangeEvent; -import com.google.gwt.event.dom.client.ChangeHandler; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.KeyUpEvent; -import com.google.gwt.event.dom.client.KeyUpHandler; -import com.google.gwt.i18n.client.Constants; -import com.google.gwt.resources.client.ClientBundle; -import com.google.gwt.resources.client.ImageResource; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.Image; -import com.google.gwt.user.client.ui.ListBox; -import com.google.gwt.user.client.ui.PushButton; -import com.google.gwt.user.client.ui.RichTextArea; -import com.google.gwt.user.client.ui.ToggleButton; - -/** - * A modified version of sample toolbar for use with {@link RichTextArea}. It - * provides a simple UI for all rich text formatting, dynamically displayed only - * for the available functionality. - */ -public class VRichTextToolbar extends Composite { - - /** - * This {@link ClientBundle} is used for all the button icons. Using a - * bundle allows all of these images to be packed into a single image, which - * saves a lot of HTTP requests, drastically improving startup time. - */ - public interface Images extends ClientBundle { - - ImageResource bold(); - - ImageResource createLink(); - - ImageResource hr(); - - ImageResource indent(); - - ImageResource insertImage(); - - ImageResource italic(); - - ImageResource justifyCenter(); - - ImageResource justifyLeft(); - - ImageResource justifyRight(); - - ImageResource ol(); - - ImageResource outdent(); - - ImageResource removeFormat(); - - ImageResource removeLink(); - - ImageResource strikeThrough(); - - ImageResource subscript(); - - ImageResource superscript(); - - ImageResource ul(); - - ImageResource underline(); - } - - /** - * This {@link Constants} interface is used to make the toolbar's strings - * internationalizable. - */ - public interface Strings extends Constants { - - String black(); - - String blue(); - - String bold(); - - String color(); - - String createLink(); - - String font(); - - String green(); - - String hr(); - - String indent(); - - String insertImage(); - - String italic(); - - String justifyCenter(); - - String justifyLeft(); - - String justifyRight(); - - String large(); - - String medium(); - - String normal(); - - String ol(); - - String outdent(); - - String red(); - - String removeFormat(); - - String removeLink(); - - String size(); - - String small(); - - String strikeThrough(); - - String subscript(); - - String superscript(); - - String ul(); - - String underline(); - - String white(); - - String xlarge(); - - String xsmall(); - - String xxlarge(); - - String xxsmall(); - - String yellow(); - } - - /** - * We use an inner EventHandler class to avoid exposing event methods on the - * RichTextToolbar itself. - */ - private class EventHandler implements ClickHandler, ChangeHandler, - KeyUpHandler { - - @Override - @SuppressWarnings("deprecation") - public void onChange(ChangeEvent event) { - Object sender = event.getSource(); - if (sender == backColors) { - basic.setBackColor(backColors.getValue(backColors - .getSelectedIndex())); - backColors.setSelectedIndex(0); - } else if (sender == foreColors) { - basic.setForeColor(foreColors.getValue(foreColors - .getSelectedIndex())); - foreColors.setSelectedIndex(0); - } else if (sender == fonts) { - basic.setFontName(fonts.getValue(fonts.getSelectedIndex())); - fonts.setSelectedIndex(0); - } else if (sender == fontSizes) { - basic.setFontSize(fontSizesConstants[fontSizes - .getSelectedIndex() - 1]); - fontSizes.setSelectedIndex(0); - } - } - - @Override - @SuppressWarnings("deprecation") - public void onClick(ClickEvent event) { - Object sender = event.getSource(); - if (sender == bold) { - basic.toggleBold(); - } else if (sender == italic) { - basic.toggleItalic(); - } else if (sender == underline) { - basic.toggleUnderline(); - } else if (sender == subscript) { - basic.toggleSubscript(); - } else if (sender == superscript) { - basic.toggleSuperscript(); - } else if (sender == strikethrough) { - extended.toggleStrikethrough(); - } else if (sender == indent) { - extended.rightIndent(); - } else if (sender == outdent) { - extended.leftIndent(); - } else if (sender == justifyLeft) { - basic.setJustification(RichTextArea.Justification.LEFT); - } else if (sender == justifyCenter) { - basic.setJustification(RichTextArea.Justification.CENTER); - } else if (sender == justifyRight) { - basic.setJustification(RichTextArea.Justification.RIGHT); - } else if (sender == insertImage) { - final String url = Window.prompt("Enter an image URL:", - "http://"); - if (url != null) { - extended.insertImage(url); - } - } else if (sender == createLink) { - final String url = Window - .prompt("Enter a link URL:", "http://"); - if (url != null) { - extended.createLink(url); - } - } else if (sender == removeLink) { - extended.removeLink(); - } else if (sender == hr) { - extended.insertHorizontalRule(); - } else if (sender == ol) { - extended.insertOrderedList(); - } else if (sender == ul) { - extended.insertUnorderedList(); - } else if (sender == removeFormat) { - extended.removeFormat(); - } else if (sender == richText) { - // We use the RichTextArea's onKeyUp event to update the toolbar - // status. This will catch any cases where the user moves the - // cursur using the keyboard, or uses one of the browser's - // built-in keyboard shortcuts. - updateStatus(); - } - } - - @Override - public void onKeyUp(KeyUpEvent event) { - if (event.getSource() == richText) { - // We use the RichTextArea's onKeyUp event to update the toolbar - // status. This will catch any cases where the user moves the - // cursor using the keyboard, or uses one of the browser's - // built-in keyboard shortcuts. - updateStatus(); - } - } - } - - private static final RichTextArea.FontSize[] fontSizesConstants = new RichTextArea.FontSize[] { - RichTextArea.FontSize.XX_SMALL, RichTextArea.FontSize.X_SMALL, - RichTextArea.FontSize.SMALL, RichTextArea.FontSize.MEDIUM, - RichTextArea.FontSize.LARGE, RichTextArea.FontSize.X_LARGE, - RichTextArea.FontSize.XX_LARGE }; - - private final Images images = (Images) GWT.create(Images.class); - private final Strings strings = (Strings) GWT.create(Strings.class); - private final EventHandler handler = new EventHandler(); - - private final RichTextArea richText; - @SuppressWarnings("deprecation") - private final RichTextArea.BasicFormatter basic; - @SuppressWarnings("deprecation") - private final RichTextArea.ExtendedFormatter extended; - - private final FlowPanel outer = new FlowPanel(); - private final FlowPanel topPanel = new FlowPanel(); - private final FlowPanel bottomPanel = new FlowPanel(); - private ToggleButton bold; - private ToggleButton italic; - private ToggleButton underline; - private ToggleButton subscript; - private ToggleButton superscript; - private ToggleButton strikethrough; - private PushButton indent; - private PushButton outdent; - private PushButton justifyLeft; - private PushButton justifyCenter; - private PushButton justifyRight; - private PushButton hr; - private PushButton ol; - private PushButton ul; - private PushButton insertImage; - private PushButton createLink; - private PushButton removeLink; - private PushButton removeFormat; - - private ListBox backColors; - private ListBox foreColors; - private ListBox fonts; - private ListBox fontSizes; - - /** - * Creates a new toolbar that drives the given rich text area. - * - * @param richText - * the rich text area to be controlled - */ - @SuppressWarnings("deprecation") - public VRichTextToolbar(RichTextArea richText) { - this.richText = richText; - basic = richText.getBasicFormatter(); - extended = richText.getExtendedFormatter(); - - outer.add(topPanel); - outer.add(bottomPanel); - topPanel.setStyleName("gwt-RichTextToolbar-top"); - bottomPanel.setStyleName("gwt-RichTextToolbar-bottom"); - - initWidget(outer); - setStyleName("gwt-RichTextToolbar"); - - if (basic != null) { - topPanel.add(bold = createToggleButton(images.bold(), - strings.bold())); - topPanel.add(italic = createToggleButton(images.italic(), - strings.italic())); - topPanel.add(underline = createToggleButton(images.underline(), - strings.underline())); - topPanel.add(subscript = createToggleButton(images.subscript(), - strings.subscript())); - topPanel.add(superscript = createToggleButton(images.superscript(), - strings.superscript())); - topPanel.add(justifyLeft = createPushButton(images.justifyLeft(), - strings.justifyLeft())); - topPanel.add(justifyCenter = createPushButton( - images.justifyCenter(), strings.justifyCenter())); - topPanel.add(justifyRight = createPushButton(images.justifyRight(), - strings.justifyRight())); - } - - if (extended != null) { - topPanel.add(strikethrough = createToggleButton( - images.strikeThrough(), strings.strikeThrough())); - topPanel.add(indent = createPushButton(images.indent(), - strings.indent())); - topPanel.add(outdent = createPushButton(images.outdent(), - strings.outdent())); - topPanel.add(hr = createPushButton(images.hr(), strings.hr())); - topPanel.add(ol = createPushButton(images.ol(), strings.ol())); - topPanel.add(ul = createPushButton(images.ul(), strings.ul())); - topPanel.add(insertImage = createPushButton(images.insertImage(), - strings.insertImage())); - topPanel.add(createLink = createPushButton(images.createLink(), - strings.createLink())); - topPanel.add(removeLink = createPushButton(images.removeLink(), - strings.removeLink())); - topPanel.add(removeFormat = createPushButton(images.removeFormat(), - strings.removeFormat())); - } - - if (basic != null) { - bottomPanel.add(backColors = createColorList("Background")); - bottomPanel.add(foreColors = createColorList("Foreground")); - bottomPanel.add(fonts = createFontList()); - bottomPanel.add(fontSizes = createFontSizes()); - - // We only use these handlers for updating status, so don't hook - // them up unless at least basic editing is supported. - richText.addKeyUpHandler(handler); - richText.addClickHandler(handler); - } - } - - private ListBox createColorList(String caption) { - final ListBox lb = new ListBox(); - lb.addChangeHandler(handler); - lb.setVisibleItemCount(1); - - lb.addItem(caption); - lb.addItem(strings.white(), "white"); - lb.addItem(strings.black(), "black"); - lb.addItem(strings.red(), "red"); - lb.addItem(strings.green(), "green"); - lb.addItem(strings.yellow(), "yellow"); - lb.addItem(strings.blue(), "blue"); - lb.setTabIndex(-1); - return lb; - } - - private ListBox createFontList() { - final ListBox lb = new ListBox(); - lb.addChangeHandler(handler); - lb.setVisibleItemCount(1); - - lb.addItem(strings.font(), ""); - lb.addItem(strings.normal(), "inherit"); - lb.addItem("Times New Roman", "Times New Roman"); - lb.addItem("Arial", "Arial"); - lb.addItem("Courier New", "Courier New"); - lb.addItem("Georgia", "Georgia"); - lb.addItem("Trebuchet", "Trebuchet"); - lb.addItem("Verdana", "Verdana"); - lb.setTabIndex(-1); - return lb; - } - - private ListBox createFontSizes() { - final ListBox lb = new ListBox(); - lb.addChangeHandler(handler); - lb.setVisibleItemCount(1); - - lb.addItem(strings.size()); - lb.addItem(strings.xxsmall()); - lb.addItem(strings.xsmall()); - lb.addItem(strings.small()); - lb.addItem(strings.medium()); - lb.addItem(strings.large()); - lb.addItem(strings.xlarge()); - lb.addItem(strings.xxlarge()); - lb.setTabIndex(-1); - return lb; - } - - private PushButton createPushButton(ImageResource img, String tip) { - final PushButton pb = new PushButton(new Image(img)); - pb.addClickHandler(handler); - pb.setTitle(tip); - pb.setTabIndex(-1); - return pb; - } - - private ToggleButton createToggleButton(ImageResource img, String tip) { - final ToggleButton tb = new ToggleButton(new Image(img)); - tb.addClickHandler(handler); - tb.setTitle(tip); - tb.setTabIndex(-1); - return tb; - } - - /** - * Updates the status of all the stateful buttons. - */ - @SuppressWarnings("deprecation") - private void updateStatus() { - if (basic != null) { - bold.setDown(basic.isBold()); - italic.setDown(basic.isItalic()); - underline.setDown(basic.isUnderlined()); - subscript.setDown(basic.isSubscript()); - superscript.setDown(basic.isSuperscript()); - } - - if (extended != null) { - strikethrough.setDown(extended.isStrikethrough()); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/backColors.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/backColors.gif Binary files differdeleted file mode 100644 index ddfc1cea2c..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/backColors.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/bold.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/bold.gif Binary files differdeleted file mode 100644 index 7c22eaac68..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/bold.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/createLink.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/createLink.gif Binary files differdeleted file mode 100644 index 1a1412fe0e..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/createLink.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/fontSizes.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/fontSizes.gif Binary files differdeleted file mode 100644 index c2f4c8cb21..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/fontSizes.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/fonts.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/fonts.gif Binary files differdeleted file mode 100644 index 1629cabb78..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/fonts.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/foreColors.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/foreColors.gif Binary files differdeleted file mode 100644 index 2bb89ef189..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/foreColors.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/gwtLogo.png b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/gwtLogo.png Binary files differdeleted file mode 100644 index 80728186d8..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/gwtLogo.png +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/hr.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/hr.gif Binary files differdeleted file mode 100644 index d507082cf1..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/hr.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/indent.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/indent.gif Binary files differdeleted file mode 100644 index 905421ed76..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/indent.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/insertImage.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/insertImage.gif Binary files differdeleted file mode 100644 index 394ec432a5..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/insertImage.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/italic.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/italic.gif Binary files differdeleted file mode 100644 index ffe0e97284..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/italic.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/justifyCenter.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/justifyCenter.gif Binary files differdeleted file mode 100644 index f7d4c4693d..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/justifyCenter.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/justifyLeft.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/justifyLeft.gif Binary files differdeleted file mode 100644 index bc37a3ed5a..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/justifyLeft.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/justifyRight.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/justifyRight.gif Binary files differdeleted file mode 100644 index 892d569384..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/justifyRight.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/ol.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/ol.gif Binary files differdeleted file mode 100644 index 54f8e4f551..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/ol.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/outdent.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/outdent.gif Binary files differdeleted file mode 100644 index 78fd1b5722..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/outdent.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/removeFormat.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/removeFormat.gif Binary files differdeleted file mode 100644 index cf92c9774f..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/removeFormat.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/removeLink.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/removeLink.gif Binary files differdeleted file mode 100644 index 40721a7bca..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/removeLink.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/strikeThrough.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/strikeThrough.gif Binary files differdeleted file mode 100644 index a7a233c023..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/strikeThrough.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/subscript.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/subscript.gif Binary files differdeleted file mode 100644 index 58b6fbb816..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/subscript.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/superscript.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/superscript.gif Binary files differdeleted file mode 100644 index a6270f6e21..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/superscript.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/ul.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/ul.gif Binary files differdeleted file mode 100644 index 83f1562bcb..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/ul.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/underline.gif b/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/underline.gif Binary files differdeleted file mode 100644 index 06f0200fdd..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/richtextarea/underline.gif +++ /dev/null diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/slider/SliderConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/slider/SliderConnector.java deleted file mode 100644 index 53f3b8874b..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/slider/SliderConnector.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.slider; - -import com.google.gwt.event.logical.shared.ValueChangeEvent; -import com.google.gwt.event.logical.shared.ValueChangeHandler; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.slider.SliderServerRpc; -import com.vaadin.shared.ui.slider.SliderState; -import com.vaadin.terminal.gwt.client.communication.RpcProxy; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.AbstractFieldConnector; -import com.vaadin.ui.Slider; - -@Connect(Slider.class) -public class SliderConnector extends AbstractFieldConnector implements - ValueChangeHandler<Double> { - - protected SliderServerRpc rpc = RpcProxy - .create(SliderServerRpc.class, this); - - @Override - public void init() { - super.init(); - getWidget().setConnection(getConnection()); - getWidget().addValueChangeHandler(this); - } - - @Override - public VSlider getWidget() { - return (VSlider) super.getWidget(); - } - - @Override - public SliderState getState() { - return (SliderState) super.getState(); - } - - @Override - public void onValueChange(ValueChangeEvent<Double> event) { - rpc.valueChanged(event.getValue()); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - getWidget().setId(getConnectorId()); - getWidget().setImmediate(getState().isImmediate()); - getWidget().setDisabled(!isEnabled()); - getWidget().setReadOnly(isReadOnly()); - getWidget().setOrientation(getState().getOrientation()); - getWidget().setMinValue(getState().getMinValue()); - getWidget().setMaxValue(getState().getMaxValue()); - getWidget().setResolution(getState().getResolution()); - getWidget().setValue(getState().getValue(), false); - getWidget().setFeedbackValue(getState().getValue()); - - getWidget().buildBase(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java b/client/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java deleted file mode 100644 index d9801626b4..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java +++ /dev/null @@ -1,627 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -// -package com.vaadin.terminal.gwt.client.ui.slider; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.logical.shared.ValueChangeEvent; -import com.google.gwt.event.logical.shared.ValueChangeHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.HasValue; -import com.vaadin.shared.ui.slider.SliderOrientation; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ContainerResizedListener; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.ui.Field; -import com.vaadin.terminal.gwt.client.ui.SimpleFocusablePanel; -import com.vaadin.terminal.gwt.client.ui.VLazyExecutor; -import com.vaadin.terminal.gwt.client.ui.VOverlay; - -public class VSlider extends SimpleFocusablePanel implements Field, - ContainerResizedListener, HasValue<Double> { - - public static final String CLASSNAME = "v-slider"; - - /** - * Minimum size (width or height, depending on orientation) of the slider - * base. - */ - private static final int MIN_SIZE = 50; - - protected ApplicationConnection client; - - protected String id; - - protected boolean immediate; - protected boolean disabled; - protected boolean readonly; - - private int acceleration = 1; - protected double min; - protected double max; - protected int resolution; - protected Double value; - protected SliderOrientation orientation = SliderOrientation.HORIZONTAL; - - private boolean valueChangeHandlerInitialized = false; - - private final HTML feedback = new HTML("", false); - private final VOverlay feedbackPopup = new VOverlay(true, false, true) { - - @Override - public void show() { - super.show(); - updateFeedbackPosition(); - } - }; - - /* DOM element for slider's base */ - private final Element base; - private final int BASE_BORDER_WIDTH = 1; - - /* DOM element for slider's handle */ - private final Element handle; - - /* DOM element for decrement arrow */ - private final Element smaller; - - /* DOM element for increment arrow */ - private final Element bigger; - - /* Temporary dragging/animation variables */ - private boolean dragging = false; - - private VLazyExecutor delayedValueUpdater = new VLazyExecutor(100, - new ScheduledCommand() { - - @Override - public void execute() { - fireValueChanged(); - acceleration = 1; - } - }); - - public VSlider() { - super(); - - base = DOM.createDiv(); - handle = DOM.createDiv(); - smaller = DOM.createDiv(); - bigger = DOM.createDiv(); - - setStyleName(CLASSNAME); - DOM.setElementProperty(base, "className", CLASSNAME + "-base"); - DOM.setElementProperty(handle, "className", CLASSNAME + "-handle"); - DOM.setElementProperty(smaller, "className", CLASSNAME + "-smaller"); - DOM.setElementProperty(bigger, "className", CLASSNAME + "-bigger"); - - DOM.appendChild(getElement(), bigger); - DOM.appendChild(getElement(), smaller); - DOM.appendChild(getElement(), base); - DOM.appendChild(base, handle); - - // Hide initially - DOM.setStyleAttribute(smaller, "display", "none"); - DOM.setStyleAttribute(bigger, "display", "none"); - DOM.setStyleAttribute(handle, "visibility", "hidden"); - - sinkEvents(Event.MOUSEEVENTS | Event.ONMOUSEWHEEL | Event.KEYEVENTS - | Event.FOCUSEVENTS | Event.TOUCHEVENTS); - - feedbackPopup.addStyleName(CLASSNAME + "-feedback"); - feedbackPopup.setWidget(feedback); - } - - void setFeedbackValue(double value) { - String currentValue = "" + value; - if (resolution == 0) { - currentValue = "" + new Double(value).intValue(); - } - feedback.setText(currentValue); - } - - private void updateFeedbackPosition() { - if (isVertical()) { - feedbackPopup.setPopupPosition( - DOM.getAbsoluteLeft(handle) + handle.getOffsetWidth(), - DOM.getAbsoluteTop(handle) + handle.getOffsetHeight() / 2 - - feedbackPopup.getOffsetHeight() / 2); - } else { - feedbackPopup.setPopupPosition( - DOM.getAbsoluteLeft(handle) + handle.getOffsetWidth() / 2 - - feedbackPopup.getOffsetWidth() / 2, - DOM.getAbsoluteTop(handle) - - feedbackPopup.getOffsetHeight()); - } - } - - void buildBase() { - final String styleAttribute = isVertical() ? "height" : "width"; - final String oppositeStyleAttribute = isVertical() ? "width" : "height"; - final String domProperty = isVertical() ? "offsetHeight" - : "offsetWidth"; - - // clear unnecessary opposite style attribute - DOM.setStyleAttribute(base, oppositeStyleAttribute, ""); - - final Element p = DOM.getParent(getElement()); - if (DOM.getElementPropertyInt(p, domProperty) > 50) { - if (isVertical()) { - setHeight(); - } else { - DOM.setStyleAttribute(base, styleAttribute, ""); - } - } else { - // Set minimum size and adjust after all components have - // (supposedly) been drawn completely. - DOM.setStyleAttribute(base, styleAttribute, MIN_SIZE + "px"); - Scheduler.get().scheduleDeferred(new Command() { - - @Override - public void execute() { - final Element p = DOM.getParent(getElement()); - if (DOM.getElementPropertyInt(p, domProperty) > (MIN_SIZE + 5)) { - if (isVertical()) { - setHeight(); - } else { - DOM.setStyleAttribute(base, styleAttribute, ""); - } - // Ensure correct position - setValue(value, false); - } - } - }); - } - - if (!isVertical()) { - // Draw handle with a delay to allow base to gain maximum width - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - buildHandle(); - setValue(value, false); - } - }); - } else { - buildHandle(); - setValue(value, false); - } - - // TODO attach listeners for focusing and arrow keys - } - - void buildHandle() { - final String handleAttribute = isVertical() ? "marginTop" - : "marginLeft"; - final String oppositeHandleAttribute = isVertical() ? "marginLeft" - : "marginTop"; - - DOM.setStyleAttribute(handle, handleAttribute, "0"); - - // clear unnecessary opposite handle attribute - DOM.setStyleAttribute(handle, oppositeHandleAttribute, ""); - - // Restore visibility - DOM.setStyleAttribute(handle, "visibility", "visible"); - - } - - @Override - public void onBrowserEvent(Event event) { - if (disabled || readonly) { - return; - } - final Element targ = DOM.eventGetTarget(event); - - if (DOM.eventGetType(event) == Event.ONMOUSEWHEEL) { - processMouseWheelEvent(event); - } else if (dragging || targ == handle) { - processHandleEvent(event); - } else if (targ == smaller) { - decreaseValue(true); - } else if (targ == bigger) { - increaseValue(true); - } else if (DOM.eventGetType(event) == Event.MOUSEEVENTS) { - processBaseEvent(event); - } else if ((BrowserInfo.get().isGecko() && DOM.eventGetType(event) == Event.ONKEYPRESS) - || (!BrowserInfo.get().isGecko() && DOM.eventGetType(event) == Event.ONKEYDOWN)) { - - if (handleNavigation(event.getKeyCode(), event.getCtrlKey(), - event.getShiftKey())) { - - feedbackPopup.show(); - - delayedValueUpdater.trigger(); - - DOM.eventPreventDefault(event); - DOM.eventCancelBubble(event, true); - } - } else if (targ.equals(getElement()) - && DOM.eventGetType(event) == Event.ONFOCUS) { - feedbackPopup.show(); - } else if (targ.equals(getElement()) - && DOM.eventGetType(event) == Event.ONBLUR) { - feedbackPopup.hide(); - } else if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) { - feedbackPopup.show(); - } - if (Util.isTouchEvent(event)) { - event.preventDefault(); // avoid simulated events - event.stopPropagation(); - } - } - - private void processMouseWheelEvent(final Event event) { - final int dir = DOM.eventGetMouseWheelVelocityY(event); - - if (dir < 0) { - increaseValue(false); - } else { - decreaseValue(false); - } - - delayedValueUpdater.trigger(); - - DOM.eventPreventDefault(event); - DOM.eventCancelBubble(event, true); - } - - private void processHandleEvent(Event event) { - switch (DOM.eventGetType(event)) { - case Event.ONMOUSEDOWN: - case Event.ONTOUCHSTART: - if (!disabled && !readonly) { - focus(); - feedbackPopup.show(); - dragging = true; - DOM.setElementProperty(handle, "className", CLASSNAME - + "-handle " + CLASSNAME + "-handle-active"); - DOM.setCapture(getElement()); - DOM.eventPreventDefault(event); // prevent selecting text - DOM.eventCancelBubble(event, true); - event.stopPropagation(); - VConsole.log("Slider move start"); - } - break; - case Event.ONMOUSEMOVE: - case Event.ONTOUCHMOVE: - if (dragging) { - VConsole.log("Slider move"); - setValueByEvent(event, false); - updateFeedbackPosition(); - event.stopPropagation(); - } - break; - case Event.ONTOUCHEND: - feedbackPopup.hide(); - case Event.ONMOUSEUP: - // feedbackPopup.hide(); - VConsole.log("Slider move end"); - dragging = false; - DOM.setElementProperty(handle, "className", CLASSNAME + "-handle"); - DOM.releaseCapture(getElement()); - setValueByEvent(event, true); - event.stopPropagation(); - break; - default: - break; - } - } - - private void processBaseEvent(Event event) { - if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) { - if (!disabled && !readonly && !dragging) { - setValueByEvent(event, true); - DOM.eventCancelBubble(event, true); - } - } - } - - private void decreaseValue(boolean updateToServer) { - setValue(new Double(value.doubleValue() - Math.pow(10, -resolution)), - updateToServer); - } - - private void increaseValue(boolean updateToServer) { - setValue(new Double(value.doubleValue() + Math.pow(10, -resolution)), - updateToServer); - } - - private void setValueByEvent(Event event, boolean updateToServer) { - double v = min; // Fallback to min - - final int coord = getEventPosition(event); - - final int handleSize, baseSize, baseOffset; - if (isVertical()) { - handleSize = handle.getOffsetHeight(); - baseSize = base.getOffsetHeight(); - baseOffset = base.getAbsoluteTop() - Window.getScrollTop() - - handleSize / 2; - } else { - handleSize = handle.getOffsetWidth(); - baseSize = base.getOffsetWidth(); - baseOffset = base.getAbsoluteLeft() - Window.getScrollLeft() - + handleSize / 2; - } - - if (isVertical()) { - v = ((baseSize - (coord - baseOffset)) / (double) (baseSize - handleSize)) - * (max - min) + min; - } else { - v = ((coord - baseOffset) / (double) (baseSize - handleSize)) - * (max - min) + min; - } - - if (v < min) { - v = min; - } else if (v > max) { - v = max; - } - - setValue(v, updateToServer); - } - - /** - * TODO consider extracting touches support to an impl class specific for - * webkit (only browser that really supports touches). - * - * @param event - * @return - */ - protected int getEventPosition(Event event) { - if (isVertical()) { - return Util.getTouchOrMouseClientY(event); - } else { - return Util.getTouchOrMouseClientX(event); - } - } - - @Override - public void iLayout() { - if (isVertical()) { - setHeight(); - } - // Update handle position - setValue(value, false); - } - - private void setHeight() { - // Calculate decoration size - DOM.setStyleAttribute(base, "height", "0"); - DOM.setStyleAttribute(base, "overflow", "hidden"); - int h = DOM.getElementPropertyInt(getElement(), "offsetHeight"); - if (h < MIN_SIZE) { - h = MIN_SIZE; - } - DOM.setStyleAttribute(base, "height", h + "px"); - DOM.setStyleAttribute(base, "overflow", ""); - } - - private void fireValueChanged() { - ValueChangeEvent.fire(VSlider.this, value); - } - - /** - * Handles the keyboard events handled by the Slider - * - * @param event - * The keyboard event received - * @return true iff the navigation event was handled - */ - public boolean handleNavigation(int keycode, boolean ctrl, boolean shift) { - - // No support for ctrl moving - if (ctrl) { - return false; - } - - if ((keycode == getNavigationUpKey() && isVertical()) - || (keycode == getNavigationRightKey() && !isVertical())) { - if (shift) { - for (int a = 0; a < acceleration; a++) { - increaseValue(false); - } - acceleration++; - } else { - increaseValue(false); - } - return true; - } else if (keycode == getNavigationDownKey() && isVertical() - || (keycode == getNavigationLeftKey() && !isVertical())) { - if (shift) { - for (int a = 0; a < acceleration; a++) { - decreaseValue(false); - } - acceleration++; - } else { - decreaseValue(false); - } - return true; - } - - return false; - } - - /** - * Get the key that increases the vertical slider. By default it is the up - * arrow key but by overriding this you can change the key to whatever you - * want. - * - * @return The keycode of the key - */ - protected int getNavigationUpKey() { - return KeyCodes.KEY_UP; - } - - /** - * Get the key that decreases the vertical slider. By default it is the down - * arrow key but by overriding this you can change the key to whatever you - * want. - * - * @return The keycode of the key - */ - protected int getNavigationDownKey() { - return KeyCodes.KEY_DOWN; - } - - /** - * Get the key that decreases the horizontal slider. By default it is the - * left arrow key but by overriding this you can change the key to whatever - * you want. - * - * @return The keycode of the key - */ - protected int getNavigationLeftKey() { - return KeyCodes.KEY_LEFT; - } - - /** - * Get the key that increases the horizontal slider. By default it is the - * right arrow key but by overriding this you can change the key to whatever - * you want. - * - * @return The keycode of the key - */ - protected int getNavigationRightKey() { - return KeyCodes.KEY_RIGHT; - } - - public void setConnection(ApplicationConnection client) { - this.client = client; - } - - public void setId(String id) { - this.id = id; - } - - public void setImmediate(boolean immediate) { - this.immediate = immediate; - } - - public void setDisabled(boolean disabled) { - this.disabled = disabled; - } - - public void setReadOnly(boolean readonly) { - this.readonly = readonly; - } - - private boolean isVertical() { - return orientation == SliderOrientation.VERTICAL; - } - - public void setOrientation(SliderOrientation orientation) { - if (this.orientation != orientation) { - this.orientation = orientation; - - if (isVertical()) { - addStyleName(VSlider.CLASSNAME + "-vertical"); - } else { - removeStyleName(VSlider.CLASSNAME + "-vertical"); - } - } - } - - public void setMinValue(double value) { - min = value; - } - - public void setMaxValue(double value) { - max = value; - } - - public void setResolution(int resolution) { - this.resolution = resolution; - } - - public HandlerRegistration addValueChangeHandler( - ValueChangeHandler<Double> handler) { - return addHandler(handler, ValueChangeEvent.getType()); - } - - public Double getValue() { - return value; - } - - public void setValue(Double value) { - if (value < min) { - value = min; - } else if (value > max) { - value = max; - } - - // Update handle position - final String styleAttribute = isVertical() ? "marginTop" : "marginLeft"; - final String domProperty = isVertical() ? "offsetHeight" - : "offsetWidth"; - final int handleSize = Integer.parseInt(DOM.getElementProperty(handle, - domProperty)); - final int baseSize = Integer.parseInt(DOM.getElementProperty(base, - domProperty)) - (2 * BASE_BORDER_WIDTH); - - final int range = baseSize - handleSize; - double v = value.doubleValue(); - - // Round value to resolution - if (resolution > 0) { - v = Math.round(v * Math.pow(10, resolution)); - v = v / Math.pow(10, resolution); - } else { - v = Math.round(v); - } - final double valueRange = max - min; - double p = 0; - if (valueRange > 0) { - p = range * ((v - min) / valueRange); - } - if (p < 0) { - p = 0; - } - if (isVertical()) { - p = range - p; - } - final double pos = p; - - DOM.setStyleAttribute(handle, styleAttribute, (Math.round(pos)) + "px"); - - // Update value - this.value = new Double(v); - setFeedbackValue(v); - } - - public void setValue(Double value, boolean fireEvents) { - if (value == null) { - return; - } - - setValue(value); - - if (fireEvents) { - fireValueChanged(); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java deleted file mode 100644 index 912f9a7c83..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.splitpanel; - -import java.util.LinkedList; -import java.util.List; - -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.event.dom.client.DomEvent; -import com.google.gwt.event.dom.client.DomEvent.Type; -import com.google.gwt.event.shared.EventHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.Widget; -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.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; -import com.vaadin.terminal.gwt.client.LayoutManager; -import com.vaadin.terminal.gwt.client.communication.RpcProxy; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector; -import com.vaadin.terminal.gwt.client.ui.ClickEventHandler; -import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout; -import com.vaadin.terminal.gwt.client.ui.splitpanel.VAbstractSplitPanel.SplitterMoveHandler; -import com.vaadin.terminal.gwt.client.ui.splitpanel.VAbstractSplitPanel.SplitterMoveHandler.SplitterMoveEvent; - -public abstract class AbstractSplitPanelConnector extends - AbstractComponentContainerConnector implements SimpleManagedLayout { - - private AbstractSplitPanelRpc rpc; - - @Override - protected void init() { - super.init(); - rpc = RpcProxy.create(AbstractSplitPanelRpc.class, this); - // TODO Remove - getWidget().client = getConnection(); - - getWidget().addHandler(new SplitterMoveHandler() { - - @Override - public void splitterMoved(SplitterMoveEvent event) { - String position = getWidget().getSplitterPosition(); - float pos = 0; - if (position.indexOf("%") > 0) { - // Send % values as a fraction to avoid that the splitter - // "jumps" when server responds with the integer pct value - // (e.g. dragged 16.6% -> should not jump to 17%) - pos = Float.valueOf(position.substring(0, - position.length() - 1)); - } else { - pos = Integer.parseInt(position.substring(0, - position.length() - 2)); - } - - rpc.setSplitterPosition(pos); - } - - }, SplitterMoveEvent.TYPE); - } - - @Override - public void updateCaption(ComponentConnector component) { - // TODO Implement caption handling - } - - ClickEventHandler clickEventHandler = new ClickEventHandler(this) { - - @Override - protected <H extends EventHandler> HandlerRegistration registerHandler( - H handler, Type<H> type) { - if ((Event.getEventsSunk(getWidget().splitter) & Event - .getTypeInt(type.getName())) != 0) { - // If we are already sinking the event for the splitter we do - // not want to additionally sink it for the root element - return getWidget().addHandler(handler, type); - } else { - return getWidget().addDomHandler(handler, type); - } - } - - @Override - protected boolean shouldFireEvent(DomEvent<?> event) { - Element target = event.getNativeEvent().getEventTarget().cast(); - if (!getWidget().splitter.isOrHasChild(target)) { - return false; - } - - return super.shouldFireEvent(event); - }; - - @Override - protected Element getRelativeToElement() { - return getWidget().splitter; - }; - - @Override - protected void fireClick(NativeEvent event, - MouseEventDetails mouseDetails) { - rpc.splitterClick(mouseDetails); - } - - }; - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - getWidget().immediate = getState().isImmediate(); - - getWidget().setEnabled(isEnabled()); - - clickEventHandler.handleEventHandlerRegistration(); - - if (getState().hasStyles()) { - getWidget().componentStyleNames = getState().getStyles(); - } else { - getWidget().componentStyleNames = new LinkedList<String>(); - } - - // Splitter updates - SplitterState splitterState = getState().getSplitterState(); - - getWidget().setStylenames(); - - getWidget().minimumPosition = splitterState.getMinPosition() - + splitterState.getMinPositionUnit(); - - getWidget().maximumPosition = splitterState.getMaxPosition() - + splitterState.getMaxPositionUnit(); - - getWidget().position = splitterState.getPosition() - + splitterState.getPositionUnit(); - - // This is needed at least for cases like #3458 to take - // appearing/disappearing scrollbars into account. - getConnection().runDescendentsLayout(getWidget()); - - getLayoutManager().setNeedsLayout(this); - - getWidget().makeScrollable(); - } - - @Override - public void layout() { - VAbstractSplitPanel splitPanel = getWidget(); - splitPanel.setSplitPosition(splitPanel.position); - splitPanel.updateSizes(); - // Report relative sizes in other direction for quicker propagation - List<ComponentConnector> children = getChildComponents(); - for (ComponentConnector child : children) { - reportOtherDimension(child); - } - } - - private void reportOtherDimension(ComponentConnector child) { - LayoutManager layoutManager = getLayoutManager(); - if (this instanceof HorizontalSplitPanelConnector) { - if (child.isRelativeHeight()) { - int height = layoutManager.getInnerHeight(getWidget() - .getElement()); - layoutManager.reportHeightAssignedToRelative(child, height); - } - } else { - if (child.isRelativeWidth()) { - int width = layoutManager.getInnerWidth(getWidget() - .getElement()); - layoutManager.reportWidthAssignedToRelative(child, width); - } - } - } - - @Override - public VAbstractSplitPanel getWidget() { - return (VAbstractSplitPanel) super.getWidget(); - } - - @Override - public AbstractSplitPanelState getState() { - return (AbstractSplitPanelState) super.getState(); - } - - private ComponentConnector getFirstChild() { - return (ComponentConnector) getState().getFirstChild(); - } - - private ComponentConnector getSecondChild() { - return (ComponentConnector) getState().getSecondChild(); - } - - @Override - public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { - super.onConnectorHierarchyChange(event); - - Widget newFirstChildWidget = null; - if (getFirstChild() != null) { - newFirstChildWidget = getFirstChild().getWidget(); - } - getWidget().setFirstWidget(newFirstChildWidget); - - Widget newSecondChildWidget = null; - if (getSecondChild() != null) { - newSecondChildWidget = getSecondChild().getWidget(); - } - getWidget().setSecondWidget(newSecondChildWidget); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/HorizontalSplitPanelConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/HorizontalSplitPanelConnector.java deleted file mode 100644 index 3165e13407..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/HorizontalSplitPanelConnector.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.splitpanel; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.ui.HorizontalSplitPanel; - -@Connect(value = HorizontalSplitPanel.class, loadStyle = LoadStyle.EAGER) -public class HorizontalSplitPanelConnector extends AbstractSplitPanelConnector { - - @Override - public VSplitPanelHorizontal getWidget() { - return (VSplitPanelHorizontal) super.getWidget(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java b/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java deleted file mode 100644 index b83108b34c..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java +++ /dev/null @@ -1,784 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.splitpanel; - -import java.util.Collections; -import java.util.List; - -import com.google.gwt.dom.client.Node; -import com.google.gwt.dom.client.Style; -import com.google.gwt.event.dom.client.TouchCancelEvent; -import com.google.gwt.event.dom.client.TouchCancelHandler; -import com.google.gwt.event.dom.client.TouchEndEvent; -import com.google.gwt.event.dom.client.TouchEndHandler; -import com.google.gwt.event.dom.client.TouchMoveEvent; -import com.google.gwt.event.dom.client.TouchMoveHandler; -import com.google.gwt.event.dom.client.TouchStartEvent; -import com.google.gwt.event.dom.client.TouchStartHandler; -import com.google.gwt.event.shared.EventHandler; -import com.google.gwt.event.shared.GwtEvent; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.ComplexPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.LayoutManager; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate; -import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate.TouchScrollHandler; -import com.vaadin.terminal.gwt.client.ui.VOverlay; -import com.vaadin.terminal.gwt.client.ui.splitpanel.VAbstractSplitPanel.SplitterMoveHandler.SplitterMoveEvent; - -public class VAbstractSplitPanel extends ComplexPanel { - - private boolean enabled = false; - - public static final String CLASSNAME = "v-splitpanel"; - - public static final int ORIENTATION_HORIZONTAL = 0; - - public static final int ORIENTATION_VERTICAL = 1; - - private static final int MIN_SIZE = 30; - - private int orientation = ORIENTATION_HORIZONTAL; - - Widget firstChild; - - Widget secondChild; - - private final Element wrapper = DOM.createDiv(); - - private final Element firstContainer = DOM.createDiv(); - - private final Element secondContainer = DOM.createDiv(); - - final Element splitter = DOM.createDiv(); - - private boolean resizing; - - private boolean resized = false; - - private int origX; - - private int origY; - - private int origMouseX; - - private int origMouseY; - - private boolean locked = false; - - private boolean positionReversed = false; - - List<String> componentStyleNames = Collections.emptyList(); - - private Element draggingCurtain; - - ApplicationConnection client; - - boolean immediate; - - /* The current position of the split handle in either percentages or pixels */ - String position; - - String maximumPosition; - - String minimumPosition; - - private TouchScrollHandler touchScrollHandler; - - protected Element scrolledContainer; - - protected int origScrollTop; - - public VAbstractSplitPanel() { - this(ORIENTATION_HORIZONTAL); - } - - public VAbstractSplitPanel(int orientation) { - setElement(DOM.createDiv()); - switch (orientation) { - case ORIENTATION_HORIZONTAL: - setStyleName(CLASSNAME + "-horizontal"); - break; - case ORIENTATION_VERTICAL: - default: - setStyleName(CLASSNAME + "-vertical"); - break; - } - // size below will be overridden in update from uidl, initial size - // needed to keep IE alive - setWidth(MIN_SIZE + "px"); - setHeight(MIN_SIZE + "px"); - constructDom(); - setOrientation(orientation); - sinkEvents(Event.MOUSEEVENTS); - - makeScrollable(); - - addDomHandler(new TouchCancelHandler() { - @Override - public void onTouchCancel(TouchCancelEvent event) { - // TODO When does this actually happen?? - VConsole.log("TOUCH CANCEL"); - } - }, TouchCancelEvent.getType()); - addDomHandler(new TouchStartHandler() { - @Override - public void onTouchStart(TouchStartEvent event) { - Node target = event.getTouches().get(0).getTarget().cast(); - if (splitter.isOrHasChild(target)) { - onMouseDown(Event.as(event.getNativeEvent())); - } - } - }, TouchStartEvent.getType()); - addDomHandler(new TouchMoveHandler() { - @Override - public void onTouchMove(TouchMoveEvent event) { - if (resizing) { - onMouseMove(Event.as(event.getNativeEvent())); - } - } - }, TouchMoveEvent.getType()); - addDomHandler(new TouchEndHandler() { - @Override - public void onTouchEnd(TouchEndEvent event) { - if (resizing) { - onMouseUp(Event.as(event.getNativeEvent())); - } - } - }, TouchEndEvent.getType()); - - } - - protected void constructDom() { - DOM.appendChild(splitter, DOM.createDiv()); // for styling - DOM.appendChild(getElement(), wrapper); - DOM.setStyleAttribute(wrapper, "position", "relative"); - DOM.setStyleAttribute(wrapper, "width", "100%"); - DOM.setStyleAttribute(wrapper, "height", "100%"); - - DOM.appendChild(wrapper, secondContainer); - DOM.appendChild(wrapper, firstContainer); - DOM.appendChild(wrapper, splitter); - - DOM.setStyleAttribute(splitter, "position", "absolute"); - DOM.setStyleAttribute(secondContainer, "position", "absolute"); - - setStylenames(); - } - - private void setOrientation(int orientation) { - this.orientation = orientation; - if (orientation == ORIENTATION_HORIZONTAL) { - DOM.setStyleAttribute(splitter, "height", "100%"); - DOM.setStyleAttribute(splitter, "top", "0"); - DOM.setStyleAttribute(firstContainer, "height", "100%"); - DOM.setStyleAttribute(secondContainer, "height", "100%"); - } else { - DOM.setStyleAttribute(splitter, "width", "100%"); - DOM.setStyleAttribute(splitter, "left", "0"); - DOM.setStyleAttribute(firstContainer, "width", "100%"); - DOM.setStyleAttribute(secondContainer, "width", "100%"); - } - } - - @Override - public boolean remove(Widget w) { - boolean removed = super.remove(w); - if (removed) { - if (firstChild == w) { - firstChild = null; - } else { - secondChild = null; - } - } - return removed; - } - - void setLocked(boolean newValue) { - if (locked != newValue) { - locked = newValue; - splitterSize = -1; - setStylenames(); - } - } - - void setPositionReversed(boolean reversed) { - if (positionReversed != reversed) { - if (orientation == ORIENTATION_HORIZONTAL) { - DOM.setStyleAttribute(splitter, "right", ""); - DOM.setStyleAttribute(splitter, "left", ""); - } else if (orientation == ORIENTATION_VERTICAL) { - DOM.setStyleAttribute(splitter, "top", ""); - DOM.setStyleAttribute(splitter, "bottom", ""); - } - - positionReversed = reversed; - } - } - - /** - * Converts given split position string (in pixels or percentage) to a - * floating point pixel value. - * - * @param pos - * @return - */ - private float convertToPixels(String pos) { - float posAsFloat; - if (pos.indexOf("%") > 0) { - posAsFloat = Math.round(Float.parseFloat(pos.substring(0, - pos.length() - 1)) - / 100 - * (orientation == ORIENTATION_HORIZONTAL ? getOffsetWidth() - : getOffsetHeight())); - } else { - posAsFloat = Float.parseFloat(pos.substring(0, pos.length() - 2)); - } - return posAsFloat; - } - - /** - * Converts given split position string (in pixels or percentage) to a float - * percentage value. - * - * @param pos - * @return - */ - private float convertToPercentage(String pos) { - if (pos.endsWith("px")) { - float pixelPosition = Float.parseFloat(pos.substring(0, - pos.length() - 2)); - int offsetLength = orientation == ORIENTATION_HORIZONTAL ? getOffsetWidth() - : getOffsetHeight(); - - // Take splitter size into account at the edge - if (pixelPosition + getSplitterSize() >= offsetLength) { - return 100; - } - - return pixelPosition / offsetLength * 100; - } else { - assert pos.endsWith("%"); - return Float.parseFloat(pos.substring(0, pos.length() - 1)); - } - } - - /** - * Returns the given position clamped to the range between current minimum - * and maximum positions. - * - * TODO Should this be in the connector? - * - * @param pos - * Position of the splitter as a CSS string, either pixels or a - * percentage. - * @return minimumPosition if pos is less than minimumPosition; - * maximumPosition if pos is greater than maximumPosition; pos - * otherwise. - */ - private String checkSplitPositionLimits(String pos) { - float positionAsFloat = convertToPixels(pos); - - if (maximumPosition != null - && convertToPixels(maximumPosition) < positionAsFloat) { - pos = maximumPosition; - } else if (minimumPosition != null - && convertToPixels(minimumPosition) > positionAsFloat) { - pos = minimumPosition; - } - return pos; - } - - /** - * Converts given string to the same units as the split position is. - * - * @param pos - * position to be converted - * @return converted position string - */ - private String convertToPositionUnits(String pos) { - if (position.indexOf("%") != -1 && pos.indexOf("%") == -1) { - // position is in percentage, pos in pixels - pos = convertToPercentage(pos) + "%"; - } else if (position.indexOf("px") > 0 && pos.indexOf("px") == -1) { - // position is in pixels and pos in percentage - pos = convertToPixels(pos) + "px"; - } - - return pos; - } - - void setSplitPosition(String pos) { - if (pos == null) { - return; - } - - pos = checkSplitPositionLimits(pos); - if (!pos.equals(position)) { - position = convertToPositionUnits(pos); - } - - // Convert percentage values to pixels - if (pos.indexOf("%") > 0) { - int size = orientation == ORIENTATION_HORIZONTAL ? getOffsetWidth() - : getOffsetHeight(); - float percentage = Float.parseFloat(pos.substring(0, - pos.length() - 1)); - pos = percentage / 100 * size + "px"; - } - - String attributeName; - if (orientation == ORIENTATION_HORIZONTAL) { - if (positionReversed) { - attributeName = "right"; - } else { - attributeName = "left"; - } - } else { - if (positionReversed) { - attributeName = "bottom"; - } else { - attributeName = "top"; - } - } - - Style style = splitter.getStyle(); - if (!pos.equals(style.getProperty(attributeName))) { - style.setProperty(attributeName, pos); - updateSizes(); - } - } - - void updateSizes() { - if (!isAttached()) { - return; - } - - int wholeSize; - int pixelPosition; - - switch (orientation) { - case ORIENTATION_HORIZONTAL: - wholeSize = DOM.getElementPropertyInt(wrapper, "clientWidth"); - pixelPosition = DOM.getElementPropertyInt(splitter, "offsetLeft"); - - // reposition splitter in case it is out of box - if ((pixelPosition > 0 && pixelPosition + getSplitterSize() > wholeSize) - || (positionReversed && pixelPosition < 0)) { - pixelPosition = wholeSize - getSplitterSize(); - if (pixelPosition < 0) { - pixelPosition = 0; - } - setSplitPosition(pixelPosition + "px"); - return; - } - - DOM.setStyleAttribute(firstContainer, "width", pixelPosition + "px"); - int secondContainerWidth = (wholeSize - pixelPosition - getSplitterSize()); - if (secondContainerWidth < 0) { - secondContainerWidth = 0; - } - DOM.setStyleAttribute(secondContainer, "width", - secondContainerWidth + "px"); - DOM.setStyleAttribute(secondContainer, "left", - (pixelPosition + getSplitterSize()) + "px"); - - LayoutManager layoutManager = LayoutManager.get(client); - ConnectorMap connectorMap = ConnectorMap.get(client); - if (firstChild != null) { - ComponentConnector connector = connectorMap - .getConnector(firstChild); - if (connector.isRelativeWidth()) { - layoutManager.reportWidthAssignedToRelative(connector, - pixelPosition); - } else { - layoutManager.setNeedsMeasure(connector); - } - } - if (secondChild != null) { - ComponentConnector connector = connectorMap - .getConnector(secondChild); - if (connector.isRelativeWidth()) { - layoutManager.reportWidthAssignedToRelative(connector, - secondContainerWidth); - } else { - layoutManager.setNeedsMeasure(connector); - } - } - break; - case ORIENTATION_VERTICAL: - wholeSize = DOM.getElementPropertyInt(wrapper, "clientHeight"); - pixelPosition = DOM.getElementPropertyInt(splitter, "offsetTop"); - - // reposition splitter in case it is out of box - if ((pixelPosition > 0 && pixelPosition + getSplitterSize() > wholeSize) - || (positionReversed && pixelPosition < 0)) { - pixelPosition = wholeSize - getSplitterSize(); - if (pixelPosition < 0) { - pixelPosition = 0; - } - setSplitPosition(pixelPosition + "px"); - return; - } - - DOM.setStyleAttribute(firstContainer, "height", pixelPosition - + "px"); - int secondContainerHeight = (wholeSize - pixelPosition - getSplitterSize()); - if (secondContainerHeight < 0) { - secondContainerHeight = 0; - } - DOM.setStyleAttribute(secondContainer, "height", - secondContainerHeight + "px"); - DOM.setStyleAttribute(secondContainer, "top", - (pixelPosition + getSplitterSize()) + "px"); - - layoutManager = LayoutManager.get(client); - connectorMap = ConnectorMap.get(client); - if (firstChild != null) { - ComponentConnector connector = connectorMap - .getConnector(firstChild); - if (connector.isRelativeHeight()) { - layoutManager.reportHeightAssignedToRelative(connector, - pixelPosition); - } else { - layoutManager.setNeedsMeasure(connector); - } - } - if (secondChild != null) { - ComponentConnector connector = connectorMap - .getConnector(secondChild); - if (connector.isRelativeHeight()) { - layoutManager.reportHeightAssignedToRelative(connector, - secondContainerHeight); - } else { - layoutManager.setNeedsMeasure(connector); - } - } - break; - } - } - - void setFirstWidget(Widget w) { - if (firstChild != null) { - firstChild.removeFromParent(); - } - if (w != null) { - super.add(w, firstContainer); - } - firstChild = w; - } - - void setSecondWidget(Widget w) { - if (secondChild != null) { - secondChild.removeFromParent(); - } - if (w != null) { - super.add(w, secondContainer); - } - secondChild = w; - } - - @Override - public void onBrowserEvent(Event event) { - switch (DOM.eventGetType(event)) { - case Event.ONMOUSEMOVE: - // case Event.ONTOUCHMOVE: - if (resizing) { - onMouseMove(event); - } - break; - case Event.ONMOUSEDOWN: - // case Event.ONTOUCHSTART: - onMouseDown(event); - break; - case Event.ONMOUSEOUT: - // Dragging curtain interferes with click events if added in - // mousedown so we add it only when needed i.e., if the mouse moves - // outside the splitter. - if (resizing) { - showDraggingCurtain(); - } - break; - case Event.ONMOUSEUP: - // case Event.ONTOUCHEND: - if (resizing) { - onMouseUp(event); - } - break; - case Event.ONCLICK: - resizing = false; - break; - } - // Only fire click event listeners if the splitter isn't moved - if (Util.isTouchEvent(event) || !resized) { - super.onBrowserEvent(event); - } else if (DOM.eventGetType(event) == Event.ONMOUSEUP) { - // Reset the resized flag after a mouseup has occured so the next - // mousedown/mouseup can be interpreted as a click. - resized = false; - } - } - - public void onMouseDown(Event event) { - if (locked || !isEnabled()) { - return; - } - final Element trg = event.getEventTarget().cast(); - if (trg == splitter || trg == DOM.getChild(splitter, 0)) { - resizing = true; - DOM.setCapture(getElement()); - origX = DOM.getElementPropertyInt(splitter, "offsetLeft"); - origY = DOM.getElementPropertyInt(splitter, "offsetTop"); - origMouseX = Util.getTouchOrMouseClientX(event); - origMouseY = Util.getTouchOrMouseClientY(event); - event.stopPropagation(); - event.preventDefault(); - } - } - - public void onMouseMove(Event event) { - switch (orientation) { - case ORIENTATION_HORIZONTAL: - final int x = Util.getTouchOrMouseClientX(event); - onHorizontalMouseMove(x); - break; - case ORIENTATION_VERTICAL: - default: - final int y = Util.getTouchOrMouseClientY(event); - onVerticalMouseMove(y); - break; - } - - } - - private void onHorizontalMouseMove(int x) { - int newX = origX + x - origMouseX; - if (newX < 0) { - newX = 0; - } - if (newX + getSplitterSize() > getOffsetWidth()) { - newX = getOffsetWidth() - getSplitterSize(); - } - - if (position.indexOf("%") > 0) { - position = convertToPositionUnits(newX + "px"); - } else { - // Reversed position - if (positionReversed) { - position = (getOffsetWidth() - newX - getSplitterSize()) + "px"; - } else { - position = newX + "px"; - } - } - - if (origX != newX) { - resized = true; - } - - // Reversed position - if (positionReversed) { - newX = getOffsetWidth() - newX - getSplitterSize(); - } - - setSplitPosition(newX + "px"); - } - - private void onVerticalMouseMove(int y) { - int newY = origY + y - origMouseY; - if (newY < 0) { - newY = 0; - } - - if (newY + getSplitterSize() > getOffsetHeight()) { - newY = getOffsetHeight() - getSplitterSize(); - } - - if (position.indexOf("%") > 0) { - position = convertToPositionUnits(newY + "px"); - } else { - // Reversed position - if (positionReversed) { - position = (getOffsetHeight() - newY - getSplitterSize()) - + "px"; - } else { - position = newY + "px"; - } - } - - if (origY != newY) { - resized = true; - } - - // Reversed position - if (positionReversed) { - newY = getOffsetHeight() - newY - getSplitterSize(); - } - - setSplitPosition(newY + "px"); - } - - public void onMouseUp(Event event) { - DOM.releaseCapture(getElement()); - hideDraggingCurtain(); - resizing = false; - if (!Util.isTouchEvent(event)) { - onMouseMove(event); - } - fireEvent(new SplitterMoveEvent(this)); - } - - public interface SplitterMoveHandler extends EventHandler { - public void splitterMoved(SplitterMoveEvent event); - - public static class SplitterMoveEvent extends - GwtEvent<SplitterMoveHandler> { - - public static final Type<SplitterMoveHandler> TYPE = new Type<SplitterMoveHandler>(); - - private Widget splitPanel; - - public SplitterMoveEvent(Widget splitPanel) { - this.splitPanel = splitPanel; - } - - @Override - public com.google.gwt.event.shared.GwtEvent.Type<SplitterMoveHandler> getAssociatedType() { - return TYPE; - } - - @Override - protected void dispatch(SplitterMoveHandler handler) { - handler.splitterMoved(this); - } - - } - } - - String getSplitterPosition() { - return position; - } - - /** - * Used in FF to avoid losing mouse capture when pointer is moved on an - * iframe. - */ - private void showDraggingCurtain() { - if (!isDraggingCurtainRequired()) { - return; - } - if (draggingCurtain == null) { - draggingCurtain = DOM.createDiv(); - DOM.setStyleAttribute(draggingCurtain, "position", "absolute"); - DOM.setStyleAttribute(draggingCurtain, "top", "0px"); - DOM.setStyleAttribute(draggingCurtain, "left", "0px"); - DOM.setStyleAttribute(draggingCurtain, "width", "100%"); - DOM.setStyleAttribute(draggingCurtain, "height", "100%"); - DOM.setStyleAttribute(draggingCurtain, "zIndex", "" - + VOverlay.Z_INDEX); - - DOM.appendChild(wrapper, draggingCurtain); - } - } - - /** - * A dragging curtain is required in Gecko and Webkit. - * - * @return true if the browser requires a dragging curtain - */ - private boolean isDraggingCurtainRequired() { - return (BrowserInfo.get().isGecko() || BrowserInfo.get().isWebkit()); - } - - /** - * Hides dragging curtain - */ - private void hideDraggingCurtain() { - if (draggingCurtain != null) { - DOM.removeChild(wrapper, draggingCurtain); - draggingCurtain = null; - } - } - - private int splitterSize = -1; - - private int getSplitterSize() { - if (splitterSize < 0) { - if (isAttached()) { - switch (orientation) { - case ORIENTATION_HORIZONTAL: - splitterSize = DOM.getElementPropertyInt(splitter, - "offsetWidth"); - break; - - default: - splitterSize = DOM.getElementPropertyInt(splitter, - "offsetHeight"); - break; - } - } - } - return splitterSize; - } - - void setStylenames() { - final String splitterClass = CLASSNAME - + (orientation == ORIENTATION_HORIZONTAL ? "-hsplitter" - : "-vsplitter"); - final String firstContainerClass = CLASSNAME + "-first-container"; - final String secondContainerClass = CLASSNAME + "-second-container"; - final String lockedSuffix = locked ? "-locked" : ""; - - splitter.setClassName(splitterClass + lockedSuffix); - firstContainer.setClassName(firstContainerClass); - secondContainer.setClassName(secondContainerClass); - - for (String styleName : componentStyleNames) { - splitter.addClassName(splitterClass + "-" + styleName - + lockedSuffix); - firstContainer.addClassName(firstContainerClass + "-" + styleName); - secondContainer - .addClassName(secondContainerClass + "-" + styleName); - } - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public boolean isEnabled() { - return enabled; - } - - /** - * Ensures the panels are scrollable eg. after style name changes - */ - void makeScrollable() { - if (touchScrollHandler == null) { - touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this); - } - touchScrollHandler.addElement(firstContainer); - touchScrollHandler.addElement(secondContainer); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VSplitPanelHorizontal.java b/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VSplitPanelHorizontal.java deleted file mode 100644 index 7016620e2d..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VSplitPanelHorizontal.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.splitpanel; - -public class VSplitPanelHorizontal extends VAbstractSplitPanel { - - public VSplitPanelHorizontal() { - super(VAbstractSplitPanel.ORIENTATION_HORIZONTAL); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VSplitPanelVertical.java b/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VSplitPanelVertical.java deleted file mode 100644 index 02397ea4c6..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VSplitPanelVertical.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.splitpanel; - -public class VSplitPanelVertical extends VAbstractSplitPanel { - - public VSplitPanelVertical() { - super(VAbstractSplitPanel.ORIENTATION_VERTICAL); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VerticalSplitPanelConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VerticalSplitPanelConnector.java deleted file mode 100644 index ab4ea350ce..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VerticalSplitPanelConnector.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.splitpanel; - -import com.google.gwt.core.client.GWT; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.ui.VerticalSplitPanel; - -@Connect(value = VerticalSplitPanel.class, loadStyle = LoadStyle.EAGER) -public class VerticalSplitPanelConnector extends AbstractSplitPanelConnector { - - @Override - public VSplitPanelVertical getWidget() { - return (VSplitPanelVertical) super.getWidget(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java deleted file mode 100644 index 77d3fa61d5..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.table; - -import java.util.Iterator; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.Style.Position; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.AbstractFieldState; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.table.TableConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.DirectionalManagedLayout; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.ServerConnector; -import com.vaadin.terminal.gwt.client.TooltipInfo; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector; -import com.vaadin.terminal.gwt.client.ui.PostLayoutListener; -import com.vaadin.terminal.gwt.client.ui.table.VScrollTable.ContextMenuDetails; -import com.vaadin.terminal.gwt.client.ui.table.VScrollTable.VScrollTableBody.VScrollTableRow; - -@Connect(com.vaadin.ui.Table.class) -public class TableConnector extends AbstractComponentContainerConnector - implements Paintable, DirectionalManagedLayout, PostLayoutListener { - - @Override - protected void init() { - super.init(); - getWidget().init(getConnection()); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal - * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection) - */ - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - getWidget().rendering = true; - - // If a row has an open context menu, it will be closed as the row is - // detached. Retain a reference here so we can restore the menu if - // required. - ContextMenuDetails contextMenuBeforeUpdate = getWidget().contextMenu; - - if (uidl.hasAttribute(TableConstants.ATTRIBUTE_PAGEBUFFER_FIRST)) { - getWidget().serverCacheFirst = uidl - .getIntAttribute(TableConstants.ATTRIBUTE_PAGEBUFFER_FIRST); - getWidget().serverCacheLast = uidl - .getIntAttribute(TableConstants.ATTRIBUTE_PAGEBUFFER_LAST); - } else { - getWidget().serverCacheFirst = -1; - getWidget().serverCacheLast = -1; - } - /* - * We need to do this before updateComponent since updateComponent calls - * this.setHeight() which will calculate a new body height depending on - * the space available. - */ - if (uidl.hasAttribute("colfooters")) { - getWidget().showColFooters = uidl.getBooleanAttribute("colfooters"); - } - - getWidget().tFoot.setVisible(getWidget().showColFooters); - - if (!isRealUpdate(uidl)) { - getWidget().rendering = false; - return; - } - - getWidget().enabled = isEnabled(); - - if (BrowserInfo.get().isIE8() && !getWidget().enabled) { - /* - * The disabled shim will not cover the table body if it is relative - * in IE8. See #7324 - */ - getWidget().scrollBodyPanel.getElement().getStyle() - .setPosition(Position.STATIC); - } else if (BrowserInfo.get().isIE8()) { - getWidget().scrollBodyPanel.getElement().getStyle() - .setPosition(Position.RELATIVE); - } - - getWidget().paintableId = uidl.getStringAttribute("id"); - getWidget().immediate = getState().isImmediate(); - - int previousTotalRows = getWidget().totalRows; - getWidget().updateTotalRows(uidl); - boolean totalRowsChanged = (getWidget().totalRows != previousTotalRows); - - getWidget().updateDragMode(uidl); - - getWidget().updateSelectionProperties(uidl, getState(), isReadOnly()); - - if (uidl.hasAttribute("alb")) { - getWidget().bodyActionKeys = uidl.getStringArrayAttribute("alb"); - } else { - // Need to clear the actions if the action handlers have been - // removed - getWidget().bodyActionKeys = null; - } - - getWidget().setCacheRateFromUIDL(uidl); - - getWidget().recalcWidths = uidl.hasAttribute("recalcWidths"); - if (getWidget().recalcWidths) { - getWidget().tHead.clear(); - getWidget().tFoot.clear(); - } - - getWidget().updatePageLength(uidl); - - getWidget().updateFirstVisibleAndScrollIfNeeded(uidl); - - getWidget().showRowHeaders = uidl.getBooleanAttribute("rowheaders"); - getWidget().showColHeaders = uidl.getBooleanAttribute("colheaders"); - - getWidget().updateSortingProperties(uidl); - - boolean keyboardSelectionOverRowFetchInProgress = getWidget() - .selectSelectedRows(uidl); - - getWidget().updateActionMap(uidl); - - getWidget().updateColumnProperties(uidl); - - UIDL ac = uidl.getChildByTagName("-ac"); - if (ac == null) { - if (getWidget().dropHandler != null) { - // remove dropHandler if not present anymore - getWidget().dropHandler = null; - } - } else { - if (getWidget().dropHandler == null) { - getWidget().dropHandler = getWidget().new VScrollTableDropHandler(); - } - getWidget().dropHandler.updateAcceptRules(ac); - } - - UIDL partialRowAdditions = uidl.getChildByTagName("prows"); - UIDL partialRowUpdates = uidl.getChildByTagName("urows"); - if (partialRowUpdates != null || partialRowAdditions != null) { - // we may have pending cache row fetch, cancel it. See #2136 - getWidget().rowRequestHandler.cancel(); - - getWidget().updateRowsInBody(partialRowUpdates); - getWidget().addAndRemoveRows(partialRowAdditions); - } else { - UIDL rowData = uidl.getChildByTagName("rows"); - if (rowData != null) { - // we may have pending cache row fetch, cancel it. See #2136 - getWidget().rowRequestHandler.cancel(); - - if (!getWidget().recalcWidths - && getWidget().initializedAndAttached) { - getWidget().updateBody(rowData, - uidl.getIntAttribute("firstrow"), - uidl.getIntAttribute("rows")); - if (getWidget().headerChangedDuringUpdate) { - getWidget().triggerLazyColumnAdjustment(true); - } else if (!getWidget().isScrollPositionVisible() - || totalRowsChanged - || getWidget().lastRenderedHeight != getWidget().scrollBody - .getOffsetHeight()) { - // webkits may still bug with their disturbing scrollbar - // bug, see #3457 - // Run overflow fix for the scrollable area - // #6698 - If there's a scroll going on, don't abort it - // by changing overflows as the length of the contents - // *shouldn't* have changed (unless the number of rows - // or the height of the widget has also changed) - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - Util.runWebkitOverflowAutoFix(getWidget().scrollBodyPanel - .getElement()); - } - }); - } - } else { - getWidget().initializeRows(uidl, rowData); - } - } - } - - // If a row had an open context menu before the update, and after the - // update there's a row with the same key as that row, restore the - // context menu. See #8526. - showSavedContextMenu(contextMenuBeforeUpdate); - - if (!getWidget().isSelectable()) { - getWidget().scrollBody.addStyleName(VScrollTable.CLASSNAME - + "-body-noselection"); - } else { - getWidget().scrollBody.removeStyleName(VScrollTable.CLASSNAME - + "-body-noselection"); - } - - getWidget().hideScrollPositionAnnotation(); - - // selection is no in sync with server, avoid excessive server visits by - // clearing to flag used during the normal operation - if (!keyboardSelectionOverRowFetchInProgress) { - getWidget().selectionChanged = false; - } - - /* - * This is called when the Home or page up button has been pressed in - * selectable mode and the next selected row was not yet rendered in the - * client - */ - if (getWidget().selectFirstItemInNextRender - || getWidget().focusFirstItemInNextRender) { - getWidget().selectFirstRenderedRowInViewPort( - getWidget().focusFirstItemInNextRender); - getWidget().selectFirstItemInNextRender = getWidget().focusFirstItemInNextRender = false; - } - - /* - * This is called when the page down or end button has been pressed in - * selectable mode and the next selected row was not yet rendered in the - * client - */ - if (getWidget().selectLastItemInNextRender - || getWidget().focusLastItemInNextRender) { - getWidget().selectLastRenderedRowInViewPort( - getWidget().focusLastItemInNextRender); - getWidget().selectLastItemInNextRender = getWidget().focusLastItemInNextRender = false; - } - getWidget().multiselectPending = false; - - if (getWidget().focusedRow != null) { - if (!getWidget().focusedRow.isAttached() - && !getWidget().rowRequestHandler.isRunning()) { - // focused row has been orphaned, can't focus - getWidget().focusRowFromBody(); - } - } - - /* - * If the server has (re)initialized the rows, our selectionRangeStart - * row will point to an index that the server knows nothing about, - * causing problems if doing multi selection with shift. The field will - * be cleared a little later when the row focus has been restored. - * (#8584) - */ - if (uidl.hasAttribute(TableConstants.ATTRIBUTE_KEY_MAPPER_RESET) - && uidl.getBooleanAttribute(TableConstants.ATTRIBUTE_KEY_MAPPER_RESET) - && getWidget().selectionRangeStart != null) { - assert !getWidget().selectionRangeStart.isAttached(); - getWidget().selectionRangeStart = getWidget().focusedRow; - } - - getWidget().tabIndex = uidl.hasAttribute("tabindex") ? uidl - .getIntAttribute("tabindex") : 0; - getWidget().setProperTabIndex(); - - getWidget().resizeSortedColumnForSortIndicator(); - - // Remember this to detect situations where overflow hack might be - // needed during scrolling - getWidget().lastRenderedHeight = getWidget().scrollBody - .getOffsetHeight(); - - getWidget().rendering = false; - getWidget().headerChangedDuringUpdate = false; - - } - - @Override - public VScrollTable getWidget() { - return (VScrollTable) super.getWidget(); - } - - @Override - public void updateCaption(ComponentConnector component) { - // NOP, not rendered - } - - @Override - public void layoutVertically() { - getWidget().updateHeight(); - } - - @Override - public void layoutHorizontally() { - getWidget().updateWidth(); - } - - @Override - public void postLayout() { - VScrollTable table = getWidget(); - if (table.sizeNeedsInit) { - table.sizeInit(); - Scheduler.get().scheduleFinally(new ScheduledCommand() { - @Override - public void execute() { - getLayoutManager().setNeedsMeasure(TableConnector.this); - ServerConnector parent = getParent(); - if (parent instanceof ComponentConnector) { - getLayoutManager().setNeedsMeasure( - (ComponentConnector) parent); - } - getLayoutManager().setNeedsVerticalLayout( - TableConnector.this); - getLayoutManager().layoutNow(); - } - }); - } - } - - @Override - public boolean isReadOnly() { - return super.isReadOnly() || getState().isPropertyReadOnly(); - } - - @Override - public AbstractFieldState getState() { - return (AbstractFieldState) super.getState(); - } - - /** - * Shows a saved row context menu if the row for the context menu is still - * visible. Does nothing if a context menu has not been saved. - * - * @param savedContextMenu - */ - public void showSavedContextMenu(ContextMenuDetails savedContextMenu) { - if (isEnabled() && savedContextMenu != null) { - Iterator<Widget> iterator = getWidget().scrollBody.iterator(); - while (iterator.hasNext()) { - Widget w = iterator.next(); - VScrollTableRow row = (VScrollTableRow) w; - if (row.getKey().equals(savedContextMenu.rowKey)) { - getWidget().contextMenu = savedContextMenu; - getConnection().getContextMenu().showAt(row, - savedContextMenu.left, savedContextMenu.top); - } - } - } - } - - @Override - public TooltipInfo getTooltipInfo(Element element) { - - TooltipInfo info = null; - - if (element != getWidget().getElement()) { - Object node = Util.findWidget( - (com.google.gwt.user.client.Element) element, - VScrollTableRow.class); - - if (node != null) { - VScrollTableRow row = (VScrollTableRow) node; - info = row.getTooltip(element); - } - } - - if (info == null) { - info = super.getTooltipInfo(element); - } - - return info; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java b/client/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java deleted file mode 100644 index eda3f7090f..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java +++ /dev/null @@ -1,6969 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.table; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -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.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.dom.client.Node; -import com.google.gwt.dom.client.NodeList; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Display; -import com.google.gwt.dom.client.Style.Position; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.dom.client.Style.Visibility; -import com.google.gwt.dom.client.TableCellElement; -import com.google.gwt.dom.client.TableRowElement; -import com.google.gwt.dom.client.TableSectionElement; -import com.google.gwt.dom.client.Touch; -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.ContextMenuEvent; -import com.google.gwt.event.dom.client.ContextMenuHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.event.dom.client.KeyUpEvent; -import com.google.gwt.event.dom.client.KeyUpHandler; -import com.google.gwt.event.dom.client.ScrollEvent; -import com.google.gwt.event.dom.client.ScrollHandler; -import com.google.gwt.event.logical.shared.CloseEvent; -import com.google.gwt.event.logical.shared.CloseHandler; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.HasWidgets; -import com.google.gwt.user.client.ui.Panel; -import com.google.gwt.user.client.ui.PopupPanel; -import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.UIObject; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ComponentState; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.dd.VerticalDropLocation; -import com.vaadin.shared.ui.table.TableConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.Focusable; -import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder; -import com.vaadin.terminal.gwt.client.TooltipInfo; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.VTooltip; -import com.vaadin.terminal.gwt.client.ui.Action; -import com.vaadin.terminal.gwt.client.ui.ActionOwner; -import com.vaadin.terminal.gwt.client.ui.FocusableScrollPanel; -import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate; -import com.vaadin.terminal.gwt.client.ui.TreeAction; -import com.vaadin.terminal.gwt.client.ui.dd.DDUtil; -import com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler; -import com.vaadin.terminal.gwt.client.ui.dd.VAcceptCallback; -import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager; -import com.vaadin.terminal.gwt.client.ui.dd.VDragEvent; -import com.vaadin.terminal.gwt.client.ui.dd.VHasDropHandler; -import com.vaadin.terminal.gwt.client.ui.dd.VTransferable; -import com.vaadin.terminal.gwt.client.ui.embedded.VEmbedded; -import com.vaadin.terminal.gwt.client.ui.label.VLabel; -import com.vaadin.terminal.gwt.client.ui.table.VScrollTable.VScrollTableBody.VScrollTableRow; -import com.vaadin.terminal.gwt.client.ui.textfield.VTextField; - -/** - * VScrollTable - * - * VScrollTable is a FlowPanel having two widgets in it: * TableHead component * - * ScrollPanel - * - * TableHead contains table's header and widgets + logic for resizing, - * reordering and hiding columns. - * - * ScrollPanel contains VScrollTableBody object which handles content. To save - * some bandwidth and to improve clients responsiveness with loads of data, in - * VScrollTableBody all rows are not necessary rendered. There are "spacers" in - * VScrollTableBody to use the exact same space as non-rendered rows would use. - * This way we can use seamlessly traditional scrollbars and scrolling to fetch - * more rows instead of "paging". - * - * In VScrollTable we listen to scroll events. On horizontal scrolling we also - * update TableHeads scroll position which has its scrollbars hidden. On - * vertical scroll events we will check if we are reaching the end of area where - * we have rows rendered and - * - * TODO implement unregistering for child components in Cells - */ -public class VScrollTable extends FlowPanel implements HasWidgets, - ScrollHandler, VHasDropHandler, FocusHandler, BlurHandler, Focusable, - ActionOwner { - - public enum SelectMode { - NONE(0), SINGLE(1), MULTI(2); - private int id; - - private SelectMode(int id) { - this.id = id; - } - - public int getId() { - return id; - } - } - - private static final String ROW_HEADER_COLUMN_KEY = "0"; - - public static final String CLASSNAME = "v-table"; - public static final String CLASSNAME_SELECTION_FOCUS = CLASSNAME + "-focus"; - - private static final double CACHE_RATE_DEFAULT = 2; - - /** - * The default multi select mode where simple left clicks only selects one - * item, CTRL+left click selects multiple items and SHIFT-left click selects - * a range of items. - */ - private static final int MULTISELECT_MODE_DEFAULT = 0; - - /** - * The simple multiselect mode is what the table used to have before - * ctrl/shift selections were added. That is that when this is set clicking - * on an item selects/deselects the item and no ctrl/shift selections are - * available. - */ - private static final int MULTISELECT_MODE_SIMPLE = 1; - - /** - * multiple of pagelength which component will cache when requesting more - * rows - */ - private double cache_rate = CACHE_RATE_DEFAULT; - /** - * fraction of pageLenght which can be scrolled without making new request - */ - private double cache_react_rate = 0.75 * cache_rate; - - public static final char ALIGN_CENTER = 'c'; - public static final char ALIGN_LEFT = 'b'; - public static final char ALIGN_RIGHT = 'e'; - private static final int CHARCODE_SPACE = 32; - private int firstRowInViewPort = 0; - private int pageLength = 15; - private int lastRequestedFirstvisible = 0; // to detect "serverside scroll" - - protected boolean showRowHeaders = false; - - private String[] columnOrder; - - protected ApplicationConnection client; - protected String paintableId; - - boolean immediate; - private boolean nullSelectionAllowed = true; - - private SelectMode selectMode = SelectMode.NONE; - - private final HashSet<String> selectedRowKeys = new HashSet<String>(); - - /* - * When scrolling and selecting at the same time, the selections are not in - * sync with the server while retrieving new rows (until key is released). - */ - private HashSet<Object> unSyncedselectionsBeforeRowFetch; - - /* - * These are used when jumping between pages when pressing Home and End - */ - boolean selectLastItemInNextRender = false; - boolean selectFirstItemInNextRender = false; - boolean focusFirstItemInNextRender = false; - boolean focusLastItemInNextRender = false; - - /* - * The currently focused row - */ - VScrollTableRow focusedRow; - - /* - * Helper to store selection range start in when using the keyboard - */ - VScrollTableRow selectionRangeStart; - - /* - * Flag for notifying when the selection has changed and should be sent to - * the server - */ - boolean selectionChanged = false; - - /* - * The speed (in pixels) which the scrolling scrolls vertically/horizontally - */ - private int scrollingVelocity = 10; - - private Timer scrollingVelocityTimer = null; - - String[] bodyActionKeys; - - private boolean enableDebug = false; - - private static final boolean hasNativeTouchScrolling = BrowserInfo.get() - .isTouchDevice() - && !BrowserInfo.get().requiresTouchScrollDelegate(); - - private Set<String> noncollapsibleColumns; - - /** - * The last known row height used to preserve the height of a table with - * custom row heights and a fixed page length after removing the last row - * from the table. - * - * A new VScrollTableBody instance is created every time the number of rows - * changes causing {@link VScrollTableBody#rowHeight} to be discarded and - * the height recalculated by {@link VScrollTableBody#getRowHeight(boolean)} - * to avoid some rounding problems, e.g. round(2 * 19.8) / 2 = 20 but - * round(3 * 19.8) / 3 = 19.66. - */ - private double lastKnownRowHeight = Double.NaN; - - /** - * Represents a select range of rows - */ - private class SelectionRange { - private VScrollTableRow startRow; - private final int length; - - /** - * Constuctor. - */ - public SelectionRange(VScrollTableRow row1, VScrollTableRow row2) { - VScrollTableRow endRow; - if (row2.isBefore(row1)) { - startRow = row2; - endRow = row1; - } else { - startRow = row1; - endRow = row2; - } - length = endRow.getIndex() - startRow.getIndex() + 1; - } - - public SelectionRange(VScrollTableRow row, int length) { - startRow = row; - this.length = length; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - - @Override - public String toString() { - return startRow.getKey() + "-" + length; - } - - private boolean inRange(VScrollTableRow row) { - return row.getIndex() >= startRow.getIndex() - && row.getIndex() < startRow.getIndex() + length; - } - - public Collection<SelectionRange> split(VScrollTableRow row) { - assert row.isAttached(); - ArrayList<SelectionRange> ranges = new ArrayList<SelectionRange>(2); - - int endOfFirstRange = row.getIndex() - 1; - if (!(endOfFirstRange - startRow.getIndex() < 0)) { - // create range of first part unless its length is < 1 - ranges.add(new SelectionRange(startRow, endOfFirstRange - - startRow.getIndex() + 1)); - } - int startOfSecondRange = row.getIndex() + 1; - if (!(getEndIndex() - startOfSecondRange < 0)) { - // create range of second part unless its length is < 1 - VScrollTableRow startOfRange = scrollBody - .getRowByRowIndex(startOfSecondRange); - ranges.add(new SelectionRange(startOfRange, getEndIndex() - - startOfSecondRange + 1)); - } - return ranges; - } - - private int getEndIndex() { - return startRow.getIndex() + length - 1; - } - - }; - - private final HashSet<SelectionRange> selectedRowRanges = new HashSet<SelectionRange>(); - - boolean initializedAndAttached = false; - - /** - * Flag to indicate if a column width recalculation is needed due update. - */ - boolean headerChangedDuringUpdate = false; - - protected final TableHead tHead = new TableHead(); - - final TableFooter tFoot = new TableFooter(); - - final FocusableScrollPanel scrollBodyPanel = new FocusableScrollPanel(true); - - private KeyPressHandler navKeyPressHandler = new KeyPressHandler() { - - @Override - public void onKeyPress(KeyPressEvent keyPressEvent) { - // This is used for Firefox only, since Firefox auto-repeat - // works correctly only if we use a key press handler, other - // browsers handle it correctly when using a key down handler - if (!BrowserInfo.get().isGecko()) { - return; - } - - NativeEvent event = keyPressEvent.getNativeEvent(); - if (!enabled) { - // Cancel default keyboard events on a disabled Table - // (prevents scrolling) - event.preventDefault(); - } else if (hasFocus) { - // Key code in Firefox/onKeyPress is present only for - // special keys, otherwise 0 is returned - int keyCode = event.getKeyCode(); - if (keyCode == 0 && event.getCharCode() == ' ') { - // Provide a keyCode for space to be compatible with - // FireFox keypress event - keyCode = CHARCODE_SPACE; - } - - if (handleNavigation(keyCode, - event.getCtrlKey() || event.getMetaKey(), - event.getShiftKey())) { - event.preventDefault(); - } - - startScrollingVelocityTimer(); - } - } - - }; - - private KeyUpHandler navKeyUpHandler = new KeyUpHandler() { - - @Override - public void onKeyUp(KeyUpEvent keyUpEvent) { - NativeEvent event = keyUpEvent.getNativeEvent(); - int keyCode = event.getKeyCode(); - - if (!isFocusable()) { - cancelScrollingVelocityTimer(); - } else if (isNavigationKey(keyCode)) { - if (keyCode == getNavigationDownKey() - || keyCode == getNavigationUpKey()) { - /* - * in multiselect mode the server may still have value from - * previous page. Clear it unless doing multiselection or - * just moving focus. - */ - if (!event.getShiftKey() && !event.getCtrlKey()) { - instructServerToForgetPreviousSelections(); - } - sendSelectedRows(); - } - cancelScrollingVelocityTimer(); - navKeyDown = false; - } - } - }; - - private KeyDownHandler navKeyDownHandler = new KeyDownHandler() { - - @Override - public void onKeyDown(KeyDownEvent keyDownEvent) { - NativeEvent event = keyDownEvent.getNativeEvent(); - // This is not used for Firefox - if (BrowserInfo.get().isGecko()) { - return; - } - - if (!enabled) { - // Cancel default keyboard events on a disabled Table - // (prevents scrolling) - event.preventDefault(); - } else if (hasFocus) { - if (handleNavigation(event.getKeyCode(), event.getCtrlKey() - || event.getMetaKey(), event.getShiftKey())) { - navKeyDown = true; - event.preventDefault(); - } - - startScrollingVelocityTimer(); - } - } - }; - int totalRows; - - private Set<String> collapsedColumns; - - final RowRequestHandler rowRequestHandler; - VScrollTableBody scrollBody; - private int firstvisible = 0; - private boolean sortAscending; - private String sortColumn; - private String oldSortColumn; - private boolean columnReordering; - - /** - * This map contains captions and icon urls for actions like: * "33_c" -> - * "Edit" * "33_i" -> "http://dom.com/edit.png" - */ - private final HashMap<Object, String> actionMap = new HashMap<Object, String>(); - private String[] visibleColOrder; - private boolean initialContentReceived = false; - private Element scrollPositionElement; - boolean enabled; - boolean showColHeaders; - boolean showColFooters; - - /** flag to indicate that table body has changed */ - private boolean isNewBody = true; - - /* - * Read from the "recalcWidths" -attribute. When it is true, the table will - * recalculate the widths for columns - desirable in some cases. For #1983, - * marked experimental. - */ - boolean recalcWidths = false; - - boolean rendering = false; - private boolean hasFocus = false; - private int dragmode; - - private int multiselectmode; - int tabIndex; - private TouchScrollDelegate touchScrollDelegate; - - int lastRenderedHeight; - - /** - * Values (serverCacheFirst+serverCacheLast) sent by server that tells which - * rows (indexes) are in the server side cache (page buffer). -1 means - * unknown. The server side cache row MUST MATCH the client side cache rows. - * - * If the client side cache contains additional rows with e.g. buttons, it - * will cause out of sync when such a button is pressed. - * - * If the server side cache contains additional rows with e.g. buttons, - * scrolling in the client will cause empty buttons to be rendered - * (cached=true request for non-existing components) - */ - int serverCacheFirst = -1; - int serverCacheLast = -1; - - boolean sizeNeedsInit = true; - - /** - * Used to recall the position of an open context menu if we need to close - * and reopen it during a row update. - */ - class ContextMenuDetails { - String rowKey; - int left; - int top; - - ContextMenuDetails(String rowKey, int left, int top) { - this.rowKey = rowKey; - this.left = left; - this.top = top; - } - } - - protected ContextMenuDetails contextMenu = null; - - public VScrollTable() { - setMultiSelectMode(MULTISELECT_MODE_DEFAULT); - - scrollBodyPanel.addStyleName(CLASSNAME + "-body-wrapper"); - scrollBodyPanel.addFocusHandler(this); - scrollBodyPanel.addBlurHandler(this); - - scrollBodyPanel.addScrollHandler(this); - scrollBodyPanel.addStyleName(CLASSNAME + "-body"); - - /* - * Firefox auto-repeat works correctly only if we use a key press - * handler, other browsers handle it correctly when using a key down - * handler - */ - if (BrowserInfo.get().isGecko()) { - scrollBodyPanel.addKeyPressHandler(navKeyPressHandler); - } else { - scrollBodyPanel.addKeyDownHandler(navKeyDownHandler); - } - scrollBodyPanel.addKeyUpHandler(navKeyUpHandler); - - scrollBodyPanel.sinkEvents(Event.TOUCHEVENTS); - - scrollBodyPanel.sinkEvents(Event.ONCONTEXTMENU); - scrollBodyPanel.addDomHandler(new ContextMenuHandler() { - - @Override - public void onContextMenu(ContextMenuEvent event) { - handleBodyContextMenu(event); - } - }, ContextMenuEvent.getType()); - - setStyleName(CLASSNAME); - - add(tHead); - add(scrollBodyPanel); - add(tFoot); - - rowRequestHandler = new RowRequestHandler(); - } - - public void init(ApplicationConnection client) { - this.client = client; - // Add a handler to clear saved context menu details when the menu - // closes. See #8526. - client.getContextMenu().addCloseHandler(new CloseHandler<PopupPanel>() { - - @Override - public void onClose(CloseEvent<PopupPanel> event) { - contextMenu = null; - } - }); - } - - private void handleBodyContextMenu(ContextMenuEvent event) { - if (enabled && bodyActionKeys != null) { - int left = Util.getTouchOrMouseClientX(event.getNativeEvent()); - int top = Util.getTouchOrMouseClientY(event.getNativeEvent()); - top += Window.getScrollTop(); - left += Window.getScrollLeft(); - client.getContextMenu().showAt(this, left, top); - - // Only prevent browser context menu if there are action handlers - // registered - event.stopPropagation(); - event.preventDefault(); - } - } - - /** - * Fires a column resize event which sends the resize information to the - * server. - * - * @param columnId - * The columnId of the column which was resized - * @param originalWidth - * The width in pixels of the column before the resize event - * @param newWidth - * The width in pixels of the column after the resize event - */ - private void fireColumnResizeEvent(String columnId, int originalWidth, - int newWidth) { - client.updateVariable(paintableId, "columnResizeEventColumn", columnId, - false); - client.updateVariable(paintableId, "columnResizeEventPrev", - originalWidth, false); - client.updateVariable(paintableId, "columnResizeEventCurr", newWidth, - immediate); - - } - - /** - * Non-immediate variable update of column widths for a collection of - * columns. - * - * @param columns - * the columns to trigger the events for. - */ - private void sendColumnWidthUpdates(Collection<HeaderCell> columns) { - String[] newSizes = new String[columns.size()]; - int ix = 0; - for (HeaderCell cell : columns) { - newSizes[ix++] = cell.getColKey() + ":" + cell.getWidth(); - } - client.updateVariable(paintableId, "columnWidthUpdates", newSizes, - false); - } - - /** - * Moves the focus one step down - * - * @return Returns true if succeeded - */ - private boolean moveFocusDown() { - return moveFocusDown(0); - } - - /** - * Moves the focus down by 1+offset rows - * - * @return Returns true if succeeded, else false if the selection could not - * be move downwards - */ - private boolean moveFocusDown(int offset) { - if (isSelectable()) { - if (focusedRow == null && scrollBody.iterator().hasNext()) { - // FIXME should focus first visible from top, not first rendered - // ?? - return setRowFocus((VScrollTableRow) scrollBody.iterator() - .next()); - } else { - VScrollTableRow next = getNextRow(focusedRow, offset); - if (next != null) { - return setRowFocus(next); - } - } - } - - return false; - } - - /** - * Moves the selection one step up - * - * @return Returns true if succeeded - */ - private boolean moveFocusUp() { - return moveFocusUp(0); - } - - /** - * Moves the focus row upwards - * - * @return Returns true if succeeded, else false if the selection could not - * be move upwards - * - */ - private boolean moveFocusUp(int offset) { - if (isSelectable()) { - if (focusedRow == null && scrollBody.iterator().hasNext()) { - // FIXME logic is exactly the same as in moveFocusDown, should - // be the opposite?? - return setRowFocus((VScrollTableRow) scrollBody.iterator() - .next()); - } else { - VScrollTableRow prev = getPreviousRow(focusedRow, offset); - if (prev != null) { - return setRowFocus(prev); - } else { - VConsole.log("no previous available"); - } - } - } - - return false; - } - - /** - * Selects a row where the current selection head is - * - * @param ctrlSelect - * Is the selection a ctrl+selection - * @param shiftSelect - * Is the selection a shift+selection - * @return Returns truw - */ - private void selectFocusedRow(boolean ctrlSelect, boolean shiftSelect) { - if (focusedRow != null) { - // Arrows moves the selection and clears previous selections - if (isSelectable() && !ctrlSelect && !shiftSelect) { - deselectAll(); - focusedRow.toggleSelection(); - selectionRangeStart = focusedRow; - } else if (isSelectable() && ctrlSelect && !shiftSelect) { - // Ctrl+arrows moves selection head - selectionRangeStart = focusedRow; - // No selection, only selection head is moved - } else if (isMultiSelectModeAny() && !ctrlSelect && shiftSelect) { - // Shift+arrows selection selects a range - focusedRow.toggleShiftSelection(shiftSelect); - } - } - } - - /** - * Sends the selection to the server if changed since the last update/visit. - */ - protected void sendSelectedRows() { - sendSelectedRows(immediate); - } - - /** - * Sends the selection to the server if it has been changed since the last - * update/visit. - * - * @param immediately - * set to true to immediately send the rows - */ - protected void sendSelectedRows(boolean immediately) { - // Don't send anything if selection has not changed - if (!selectionChanged) { - return; - } - - // Reset selection changed flag - selectionChanged = false; - - // Note: changing the immediateness of this might require changes to - // "clickEvent" immediateness also. - if (isMultiSelectModeDefault()) { - // Convert ranges to a set of strings - Set<String> ranges = new HashSet<String>(); - for (SelectionRange range : selectedRowRanges) { - ranges.add(range.toString()); - } - - // Send the selected row ranges - client.updateVariable(paintableId, "selectedRanges", - ranges.toArray(new String[selectedRowRanges.size()]), false); - - // clean selectedRowKeys so that they don't contain excess values - for (Iterator<String> iterator = selectedRowKeys.iterator(); iterator - .hasNext();) { - String key = iterator.next(); - VScrollTableRow renderedRowByKey = getRenderedRowByKey(key); - if (renderedRowByKey != null) { - for (SelectionRange range : selectedRowRanges) { - if (range.inRange(renderedRowByKey)) { - iterator.remove(); - } - } - } else { - // orphaned selected key, must be in a range, ignore - iterator.remove(); - } - - } - } - - // Send the selected rows - client.updateVariable(paintableId, "selected", - selectedRowKeys.toArray(new String[selectedRowKeys.size()]), - immediately); - - } - - /** - * Get the key that moves the selection head upwards. By default it is the - * up arrow key but by overriding this you can change the key to whatever - * you want. - * - * @return The keycode of the key - */ - protected int getNavigationUpKey() { - return KeyCodes.KEY_UP; - } - - /** - * Get the key that moves the selection head downwards. By default it is the - * down arrow key but by overriding this you can change the key to whatever - * you want. - * - * @return The keycode of the key - */ - protected int getNavigationDownKey() { - return KeyCodes.KEY_DOWN; - } - - /** - * Get the key that scrolls to the left in the table. By default it is the - * left arrow key but by overriding this you can change the key to whatever - * you want. - * - * @return The keycode of the key - */ - protected int getNavigationLeftKey() { - return KeyCodes.KEY_LEFT; - } - - /** - * Get the key that scroll to the right on the table. By default it is the - * right arrow key but by overriding this you can change the key to whatever - * you want. - * - * @return The keycode of the key - */ - protected int getNavigationRightKey() { - return KeyCodes.KEY_RIGHT; - } - - /** - * Get the key that selects an item in the table. By default it is the space - * bar key but by overriding this you can change the key to whatever you - * want. - * - * @return - */ - protected int getNavigationSelectKey() { - return CHARCODE_SPACE; - } - - /** - * Get the key the moves the selection one page up in the table. By default - * this is the Page Up key but by overriding this you can change the key to - * whatever you want. - * - * @return - */ - protected int getNavigationPageUpKey() { - return KeyCodes.KEY_PAGEUP; - } - - /** - * Get the key the moves the selection one page down in the table. By - * default this is the Page Down key but by overriding this you can change - * the key to whatever you want. - * - * @return - */ - protected int getNavigationPageDownKey() { - return KeyCodes.KEY_PAGEDOWN; - } - - /** - * Get the key the moves the selection to the beginning of the table. By - * default this is the Home key but by overriding this you can change the - * key to whatever you want. - * - * @return - */ - protected int getNavigationStartKey() { - return KeyCodes.KEY_HOME; - } - - /** - * Get the key the moves the selection to the end of the table. By default - * this is the End key but by overriding this you can change the key to - * whatever you want. - * - * @return - */ - protected int getNavigationEndKey() { - return KeyCodes.KEY_END; - } - - void initializeRows(UIDL uidl, UIDL rowData) { - if (scrollBody != null) { - scrollBody.removeFromParent(); - } - scrollBody = createScrollBody(); - - scrollBody.renderInitialRows(rowData, uidl.getIntAttribute("firstrow"), - uidl.getIntAttribute("rows")); - scrollBodyPanel.add(scrollBody); - - // New body starts scrolled to the left, make sure the header and footer - // are also scrolled to the left - tHead.setHorizontalScrollPosition(0); - tFoot.setHorizontalScrollPosition(0); - - initialContentReceived = true; - sizeNeedsInit = true; - scrollBody.restoreRowVisibility(); - } - - void updateColumnProperties(UIDL uidl) { - updateColumnOrder(uidl); - - updateCollapsedColumns(uidl); - - UIDL vc = uidl.getChildByTagName("visiblecolumns"); - if (vc != null) { - tHead.updateCellsFromUIDL(vc); - tFoot.updateCellsFromUIDL(vc); - } - - updateHeader(uidl.getStringArrayAttribute("vcolorder")); - updateFooter(uidl.getStringArrayAttribute("vcolorder")); - if (uidl.hasVariable("noncollapsiblecolumns")) { - noncollapsibleColumns = uidl - .getStringArrayVariableAsSet("noncollapsiblecolumns"); - } - } - - private void updateCollapsedColumns(UIDL uidl) { - if (uidl.hasVariable("collapsedcolumns")) { - tHead.setColumnCollapsingAllowed(true); - collapsedColumns = uidl - .getStringArrayVariableAsSet("collapsedcolumns"); - } else { - tHead.setColumnCollapsingAllowed(false); - } - } - - private void updateColumnOrder(UIDL uidl) { - if (uidl.hasVariable("columnorder")) { - columnReordering = true; - columnOrder = uidl.getStringArrayVariable("columnorder"); - } else { - columnReordering = false; - columnOrder = null; - } - } - - boolean selectSelectedRows(UIDL uidl) { - boolean keyboardSelectionOverRowFetchInProgress = false; - - if (uidl.hasVariable("selected")) { - final Set<String> selectedKeys = uidl - .getStringArrayVariableAsSet("selected"); - if (scrollBody != null) { - Iterator<Widget> iterator = scrollBody.iterator(); - while (iterator.hasNext()) { - /* - * Make the focus reflect to the server side state unless we - * are currently selecting multiple rows with keyboard. - */ - VScrollTableRow row = (VScrollTableRow) iterator.next(); - boolean selected = selectedKeys.contains(row.getKey()); - if (!selected - && unSyncedselectionsBeforeRowFetch != null - && unSyncedselectionsBeforeRowFetch.contains(row - .getKey())) { - selected = true; - keyboardSelectionOverRowFetchInProgress = true; - } - if (selected != row.isSelected()) { - row.toggleSelection(); - if (!isSingleSelectMode() && !selected) { - // Update selection range in case a row is - // unselected from the middle of a range - #8076 - removeRowFromUnsentSelectionRanges(row); - } - } - } - } - } - unSyncedselectionsBeforeRowFetch = null; - return keyboardSelectionOverRowFetchInProgress; - } - - void updateSortingProperties(UIDL uidl) { - oldSortColumn = sortColumn; - if (uidl.hasVariable("sortascending")) { - sortAscending = uidl.getBooleanVariable("sortascending"); - sortColumn = uidl.getStringVariable("sortcolumn"); - } - } - - void resizeSortedColumnForSortIndicator() { - // Force recalculation of the captionContainer element inside the header - // cell to accomodate for the size of the sort arrow. - HeaderCell sortedHeader = tHead.getHeaderCell(sortColumn); - if (sortedHeader != null) { - tHead.resizeCaptionContainer(sortedHeader); - } - // Also recalculate the width of the captionContainer element in the - // previously sorted header, since this now has more room. - HeaderCell oldSortedHeader = tHead.getHeaderCell(oldSortColumn); - if (oldSortedHeader != null) { - tHead.resizeCaptionContainer(oldSortedHeader); - } - } - - void updateFirstVisibleAndScrollIfNeeded(UIDL uidl) { - firstvisible = uidl.hasVariable("firstvisible") ? uidl - .getIntVariable("firstvisible") : 0; - if (firstvisible != lastRequestedFirstvisible && scrollBody != null) { - // received 'surprising' firstvisible from server: scroll there - firstRowInViewPort = firstvisible; - scrollBodyPanel - .setScrollPosition(measureRowHeightOffset(firstvisible)); - } - } - - protected int measureRowHeightOffset(int rowIx) { - return (int) (rowIx * scrollBody.getRowHeight()); - } - - void updatePageLength(UIDL uidl) { - int oldPageLength = pageLength; - if (uidl.hasAttribute("pagelength")) { - pageLength = uidl.getIntAttribute("pagelength"); - } else { - // pagelenght is "0" meaning scrolling is turned off - pageLength = totalRows; - } - - if (oldPageLength != pageLength && initializedAndAttached) { - // page length changed, need to update size - sizeNeedsInit = true; - } - } - - void updateSelectionProperties(UIDL uidl, ComponentState state, - boolean readOnly) { - setMultiSelectMode(uidl.hasAttribute("multiselectmode") ? uidl - .getIntAttribute("multiselectmode") : MULTISELECT_MODE_DEFAULT); - - nullSelectionAllowed = uidl.hasAttribute("nsa") ? uidl - .getBooleanAttribute("nsa") : true; - - if (uidl.hasAttribute("selectmode")) { - if (readOnly) { - selectMode = SelectMode.NONE; - } else if (uidl.getStringAttribute("selectmode").equals("multi")) { - selectMode = SelectMode.MULTI; - } else if (uidl.getStringAttribute("selectmode").equals("single")) { - selectMode = SelectMode.SINGLE; - } else { - selectMode = SelectMode.NONE; - } - } - } - - void updateDragMode(UIDL uidl) { - dragmode = uidl.hasAttribute("dragmode") ? uidl - .getIntAttribute("dragmode") : 0; - if (BrowserInfo.get().isIE()) { - if (dragmode > 0) { - getElement().setPropertyJSO("onselectstart", - getPreventTextSelectionIEHack()); - } else { - getElement().setPropertyJSO("onselectstart", null); - } - } - } - - protected void updateTotalRows(UIDL uidl) { - int newTotalRows = uidl.getIntAttribute("totalrows"); - if (newTotalRows != getTotalRows()) { - if (scrollBody != null) { - if (getTotalRows() == 0) { - tHead.clear(); - tFoot.clear(); - } - initializedAndAttached = false; - initialContentReceived = false; - isNewBody = true; - } - setTotalRows(newTotalRows); - } - } - - protected void setTotalRows(int newTotalRows) { - totalRows = newTotalRows; - } - - public int getTotalRows() { - return totalRows; - } - - void focusRowFromBody() { - if (selectedRowKeys.size() == 1) { - // try to focus a row currently selected and in viewport - String selectedRowKey = selectedRowKeys.iterator().next(); - if (selectedRowKey != null) { - VScrollTableRow renderedRow = getRenderedRowByKey(selectedRowKey); - if (renderedRow == null || !renderedRow.isInViewPort()) { - setRowFocus(scrollBody.getRowByRowIndex(firstRowInViewPort)); - } else { - setRowFocus(renderedRow); - } - } - } else { - // multiselect mode - setRowFocus(scrollBody.getRowByRowIndex(firstRowInViewPort)); - } - } - - protected VScrollTableBody createScrollBody() { - return new VScrollTableBody(); - } - - /** - * Selects the last row visible in the table - * - * @param focusOnly - * Should the focus only be moved to the last row - */ - void selectLastRenderedRowInViewPort(boolean focusOnly) { - int index = firstRowInViewPort + getFullyVisibleRowCount(); - VScrollTableRow lastRowInViewport = scrollBody.getRowByRowIndex(index); - if (lastRowInViewport == null) { - // this should not happen in normal situations (white space at the - // end of viewport). Select the last rendered as a fallback. - lastRowInViewport = scrollBody.getRowByRowIndex(scrollBody - .getLastRendered()); - if (lastRowInViewport == null) { - return; // empty table - } - } - setRowFocus(lastRowInViewport); - if (!focusOnly) { - selectFocusedRow(false, multiselectPending); - sendSelectedRows(); - } - } - - /** - * Selects the first row visible in the table - * - * @param focusOnly - * Should the focus only be moved to the first row - */ - void selectFirstRenderedRowInViewPort(boolean focusOnly) { - int index = firstRowInViewPort; - VScrollTableRow firstInViewport = scrollBody.getRowByRowIndex(index); - if (firstInViewport == null) { - // this should not happen in normal situations - return; - } - setRowFocus(firstInViewport); - if (!focusOnly) { - selectFocusedRow(false, multiselectPending); - sendSelectedRows(); - } - } - - void setCacheRateFromUIDL(UIDL uidl) { - setCacheRate(uidl.hasAttribute("cr") ? uidl.getDoubleAttribute("cr") - : CACHE_RATE_DEFAULT); - } - - private void setCacheRate(double d) { - if (cache_rate != d) { - cache_rate = d; - cache_react_rate = 0.75 * d; - } - } - - void updateActionMap(UIDL mainUidl) { - UIDL actionsUidl = mainUidl.getChildByTagName("actions"); - if (actionsUidl == null) { - return; - } - - final Iterator<?> it = actionsUidl.getChildIterator(); - while (it.hasNext()) { - final UIDL action = (UIDL) it.next(); - final String key = action.getStringAttribute("key"); - final String caption = action.getStringAttribute("caption"); - actionMap.put(key + "_c", caption); - if (action.hasAttribute("icon")) { - // TODO need some uri handling ?? - actionMap.put(key + "_i", client.translateVaadinUri(action - .getStringAttribute("icon"))); - } else { - actionMap.remove(key + "_i"); - } - } - - } - - public String getActionCaption(String actionKey) { - return actionMap.get(actionKey + "_c"); - } - - public String getActionIcon(String actionKey) { - return actionMap.get(actionKey + "_i"); - } - - private void updateHeader(String[] strings) { - if (strings == null) { - return; - } - - int visibleCols = strings.length; - int colIndex = 0; - if (showRowHeaders) { - tHead.enableColumn(ROW_HEADER_COLUMN_KEY, colIndex); - visibleCols++; - visibleColOrder = new String[visibleCols]; - visibleColOrder[colIndex] = ROW_HEADER_COLUMN_KEY; - colIndex++; - } else { - visibleColOrder = new String[visibleCols]; - tHead.removeCell(ROW_HEADER_COLUMN_KEY); - } - - int i; - for (i = 0; i < strings.length; i++) { - final String cid = strings[i]; - visibleColOrder[colIndex] = cid; - tHead.enableColumn(cid, colIndex); - colIndex++; - } - - tHead.setVisible(showColHeaders); - setContainerHeight(); - - } - - /** - * Updates footers. - * <p> - * Update headers whould be called before this method is called! - * </p> - * - * @param strings - */ - private void updateFooter(String[] strings) { - if (strings == null) { - return; - } - - // Add dummy column if row headers are present - int colIndex = 0; - if (showRowHeaders) { - tFoot.enableColumn(ROW_HEADER_COLUMN_KEY, colIndex); - colIndex++; - } else { - tFoot.removeCell(ROW_HEADER_COLUMN_KEY); - } - - int i; - for (i = 0; i < strings.length; i++) { - final String cid = strings[i]; - tFoot.enableColumn(cid, colIndex); - colIndex++; - } - - tFoot.setVisible(showColFooters); - } - - /** - * @param uidl - * which contains row data - * @param firstRow - * first row in data set - * @param reqRows - * amount of rows in data set - */ - void updateBody(UIDL uidl, int firstRow, int reqRows) { - if (uidl == null || reqRows < 1) { - // container is empty, remove possibly existing rows - if (firstRow <= 0) { - while (scrollBody.getLastRendered() > scrollBody.firstRendered) { - scrollBody.unlinkRow(false); - } - scrollBody.unlinkRow(false); - } - return; - } - - scrollBody.renderRows(uidl, firstRow, reqRows); - - discardRowsOutsideCacheWindow(); - } - - void updateRowsInBody(UIDL partialRowUpdates) { - if (partialRowUpdates == null) { - return; - } - int firstRowIx = partialRowUpdates.getIntAttribute("firsturowix"); - int count = partialRowUpdates.getIntAttribute("numurows"); - scrollBody.unlinkRows(firstRowIx, count); - scrollBody.insertRows(partialRowUpdates, firstRowIx, count); - } - - /** - * Updates the internal cache by unlinking rows that fall outside of the - * caching window. - */ - protected void discardRowsOutsideCacheWindow() { - int firstRowToKeep = (int) (firstRowInViewPort - pageLength - * cache_rate); - int lastRowToKeep = (int) (firstRowInViewPort + pageLength + pageLength - * cache_rate); - debug("Client side calculated cache rows to keep: " + firstRowToKeep - + "-" + lastRowToKeep); - - if (serverCacheFirst != -1) { - firstRowToKeep = serverCacheFirst; - lastRowToKeep = serverCacheLast; - debug("Server cache rows that override: " + serverCacheFirst + "-" - + serverCacheLast); - if (firstRowToKeep < scrollBody.getFirstRendered() - || lastRowToKeep > scrollBody.getLastRendered()) { - debug("*** Server wants us to keep " + serverCacheFirst + "-" - + serverCacheLast + " but we only have rows " - + scrollBody.getFirstRendered() + "-" - + scrollBody.getLastRendered() + " rendered!"); - } - } - discardRowsOutsideOf(firstRowToKeep, lastRowToKeep); - - scrollBody.fixSpacers(); - - scrollBody.restoreRowVisibility(); - } - - private void discardRowsOutsideOf(int optimalFirstRow, int optimalLastRow) { - /* - * firstDiscarded and lastDiscarded are only calculated for debug - * purposes - */ - int firstDiscarded = -1, lastDiscarded = -1; - boolean cont = true; - while (cont && scrollBody.getLastRendered() > optimalFirstRow - && scrollBody.getFirstRendered() < optimalFirstRow) { - if (firstDiscarded == -1) { - firstDiscarded = scrollBody.getFirstRendered(); - } - - // removing row from start - cont = scrollBody.unlinkRow(true); - } - if (firstDiscarded != -1) { - lastDiscarded = scrollBody.getFirstRendered() - 1; - debug("Discarded rows " + firstDiscarded + "-" + lastDiscarded); - } - firstDiscarded = lastDiscarded = -1; - - cont = true; - while (cont && scrollBody.getLastRendered() > optimalLastRow) { - if (lastDiscarded == -1) { - lastDiscarded = scrollBody.getLastRendered(); - } - - // removing row from the end - cont = scrollBody.unlinkRow(false); - } - if (lastDiscarded != -1) { - firstDiscarded = scrollBody.getLastRendered() + 1; - debug("Discarded rows " + firstDiscarded + "-" + lastDiscarded); - } - - debug("Now in cache: " + scrollBody.getFirstRendered() + "-" - + scrollBody.getLastRendered()); - } - - /** - * Inserts rows in the table body or removes them from the table body based - * on the commands in the UIDL. - * - * @param partialRowAdditions - * the UIDL containing row updates. - */ - protected void addAndRemoveRows(UIDL partialRowAdditions) { - if (partialRowAdditions == null) { - return; - } - if (partialRowAdditions.hasAttribute("hide")) { - scrollBody.unlinkAndReindexRows( - partialRowAdditions.getIntAttribute("firstprowix"), - partialRowAdditions.getIntAttribute("numprows")); - scrollBody.ensureCacheFilled(); - } else { - if (partialRowAdditions.hasAttribute("delbelow")) { - scrollBody.insertRowsDeleteBelow(partialRowAdditions, - partialRowAdditions.getIntAttribute("firstprowix"), - partialRowAdditions.getIntAttribute("numprows")); - } else { - scrollBody.insertAndReindexRows(partialRowAdditions, - partialRowAdditions.getIntAttribute("firstprowix"), - partialRowAdditions.getIntAttribute("numprows")); - } - } - - discardRowsOutsideCacheWindow(); - } - - /** - * Gives correct column index for given column key ("cid" in UIDL). - * - * @param colKey - * @return column index of visible columns, -1 if column not visible - */ - private int getColIndexByKey(String colKey) { - // return 0 if asked for rowHeaders - if (ROW_HEADER_COLUMN_KEY.equals(colKey)) { - return 0; - } - for (int i = 0; i < visibleColOrder.length; i++) { - if (visibleColOrder[i].equals(colKey)) { - return i; - } - } - return -1; - } - - private boolean isMultiSelectModeSimple() { - return selectMode == SelectMode.MULTI - && multiselectmode == MULTISELECT_MODE_SIMPLE; - } - - private boolean isSingleSelectMode() { - return selectMode == SelectMode.SINGLE; - } - - private boolean isMultiSelectModeAny() { - return selectMode == SelectMode.MULTI; - } - - private boolean isMultiSelectModeDefault() { - return selectMode == SelectMode.MULTI - && multiselectmode == MULTISELECT_MODE_DEFAULT; - } - - private void setMultiSelectMode(int multiselectmode) { - if (BrowserInfo.get().isTouchDevice()) { - // Always use the simple mode for touch devices that do not have - // shift/ctrl keys - this.multiselectmode = MULTISELECT_MODE_SIMPLE; - } else { - this.multiselectmode = multiselectmode; - } - - } - - protected boolean isSelectable() { - return selectMode.getId() > SelectMode.NONE.getId(); - } - - private boolean isCollapsedColumn(String colKey) { - if (collapsedColumns == null) { - return false; - } - if (collapsedColumns.contains(colKey)) { - return true; - } - return false; - } - - private String getColKeyByIndex(int index) { - return tHead.getHeaderCell(index).getColKey(); - } - - private void setColWidth(int colIndex, int w, boolean isDefinedWidth) { - final HeaderCell hcell = tHead.getHeaderCell(colIndex); - - // Make sure that the column grows to accommodate the sort indicator if - // necessary. - if (w < hcell.getMinWidth()) { - w = hcell.getMinWidth(); - } - - // Set header column width - hcell.setWidth(w, isDefinedWidth); - - // Ensure indicators have been taken into account - tHead.resizeCaptionContainer(hcell); - - // Set body column width - scrollBody.setColWidth(colIndex, w); - - // Set footer column width - FooterCell fcell = tFoot.getFooterCell(colIndex); - fcell.setWidth(w, isDefinedWidth); - } - - private int getColWidth(String colKey) { - return tHead.getHeaderCell(colKey).getWidth(); - } - - /** - * Get a rendered row by its key - * - * @param key - * The key to search with - * @return - */ - public VScrollTableRow getRenderedRowByKey(String key) { - if (scrollBody != null) { - final Iterator<Widget> it = scrollBody.iterator(); - VScrollTableRow r = null; - while (it.hasNext()) { - r = (VScrollTableRow) it.next(); - if (r.getKey().equals(key)) { - return r; - } - } - } - return null; - } - - /** - * Returns the next row to the given row - * - * @param row - * The row to calculate from - * - * @return The next row or null if no row exists - */ - private VScrollTableRow getNextRow(VScrollTableRow row, int offset) { - final Iterator<Widget> it = scrollBody.iterator(); - VScrollTableRow r = null; - while (it.hasNext()) { - r = (VScrollTableRow) it.next(); - if (r == row) { - r = null; - while (offset >= 0 && it.hasNext()) { - r = (VScrollTableRow) it.next(); - offset--; - } - return r; - } - } - - return null; - } - - /** - * Returns the previous row from the given row - * - * @param row - * The row to calculate from - * @return The previous row or null if no row exists - */ - private VScrollTableRow getPreviousRow(VScrollTableRow row, int offset) { - final Iterator<Widget> it = scrollBody.iterator(); - final Iterator<Widget> offsetIt = scrollBody.iterator(); - VScrollTableRow r = null; - VScrollTableRow prev = null; - while (it.hasNext()) { - r = (VScrollTableRow) it.next(); - if (offset < 0) { - prev = (VScrollTableRow) offsetIt.next(); - } - if (r == row) { - return prev; - } - offset--; - } - - return null; - } - - protected void reOrderColumn(String columnKey, int newIndex) { - - final int oldIndex = getColIndexByKey(columnKey); - - // Change header order - tHead.moveCell(oldIndex, newIndex); - - // Change body order - scrollBody.moveCol(oldIndex, newIndex); - - // Change footer order - tFoot.moveCell(oldIndex, newIndex); - - /* - * Build new columnOrder and update it to server Note that columnOrder - * also contains collapsed columns so we cannot directly build it from - * cells vector Loop the old columnOrder and append in order to new - * array unless on moved columnKey. On new index also put the moved key - * i == index on columnOrder, j == index on newOrder - */ - final String oldKeyOnNewIndex = visibleColOrder[newIndex]; - if (showRowHeaders) { - newIndex--; // columnOrder don't have rowHeader - } - // add back hidden rows, - for (int i = 0; i < columnOrder.length; i++) { - if (columnOrder[i].equals(oldKeyOnNewIndex)) { - break; // break loop at target - } - if (isCollapsedColumn(columnOrder[i])) { - newIndex++; - } - } - // finally we can build the new columnOrder for server - final String[] newOrder = new String[columnOrder.length]; - for (int i = 0, j = 0; j < newOrder.length; i++) { - if (j == newIndex) { - newOrder[j] = columnKey; - j++; - } - if (i == columnOrder.length) { - break; - } - if (columnOrder[i].equals(columnKey)) { - continue; - } - newOrder[j] = columnOrder[i]; - j++; - } - columnOrder = newOrder; - // also update visibleColumnOrder - int i = showRowHeaders ? 1 : 0; - for (int j = 0; j < newOrder.length; j++) { - final String cid = newOrder[j]; - if (!isCollapsedColumn(cid)) { - visibleColOrder[i++] = cid; - } - } - client.updateVariable(paintableId, "columnorder", columnOrder, false); - if (client.hasEventListeners(this, - TableConstants.COLUMN_REORDER_EVENT_ID)) { - client.sendPendingVariableChanges(); - } - } - - @Override - protected void onDetach() { - rowRequestHandler.cancel(); - super.onDetach(); - // ensure that scrollPosElement will be detached - if (scrollPositionElement != null) { - final Element parent = DOM.getParent(scrollPositionElement); - if (parent != null) { - DOM.removeChild(parent, scrollPositionElement); - } - } - } - - /** - * Run only once when component is attached and received its initial - * content. This function: - * - * * Syncs headers and bodys "natural widths and saves the values. - * - * * Sets proper width and height - * - * * Makes deferred request to get some cache rows - */ - void sizeInit() { - sizeNeedsInit = false; - - scrollBody.setContainerHeight(); - - /* - * We will use browsers table rendering algorithm to find proper column - * widths. If content and header take less space than available, we will - * divide extra space relatively to each column which has not width set. - * - * Overflow pixels are added to last column. - */ - - Iterator<Widget> headCells = tHead.iterator(); - Iterator<Widget> footCells = tFoot.iterator(); - int i = 0; - int totalExplicitColumnsWidths = 0; - int total = 0; - float expandRatioDivider = 0; - - final int[] widths = new int[tHead.visibleCells.size()]; - - tHead.enableBrowserIntelligence(); - tFoot.enableBrowserIntelligence(); - - // first loop: collect natural widths - while (headCells.hasNext()) { - final HeaderCell hCell = (HeaderCell) headCells.next(); - final FooterCell fCell = (FooterCell) footCells.next(); - int w = hCell.getWidth(); - if (hCell.isDefinedWidth()) { - // server has defined column width explicitly - totalExplicitColumnsWidths += w; - } else { - if (hCell.getExpandRatio() > 0) { - expandRatioDivider += hCell.getExpandRatio(); - w = 0; - } else { - // get and store greater of header width and column width, - // and - // store it as a minimumn natural col width - int headerWidth = hCell.getNaturalColumnWidth(i); - int footerWidth = fCell.getNaturalColumnWidth(i); - w = headerWidth > footerWidth ? headerWidth : footerWidth; - } - hCell.setNaturalMinimumColumnWidth(w); - fCell.setNaturalMinimumColumnWidth(w); - } - widths[i] = w; - total += w; - i++; - } - - tHead.disableBrowserIntelligence(); - tFoot.disableBrowserIntelligence(); - - boolean willHaveScrollbarz = willHaveScrollbars(); - - // fix "natural" width if width not set - if (isDynamicWidth()) { - int w = total; - w += scrollBody.getCellExtraWidth() * visibleColOrder.length; - if (willHaveScrollbarz) { - w += Util.getNativeScrollbarSize(); - } - setContentWidth(w); - } - - int availW = scrollBody.getAvailableWidth(); - if (BrowserInfo.get().isIE()) { - // Hey IE, are you really sure about this? - availW = scrollBody.getAvailableWidth(); - } - availW -= scrollBody.getCellExtraWidth() * visibleColOrder.length; - - if (willHaveScrollbarz) { - availW -= Util.getNativeScrollbarSize(); - } - - // TODO refactor this code to be the same as in resize timer - boolean needsReLayout = false; - - if (availW > total) { - // natural size is smaller than available space - final int extraSpace = availW - total; - final int totalWidthR = total - totalExplicitColumnsWidths; - int checksum = 0; - needsReLayout = true; - - if (extraSpace == 1) { - // We cannot divide one single pixel so we give it the first - // undefined column - headCells = tHead.iterator(); - i = 0; - checksum = availW; - while (headCells.hasNext()) { - HeaderCell hc = (HeaderCell) headCells.next(); - if (!hc.isDefinedWidth()) { - widths[i]++; - break; - } - i++; - } - - } else if (expandRatioDivider > 0) { - // visible columns have some active expand ratios, excess - // space is divided according to them - headCells = tHead.iterator(); - i = 0; - while (headCells.hasNext()) { - HeaderCell hCell = (HeaderCell) headCells.next(); - if (hCell.getExpandRatio() > 0) { - int w = widths[i]; - final int newSpace = Math.round((extraSpace * (hCell - .getExpandRatio() / expandRatioDivider))); - w += newSpace; - widths[i] = w; - } - checksum += widths[i]; - i++; - } - } else if (totalWidthR > 0) { - // no expand ratios defined, we will share extra space - // relatively to "natural widths" among those without - // explicit width - headCells = tHead.iterator(); - i = 0; - while (headCells.hasNext()) { - HeaderCell hCell = (HeaderCell) headCells.next(); - if (!hCell.isDefinedWidth()) { - int w = widths[i]; - final int newSpace = Math.round((float) extraSpace - * (float) w / totalWidthR); - w += newSpace; - widths[i] = w; - } - checksum += widths[i]; - i++; - } - } - - if (extraSpace > 0 && checksum != availW) { - /* - * There might be in some cases a rounding error of 1px when - * extra space is divided so if there is one then we give the - * first undefined column 1 more pixel - */ - headCells = tHead.iterator(); - i = 0; - while (headCells.hasNext()) { - HeaderCell hc = (HeaderCell) headCells.next(); - if (!hc.isDefinedWidth()) { - widths[i] += availW - checksum; - break; - } - i++; - } - } - - } else { - // bodys size will be more than available and scrollbar will appear - } - - // last loop: set possibly modified values or reset if new tBody - i = 0; - headCells = tHead.iterator(); - while (headCells.hasNext()) { - final HeaderCell hCell = (HeaderCell) headCells.next(); - if (isNewBody || hCell.getWidth() == -1) { - final int w = widths[i]; - setColWidth(i, w, false); - } - i++; - } - - initializedAndAttached = true; - - if (needsReLayout) { - scrollBody.reLayoutComponents(); - } - - updatePageLength(); - - /* - * Fix "natural" height if height is not set. This must be after width - * fixing so the components' widths have been adjusted. - */ - if (isDynamicHeight()) { - /* - * We must force an update of the row height as this point as it - * might have been (incorrectly) calculated earlier - */ - - int bodyHeight; - if (pageLength == totalRows) { - /* - * A hack to support variable height rows when paging is off. - * Generally this is not supported by scrolltable. We want to - * show all rows so the bodyHeight should be equal to the table - * height. - */ - // int bodyHeight = scrollBody.getOffsetHeight(); - bodyHeight = scrollBody.getRequiredHeight(); - } else { - bodyHeight = (int) Math.round(scrollBody.getRowHeight(true) - * pageLength); - } - boolean needsSpaceForHorizontalSrollbar = (total > availW); - if (needsSpaceForHorizontalSrollbar) { - bodyHeight += Util.getNativeScrollbarSize(); - } - scrollBodyPanel.setHeight(bodyHeight + "px"); - Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement()); - } - - isNewBody = false; - - if (firstvisible > 0) { - // Deferred due to some Firefox oddities - Scheduler.get().scheduleDeferred(new Command() { - - @Override - public void execute() { - scrollBodyPanel - .setScrollPosition(measureRowHeightOffset(firstvisible)); - firstRowInViewPort = firstvisible; - } - }); - } - - if (enabled) { - // Do we need cache rows - if (scrollBody.getLastRendered() + 1 < firstRowInViewPort - + pageLength + (int) cache_react_rate * pageLength) { - if (totalRows - 1 > scrollBody.getLastRendered()) { - // fetch cache rows - int firstInNewSet = scrollBody.getLastRendered() + 1; - rowRequestHandler.setReqFirstRow(firstInNewSet); - int lastInNewSet = (int) (firstRowInViewPort + pageLength + cache_rate - * pageLength); - if (lastInNewSet > totalRows - 1) { - lastInNewSet = totalRows - 1; - } - rowRequestHandler.setReqRows(lastInNewSet - firstInNewSet - + 1); - rowRequestHandler.deferRowFetch(1); - } - } - } - - /* - * Ensures the column alignments are correct at initial loading. <br/> - * (child components widths are correct) - */ - scrollBody.reLayoutComponents(); - Scheduler.get().scheduleDeferred(new Command() { - - @Override - public void execute() { - Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement()); - } - }); - } - - /** - * Note, this method is not official api although declared as protected. - * Extend at you own risk. - * - * @return true if content area will have scrollbars visible. - */ - protected boolean willHaveScrollbars() { - if (isDynamicHeight()) { - if (pageLength < totalRows) { - return true; - } - } else { - int fakeheight = (int) Math.round(scrollBody.getRowHeight() - * totalRows); - int availableHeight = scrollBodyPanel.getElement().getPropertyInt( - "clientHeight"); - if (fakeheight > availableHeight) { - return true; - } - } - return false; - } - - private void announceScrollPosition() { - if (scrollPositionElement == null) { - scrollPositionElement = DOM.createDiv(); - scrollPositionElement.setClassName(CLASSNAME + "-scrollposition"); - scrollPositionElement.getStyle().setPosition(Position.ABSOLUTE); - scrollPositionElement.getStyle().setDisplay(Display.NONE); - getElement().appendChild(scrollPositionElement); - } - - Style style = scrollPositionElement.getStyle(); - style.setMarginLeft(getElement().getOffsetWidth() / 2 - 80, Unit.PX); - style.setMarginTop(-scrollBodyPanel.getOffsetHeight(), Unit.PX); - - // indexes go from 1-totalRows, as rowheaders in index-mode indicate - int last = (firstRowInViewPort + pageLength); - if (last > totalRows) { - last = totalRows; - } - scrollPositionElement.setInnerHTML("<span>" + (firstRowInViewPort + 1) - + " – " + (last) + "..." + "</span>"); - style.setDisplay(Display.BLOCK); - } - - void hideScrollPositionAnnotation() { - if (scrollPositionElement != null) { - DOM.setStyleAttribute(scrollPositionElement, "display", "none"); - } - } - - boolean isScrollPositionVisible() { - return scrollPositionElement != null - && !scrollPositionElement.getStyle().getDisplay() - .equals(Display.NONE.toString()); - } - - class RowRequestHandler extends Timer { - - private int reqFirstRow = 0; - private int reqRows = 0; - private boolean isRunning = false; - - public void deferRowFetch() { - deferRowFetch(250); - } - - public boolean isRunning() { - return isRunning; - } - - public void deferRowFetch(int msec) { - isRunning = true; - if (reqRows > 0 && reqFirstRow < totalRows) { - schedule(msec); - - // tell scroll position to user if currently "visible" rows are - // not rendered - if (totalRows > pageLength - && ((firstRowInViewPort + pageLength > scrollBody - .getLastRendered()) || (firstRowInViewPort < scrollBody - .getFirstRendered()))) { - announceScrollPosition(); - } else { - hideScrollPositionAnnotation(); - } - } - } - - public void setReqFirstRow(int reqFirstRow) { - if (reqFirstRow < 0) { - reqFirstRow = 0; - } else if (reqFirstRow >= totalRows) { - reqFirstRow = totalRows - 1; - } - this.reqFirstRow = reqFirstRow; - } - - public void setReqRows(int reqRows) { - this.reqRows = reqRows; - } - - @Override - public void run() { - if (client.hasActiveRequest() || navKeyDown) { - // if client connection is busy, don't bother loading it more - VConsole.log("Postponed rowfetch"); - schedule(250); - } else { - - int firstToBeRendered = scrollBody.firstRendered; - if (reqFirstRow < firstToBeRendered) { - firstToBeRendered = reqFirstRow; - } else if (firstRowInViewPort - (int) (cache_rate * pageLength) > firstToBeRendered) { - firstToBeRendered = firstRowInViewPort - - (int) (cache_rate * pageLength); - if (firstToBeRendered < 0) { - firstToBeRendered = 0; - } - } - - int lastToBeRendered = scrollBody.lastRendered; - - if (reqFirstRow + reqRows - 1 > lastToBeRendered) { - lastToBeRendered = reqFirstRow + reqRows - 1; - } else if (firstRowInViewPort + pageLength + pageLength - * cache_rate < lastToBeRendered) { - lastToBeRendered = (firstRowInViewPort + pageLength + (int) (pageLength * cache_rate)); - if (lastToBeRendered >= totalRows) { - lastToBeRendered = totalRows - 1; - } - // due Safari 3.1 bug (see #2607), verify reqrows, original - // problem unknown, but this should catch the issue - if (reqFirstRow + reqRows - 1 > lastToBeRendered) { - reqRows = lastToBeRendered - reqFirstRow; - } - } - - client.updateVariable(paintableId, "firstToBeRendered", - firstToBeRendered, false); - - client.updateVariable(paintableId, "lastToBeRendered", - lastToBeRendered, false); - // remember which firstvisible we requested, in case the server - // has - // a differing opinion - lastRequestedFirstvisible = firstRowInViewPort; - client.updateVariable(paintableId, "firstvisible", - firstRowInViewPort, false); - client.updateVariable(paintableId, "reqfirstrow", reqFirstRow, - false); - client.updateVariable(paintableId, "reqrows", reqRows, true); - - if (selectionChanged) { - unSyncedselectionsBeforeRowFetch = new HashSet<Object>( - selectedRowKeys); - } - isRunning = false; - } - } - - public int getReqFirstRow() { - return reqFirstRow; - } - - /** - * Sends request to refresh content at this position. - */ - public void refreshContent() { - isRunning = true; - int first = (int) (firstRowInViewPort - pageLength * cache_rate); - int reqRows = (int) (2 * pageLength * cache_rate + pageLength); - if (first < 0) { - reqRows = reqRows + first; - first = 0; - } - setReqFirstRow(first); - setReqRows(reqRows); - run(); - } - } - - public class HeaderCell extends Widget { - - Element td = DOM.createTD(); - - Element captionContainer = DOM.createDiv(); - - Element sortIndicator = DOM.createDiv(); - - Element colResizeWidget = DOM.createDiv(); - - Element floatingCopyOfHeaderCell; - - private boolean sortable = false; - private final String cid; - private boolean dragging; - - private int dragStartX; - private int colIndex; - private int originalWidth; - - private boolean isResizing; - - private int headerX; - - private boolean moved; - - private int closestSlot; - - private int width = -1; - - private int naturalWidth = -1; - - private char align = ALIGN_LEFT; - - boolean definedWidth = false; - - private float expandRatio = 0; - - private boolean sorted; - - public void setSortable(boolean b) { - sortable = b; - } - - /** - * Makes room for the sorting indicator in case the column that the - * header cell belongs to is sorted. This is done by resizing the width - * of the caption container element by the correct amount - */ - public void resizeCaptionContainer(int rightSpacing) { - int captionContainerWidth = width - - colResizeWidget.getOffsetWidth() - rightSpacing; - - if (td.getClassName().contains("-asc") - || td.getClassName().contains("-desc")) { - // Leave room for the sort indicator - captionContainerWidth -= sortIndicator.getOffsetWidth(); - } - - if (captionContainerWidth < 0) { - rightSpacing += captionContainerWidth; - captionContainerWidth = 0; - } - - captionContainer.getStyle().setPropertyPx("width", - captionContainerWidth); - - // Apply/Remove spacing if defined - if (rightSpacing > 0) { - colResizeWidget.getStyle().setMarginLeft(rightSpacing, Unit.PX); - } else { - colResizeWidget.getStyle().clearMarginLeft(); - } - } - - public void setNaturalMinimumColumnWidth(int w) { - naturalWidth = w; - } - - public HeaderCell(String colId, String headerText) { - cid = colId; - - DOM.setElementProperty(colResizeWidget, "className", CLASSNAME - + "-resizer"); - - setText(headerText); - - DOM.appendChild(td, colResizeWidget); - - DOM.setElementProperty(sortIndicator, "className", CLASSNAME - + "-sort-indicator"); - DOM.appendChild(td, sortIndicator); - - DOM.setElementProperty(captionContainer, "className", CLASSNAME - + "-caption-container"); - - // ensure no clipping initially (problem on column additions) - DOM.setStyleAttribute(captionContainer, "overflow", "visible"); - - DOM.appendChild(td, captionContainer); - - DOM.sinkEvents(td, Event.MOUSEEVENTS | Event.ONDBLCLICK - | Event.ONCONTEXTMENU | Event.TOUCHEVENTS); - - setElement(td); - - setAlign(ALIGN_LEFT); - } - - public void disableAutoWidthCalculation() { - definedWidth = true; - expandRatio = 0; - } - - public void setWidth(int w, boolean ensureDefinedWidth) { - if (ensureDefinedWidth) { - definedWidth = true; - // on column resize expand ratio becomes zero - expandRatio = 0; - } - if (width == -1) { - // go to default mode, clip content if necessary - DOM.setStyleAttribute(captionContainer, "overflow", ""); - } - width = w; - if (w == -1) { - DOM.setStyleAttribute(captionContainer, "width", ""); - setWidth(""); - } else { - tHead.resizeCaptionContainer(this); - - /* - * if we already have tBody, set the header width properly, if - * not defer it. IE will fail with complex float in table header - * unless TD width is not explicitly set. - */ - if (scrollBody != null) { - int tdWidth = width + scrollBody.getCellExtraWidth(); - setWidth(tdWidth + "px"); - } else { - Scheduler.get().scheduleDeferred(new Command() { - - @Override - public void execute() { - int tdWidth = width - + scrollBody.getCellExtraWidth(); - setWidth(tdWidth + "px"); - } - }); - } - } - } - - public void setUndefinedWidth() { - definedWidth = false; - setWidth(-1, false); - } - - /** - * Detects if width is fixed by developer on server side or resized to - * current width by user. - * - * @return true if defined, false if "natural" width - */ - public boolean isDefinedWidth() { - return definedWidth && width >= 0; - } - - public int getWidth() { - return width; - } - - public void setText(String headerText) { - DOM.setInnerHTML(captionContainer, headerText); - } - - public String getColKey() { - return cid; - } - - private void setSorted(boolean sorted) { - this.sorted = sorted; - if (sorted) { - if (sortAscending) { - this.setStyleName(CLASSNAME + "-header-cell-asc"); - } else { - this.setStyleName(CLASSNAME + "-header-cell-desc"); - } - } else { - this.setStyleName(CLASSNAME + "-header-cell"); - } - } - - /** - * Handle column reordering. - */ - - @Override - public void onBrowserEvent(Event event) { - if (enabled && event != null) { - if (isResizing - || event.getEventTarget().cast() == colResizeWidget) { - if (dragging - && (event.getTypeInt() == Event.ONMOUSEUP || event - .getTypeInt() == Event.ONTOUCHEND)) { - // Handle releasing column header on spacer #5318 - handleCaptionEvent(event); - } else { - onResizeEvent(event); - } - } else { - /* - * Ensure focus before handling caption event. Otherwise - * variables changed from caption event may be before - * variables from other components that fire variables when - * they lose focus. - */ - if (event.getTypeInt() == Event.ONMOUSEDOWN - || event.getTypeInt() == Event.ONTOUCHSTART) { - scrollBodyPanel.setFocus(true); - } - handleCaptionEvent(event); - boolean stopPropagation = true; - if (event.getTypeInt() == Event.ONCONTEXTMENU - && !client.hasEventListeners(VScrollTable.this, - TableConstants.HEADER_CLICK_EVENT_ID)) { - // Prevent showing the browser's context menu only when - // there is a header click listener. - stopPropagation = false; - } - if (stopPropagation) { - event.stopPropagation(); - event.preventDefault(); - } - } - } - } - - private void createFloatingCopy() { - floatingCopyOfHeaderCell = DOM.createDiv(); - DOM.setInnerHTML(floatingCopyOfHeaderCell, DOM.getInnerHTML(td)); - floatingCopyOfHeaderCell = DOM - .getChild(floatingCopyOfHeaderCell, 2); - DOM.setElementProperty(floatingCopyOfHeaderCell, "className", - CLASSNAME + "-header-drag"); - // otherwise might wrap or be cut if narrow column - DOM.setStyleAttribute(floatingCopyOfHeaderCell, "width", "auto"); - updateFloatingCopysPosition(DOM.getAbsoluteLeft(td), - DOM.getAbsoluteTop(td)); - DOM.appendChild(RootPanel.get().getElement(), - floatingCopyOfHeaderCell); - } - - private void updateFloatingCopysPosition(int x, int y) { - x -= DOM.getElementPropertyInt(floatingCopyOfHeaderCell, - "offsetWidth") / 2; - DOM.setStyleAttribute(floatingCopyOfHeaderCell, "left", x + "px"); - if (y > 0) { - DOM.setStyleAttribute(floatingCopyOfHeaderCell, "top", (y + 7) - + "px"); - } - } - - private void hideFloatingCopy() { - DOM.removeChild(RootPanel.get().getElement(), - floatingCopyOfHeaderCell); - floatingCopyOfHeaderCell = null; - } - - /** - * Fires a header click event after the user has clicked a column header - * cell - * - * @param event - * The click event - */ - private void fireHeaderClickedEvent(Event event) { - if (client.hasEventListeners(VScrollTable.this, - TableConstants.HEADER_CLICK_EVENT_ID)) { - MouseEventDetails details = MouseEventDetailsBuilder - .buildMouseEventDetails(event); - client.updateVariable(paintableId, "headerClickEvent", - details.toString(), false); - client.updateVariable(paintableId, "headerClickCID", cid, true); - } - } - - protected void handleCaptionEvent(Event event) { - switch (DOM.eventGetType(event)) { - case Event.ONTOUCHSTART: - case Event.ONMOUSEDOWN: - if (columnReordering - && Util.isTouchEventOrLeftMouseButton(event)) { - if (event.getTypeInt() == Event.ONTOUCHSTART) { - /* - * prevent using this event in e.g. scrolling - */ - event.stopPropagation(); - } - dragging = true; - moved = false; - colIndex = getColIndexByKey(cid); - DOM.setCapture(getElement()); - headerX = tHead.getAbsoluteLeft(); - event.preventDefault(); // prevent selecting text && - // generated touch events - } - break; - case Event.ONMOUSEUP: - case Event.ONTOUCHEND: - case Event.ONTOUCHCANCEL: - if (columnReordering - && Util.isTouchEventOrLeftMouseButton(event)) { - dragging = false; - DOM.releaseCapture(getElement()); - if (moved) { - hideFloatingCopy(); - tHead.removeSlotFocus(); - if (closestSlot != colIndex - && closestSlot != (colIndex + 1)) { - if (closestSlot > colIndex) { - reOrderColumn(cid, closestSlot - 1); - } else { - reOrderColumn(cid, closestSlot); - } - } - } - if (Util.isTouchEvent(event)) { - /* - * Prevent using in e.g. scrolling and prevent generated - * events. - */ - event.preventDefault(); - event.stopPropagation(); - } - } - - if (!moved) { - // mouse event was a click to header -> sort column - if (sortable && Util.isTouchEventOrLeftMouseButton(event)) { - if (sortColumn.equals(cid)) { - // just toggle order - client.updateVariable(paintableId, "sortascending", - !sortAscending, false); - } else { - // set table sorted by this column - client.updateVariable(paintableId, "sortcolumn", - cid, false); - } - // get also cache columns at the same request - scrollBodyPanel.setScrollPosition(0); - firstvisible = 0; - rowRequestHandler.setReqFirstRow(0); - rowRequestHandler.setReqRows((int) (2 * pageLength - * cache_rate + pageLength)); - rowRequestHandler.deferRowFetch(); // some validation + - // defer 250ms - rowRequestHandler.cancel(); // instead of waiting - rowRequestHandler.run(); // run immediately - } - fireHeaderClickedEvent(event); - if (Util.isTouchEvent(event)) { - /* - * Prevent using in e.g. scrolling and prevent generated - * events. - */ - event.preventDefault(); - event.stopPropagation(); - } - break; - } - break; - case Event.ONDBLCLICK: - fireHeaderClickedEvent(event); - break; - case Event.ONTOUCHMOVE: - case Event.ONMOUSEMOVE: - if (dragging && Util.isTouchEventOrLeftMouseButton(event)) { - if (event.getTypeInt() == Event.ONTOUCHMOVE) { - /* - * prevent using this event in e.g. scrolling - */ - event.stopPropagation(); - } - if (!moved) { - createFloatingCopy(); - moved = true; - } - - final int clientX = Util.getTouchOrMouseClientX(event); - final int x = clientX + tHead.hTableWrapper.getScrollLeft(); - int slotX = headerX; - closestSlot = colIndex; - int closestDistance = -1; - int start = 0; - if (showRowHeaders) { - start++; - } - final int visibleCellCount = tHead.getVisibleCellCount(); - for (int i = start; i <= visibleCellCount; i++) { - if (i > 0) { - final String colKey = getColKeyByIndex(i - 1); - slotX += getColWidth(colKey); - } - final int dist = Math.abs(x - slotX); - if (closestDistance == -1 || dist < closestDistance) { - closestDistance = dist; - closestSlot = i; - } - } - tHead.focusSlot(closestSlot); - - updateFloatingCopysPosition(clientX, -1); - } - break; - default: - break; - } - } - - private void onResizeEvent(Event event) { - switch (DOM.eventGetType(event)) { - case Event.ONMOUSEDOWN: - if (!Util.isTouchEventOrLeftMouseButton(event)) { - return; - } - isResizing = true; - DOM.setCapture(getElement()); - dragStartX = DOM.eventGetClientX(event); - colIndex = getColIndexByKey(cid); - originalWidth = getWidth(); - DOM.eventPreventDefault(event); - break; - case Event.ONMOUSEUP: - if (!Util.isTouchEventOrLeftMouseButton(event)) { - return; - } - isResizing = false; - DOM.releaseCapture(getElement()); - tHead.disableAutoColumnWidthCalculation(this); - - // Ensure last header cell is taking into account possible - // column selector - HeaderCell lastCell = tHead.getHeaderCell(tHead - .getVisibleCellCount() - 1); - tHead.resizeCaptionContainer(lastCell); - triggerLazyColumnAdjustment(true); - - fireColumnResizeEvent(cid, originalWidth, getColWidth(cid)); - break; - case Event.ONMOUSEMOVE: - if (!Util.isTouchEventOrLeftMouseButton(event)) { - return; - } - if (isResizing) { - final int deltaX = DOM.eventGetClientX(event) - dragStartX; - if (deltaX == 0) { - return; - } - tHead.disableAutoColumnWidthCalculation(this); - - int newWidth = originalWidth + deltaX; - if (newWidth < getMinWidth()) { - newWidth = getMinWidth(); - } - setColWidth(colIndex, newWidth, true); - triggerLazyColumnAdjustment(false); - forceRealignColumnHeaders(); - } - break; - default: - break; - } - } - - public int getMinWidth() { - int cellExtraWidth = 0; - if (scrollBody != null) { - cellExtraWidth += scrollBody.getCellExtraWidth(); - } - return cellExtraWidth + sortIndicator.getOffsetWidth(); - } - - public String getCaption() { - return DOM.getInnerText(captionContainer); - } - - public boolean isEnabled() { - return getParent() != null; - } - - public void setAlign(char c) { - final String ALIGN_PREFIX = CLASSNAME + "-caption-container-align-"; - if (align != c) { - captionContainer.removeClassName(ALIGN_PREFIX + "center"); - captionContainer.removeClassName(ALIGN_PREFIX + "right"); - captionContainer.removeClassName(ALIGN_PREFIX + "left"); - switch (c) { - case ALIGN_CENTER: - captionContainer.addClassName(ALIGN_PREFIX + "center"); - break; - case ALIGN_RIGHT: - captionContainer.addClassName(ALIGN_PREFIX + "right"); - break; - default: - captionContainer.addClassName(ALIGN_PREFIX + "left"); - break; - } - } - align = c; - } - - public char getAlign() { - return align; - } - - /** - * Detects the natural minimum width for the column of this header cell. - * If column is resized by user or the width is defined by server the - * actual width is returned. Else the natural min width is returned. - * - * @param columnIndex - * column index hint, if -1 (unknown) it will be detected - * - * @return - */ - public int getNaturalColumnWidth(int columnIndex) { - if (isDefinedWidth()) { - return width; - } else { - if (naturalWidth < 0) { - // This is recently revealed column. Try to detect a proper - // value (greater of header and data - // cols) - - int hw = captionContainer.getOffsetWidth() - + scrollBody.getCellExtraWidth(); - if (BrowserInfo.get().isGecko()) { - hw += sortIndicator.getOffsetWidth(); - } - if (columnIndex < 0) { - columnIndex = 0; - for (Iterator<Widget> it = tHead.iterator(); it - .hasNext(); columnIndex++) { - if (it.next() == this) { - break; - } - } - } - final int cw = scrollBody.getColWidth(columnIndex); - naturalWidth = (hw > cw ? hw : cw); - } - return naturalWidth; - } - } - - public void setExpandRatio(float floatAttribute) { - if (floatAttribute != expandRatio) { - triggerLazyColumnAdjustment(false); - } - expandRatio = floatAttribute; - } - - public float getExpandRatio() { - return expandRatio; - } - - public boolean isSorted() { - return sorted; - } - } - - /** - * HeaderCell that is header cell for row headers. - * - * Reordering disabled and clicking on it resets sorting. - */ - public class RowHeadersHeaderCell extends HeaderCell { - - RowHeadersHeaderCell() { - super(ROW_HEADER_COLUMN_KEY, ""); - this.setStyleName(CLASSNAME + "-header-cell-rowheader"); - } - - @Override - protected void handleCaptionEvent(Event event) { - // NOP: RowHeaders cannot be reordered - // TODO It'd be nice to reset sorting here - } - } - - public class TableHead extends Panel implements ActionOwner { - - private static final int WRAPPER_WIDTH = 900000; - - ArrayList<Widget> visibleCells = new ArrayList<Widget>(); - - HashMap<String, HeaderCell> availableCells = new HashMap<String, HeaderCell>(); - - Element div = DOM.createDiv(); - Element hTableWrapper = DOM.createDiv(); - Element hTableContainer = DOM.createDiv(); - Element table = DOM.createTable(); - Element headerTableBody = DOM.createTBody(); - Element tr = DOM.createTR(); - - private final Element columnSelector = DOM.createDiv(); - - private int focusedSlot = -1; - - public TableHead() { - if (BrowserInfo.get().isIE()) { - table.setPropertyInt("cellSpacing", 0); - } - - DOM.setStyleAttribute(hTableWrapper, "overflow", "hidden"); - DOM.setElementProperty(hTableWrapper, "className", CLASSNAME - + "-header"); - - // TODO move styles to CSS - DOM.setElementProperty(columnSelector, "className", CLASSNAME - + "-column-selector"); - DOM.setStyleAttribute(columnSelector, "display", "none"); - - DOM.appendChild(table, headerTableBody); - DOM.appendChild(headerTableBody, tr); - DOM.appendChild(hTableContainer, table); - DOM.appendChild(hTableWrapper, hTableContainer); - DOM.appendChild(div, hTableWrapper); - DOM.appendChild(div, columnSelector); - setElement(div); - - setStyleName(CLASSNAME + "-header-wrap"); - - DOM.sinkEvents(columnSelector, Event.ONCLICK); - - availableCells.put(ROW_HEADER_COLUMN_KEY, - new RowHeadersHeaderCell()); - } - - public void resizeCaptionContainer(HeaderCell cell) { - HeaderCell lastcell = getHeaderCell(visibleCells.size() - 1); - - // Measure column widths - int columnTotalWidth = 0; - for (Widget w : visibleCells) { - columnTotalWidth += w.getOffsetWidth(); - } - - if (cell == lastcell - && columnSelector.getOffsetWidth() > 0 - && columnTotalWidth >= div.getOffsetWidth() - - columnSelector.getOffsetWidth() - && !hasVerticalScrollbar()) { - // Ensure column caption is visible when placed under the column - // selector widget by shifting and resizing the caption. - int offset = 0; - int diff = div.getOffsetWidth() - columnTotalWidth; - if (diff < columnSelector.getOffsetWidth() && diff > 0) { - // If the difference is less than the column selectors width - // then just offset by the - // difference - offset = columnSelector.getOffsetWidth() - diff; - } else { - // Else offset by the whole column selector - offset = columnSelector.getOffsetWidth(); - } - lastcell.resizeCaptionContainer(offset); - } else { - cell.resizeCaptionContainer(0); - } - } - - @Override - public void clear() { - for (String cid : availableCells.keySet()) { - removeCell(cid); - } - availableCells.clear(); - availableCells.put(ROW_HEADER_COLUMN_KEY, - new RowHeadersHeaderCell()); - } - - public void updateCellsFromUIDL(UIDL uidl) { - Iterator<?> it = uidl.getChildIterator(); - HashSet<String> updated = new HashSet<String>(); - boolean refreshContentWidths = false; - while (it.hasNext()) { - final UIDL col = (UIDL) it.next(); - final String cid = col.getStringAttribute("cid"); - updated.add(cid); - - String caption = buildCaptionHtmlSnippet(col); - HeaderCell c = getHeaderCell(cid); - if (c == null) { - c = new HeaderCell(cid, caption); - availableCells.put(cid, c); - if (initializedAndAttached) { - // we will need a column width recalculation - initializedAndAttached = false; - initialContentReceived = false; - isNewBody = true; - } - } else { - c.setText(caption); - } - - if (col.hasAttribute("sortable")) { - c.setSortable(true); - if (cid.equals(sortColumn)) { - c.setSorted(true); - } else { - c.setSorted(false); - } - } else { - c.setSortable(false); - } - - if (col.hasAttribute("align")) { - c.setAlign(col.getStringAttribute("align").charAt(0)); - } else { - c.setAlign(ALIGN_LEFT); - - } - if (col.hasAttribute("width")) { - final String widthStr = col.getStringAttribute("width"); - // Make sure to accomodate for the sort indicator if - // necessary. - int width = Integer.parseInt(widthStr); - if (width < c.getMinWidth()) { - width = c.getMinWidth(); - } - if (width != c.getWidth() && scrollBody != null) { - // Do a more thorough update if a column is resized from - // the server *after* the header has been properly - // initialized - final int colIx = getColIndexByKey(c.cid); - final int newWidth = width; - Scheduler.get().scheduleDeferred( - new ScheduledCommand() { - - @Override - public void execute() { - setColWidth(colIx, newWidth, true); - } - }); - refreshContentWidths = true; - } else { - c.setWidth(width, true); - } - } else if (recalcWidths) { - c.setUndefinedWidth(); - } - if (col.hasAttribute("er")) { - c.setExpandRatio(col.getFloatAttribute("er")); - } - if (col.hasAttribute("collapsed")) { - // ensure header is properly removed from parent (case when - // collapsing happens via servers side api) - if (c.isAttached()) { - c.removeFromParent(); - headerChangedDuringUpdate = true; - } - } - } - - if (refreshContentWidths) { - // Recalculate the column sizings if any column has changed - Scheduler.get().scheduleDeferred(new ScheduledCommand() { - - @Override - public void execute() { - triggerLazyColumnAdjustment(true); - } - }); - } - - // check for orphaned header cells - for (Iterator<String> cit = availableCells.keySet().iterator(); cit - .hasNext();) { - String cid = cit.next(); - if (!updated.contains(cid)) { - removeCell(cid); - cit.remove(); - // we will need a column width recalculation, since columns - // with expand ratios should expand to fill the void. - initializedAndAttached = false; - initialContentReceived = false; - isNewBody = true; - } - } - } - - public void enableColumn(String cid, int index) { - final HeaderCell c = getHeaderCell(cid); - if (!c.isEnabled() || getHeaderCell(index) != c) { - setHeaderCell(index, c); - if (initializedAndAttached) { - headerChangedDuringUpdate = true; - } - } - } - - public int getVisibleCellCount() { - return visibleCells.size(); - } - - public void setHorizontalScrollPosition(int scrollLeft) { - hTableWrapper.setScrollLeft(scrollLeft); - } - - public void setColumnCollapsingAllowed(boolean cc) { - if (cc) { - columnSelector.getStyle().setDisplay(Display.BLOCK); - } else { - columnSelector.getStyle().setDisplay(Display.NONE); - } - } - - public void disableBrowserIntelligence() { - hTableContainer.getStyle().setWidth(WRAPPER_WIDTH, Unit.PX); - } - - public void enableBrowserIntelligence() { - hTableContainer.getStyle().clearWidth(); - } - - public void setHeaderCell(int index, HeaderCell cell) { - if (cell.isEnabled()) { - // we're moving the cell - DOM.removeChild(tr, cell.getElement()); - orphan(cell); - visibleCells.remove(cell); - } - if (index < visibleCells.size()) { - // insert to right slot - DOM.insertChild(tr, cell.getElement(), index); - adopt(cell); - visibleCells.add(index, cell); - } else if (index == visibleCells.size()) { - // simply append - DOM.appendChild(tr, cell.getElement()); - adopt(cell); - visibleCells.add(cell); - } else { - throw new RuntimeException( - "Header cells must be appended in order"); - } - } - - public HeaderCell getHeaderCell(int index) { - if (index >= 0 && index < visibleCells.size()) { - return (HeaderCell) visibleCells.get(index); - } else { - return null; - } - } - - /** - * Get's HeaderCell by it's column Key. - * - * Note that this returns HeaderCell even if it is currently collapsed. - * - * @param cid - * Column key of accessed HeaderCell - * @return HeaderCell - */ - public HeaderCell getHeaderCell(String cid) { - return availableCells.get(cid); - } - - public void moveCell(int oldIndex, int newIndex) { - final HeaderCell hCell = getHeaderCell(oldIndex); - final Element cell = hCell.getElement(); - - visibleCells.remove(oldIndex); - DOM.removeChild(tr, cell); - - DOM.insertChild(tr, cell, newIndex); - visibleCells.add(newIndex, hCell); - } - - @Override - public Iterator<Widget> iterator() { - return visibleCells.iterator(); - } - - @Override - public boolean remove(Widget w) { - if (visibleCells.contains(w)) { - visibleCells.remove(w); - orphan(w); - DOM.removeChild(DOM.getParent(w.getElement()), w.getElement()); - return true; - } - return false; - } - - public void removeCell(String colKey) { - final HeaderCell c = getHeaderCell(colKey); - remove(c); - } - - private void focusSlot(int index) { - removeSlotFocus(); - if (index > 0) { - DOM.setElementProperty( - DOM.getFirstChild(DOM.getChild(tr, index - 1)), - "className", CLASSNAME + "-resizer " + CLASSNAME - + "-focus-slot-right"); - } else { - DOM.setElementProperty( - DOM.getFirstChild(DOM.getChild(tr, index)), - "className", CLASSNAME + "-resizer " + CLASSNAME - + "-focus-slot-left"); - } - focusedSlot = index; - } - - private void removeSlotFocus() { - if (focusedSlot < 0) { - return; - } - if (focusedSlot == 0) { - DOM.setElementProperty( - DOM.getFirstChild(DOM.getChild(tr, focusedSlot)), - "className", CLASSNAME + "-resizer"); - } else if (focusedSlot > 0) { - DOM.setElementProperty( - DOM.getFirstChild(DOM.getChild(tr, focusedSlot - 1)), - "className", CLASSNAME + "-resizer"); - } - focusedSlot = -1; - } - - @Override - public void onBrowserEvent(Event event) { - if (enabled) { - if (event.getEventTarget().cast() == columnSelector) { - final int left = DOM.getAbsoluteLeft(columnSelector); - final int top = DOM.getAbsoluteTop(columnSelector) - + DOM.getElementPropertyInt(columnSelector, - "offsetHeight"); - client.getContextMenu().showAt(this, left, top); - } - } - } - - @Override - protected void onDetach() { - super.onDetach(); - if (client != null) { - client.getContextMenu().ensureHidden(this); - } - } - - class VisibleColumnAction extends Action { - - String colKey; - private boolean collapsed; - private boolean noncollapsible = false; - private VScrollTableRow currentlyFocusedRow; - - public VisibleColumnAction(String colKey) { - super(VScrollTable.TableHead.this); - this.colKey = colKey; - caption = tHead.getHeaderCell(colKey).getCaption(); - currentlyFocusedRow = focusedRow; - } - - @Override - public void execute() { - if (noncollapsible) { - return; - } - client.getContextMenu().hide(); - // toggle selected column - if (collapsedColumns.contains(colKey)) { - collapsedColumns.remove(colKey); - } else { - tHead.removeCell(colKey); - collapsedColumns.add(colKey); - triggerLazyColumnAdjustment(true); - } - - // update variable to server - client.updateVariable(paintableId, "collapsedcolumns", - collapsedColumns.toArray(new String[collapsedColumns - .size()]), false); - // let rowRequestHandler determine proper rows - rowRequestHandler.refreshContent(); - lazyRevertFocusToRow(currentlyFocusedRow); - } - - public void setCollapsed(boolean b) { - collapsed = b; - } - - public void setNoncollapsible(boolean b) { - noncollapsible = b; - } - - /** - * Override default method to distinguish on/off columns - */ - - @Override - public String getHTML() { - final StringBuffer buf = new StringBuffer(); - buf.append("<span class=\""); - if (collapsed) { - buf.append("v-off"); - } else { - buf.append("v-on"); - } - if (noncollapsible) { - buf.append(" v-disabled"); - } - buf.append("\">"); - - buf.append(super.getHTML()); - buf.append("</span>"); - - return buf.toString(); - } - - } - - /* - * Returns columns as Action array for column select popup - */ - - @Override - public Action[] getActions() { - Object[] cols; - if (columnReordering && columnOrder != null) { - cols = columnOrder; - } else { - // if columnReordering is disabled, we need different way to get - // all available columns - cols = visibleColOrder; - cols = new Object[visibleColOrder.length - + collapsedColumns.size()]; - int i; - for (i = 0; i < visibleColOrder.length; i++) { - cols[i] = visibleColOrder[i]; - } - for (final Iterator<String> it = collapsedColumns.iterator(); it - .hasNext();) { - cols[i++] = it.next(); - } - } - final Action[] actions = new Action[cols.length]; - - for (int i = 0; i < cols.length; i++) { - final String cid = (String) cols[i]; - final HeaderCell c = getHeaderCell(cid); - final VisibleColumnAction a = new VisibleColumnAction( - c.getColKey()); - a.setCaption(c.getCaption()); - if (!c.isEnabled()) { - a.setCollapsed(true); - } - if (noncollapsibleColumns.contains(cid)) { - a.setNoncollapsible(true); - } - actions[i] = a; - } - return actions; - } - - @Override - public ApplicationConnection getClient() { - return client; - } - - @Override - public String getPaintableId() { - return paintableId; - } - - /** - * Returns column alignments for visible columns - */ - public char[] getColumnAlignments() { - final Iterator<Widget> it = visibleCells.iterator(); - final char[] aligns = new char[visibleCells.size()]; - int colIndex = 0; - while (it.hasNext()) { - aligns[colIndex++] = ((HeaderCell) it.next()).getAlign(); - } - return aligns; - } - - /** - * Disables the automatic calculation of all column widths by forcing - * the widths to be "defined" thus turning off expand ratios and such. - */ - public void disableAutoColumnWidthCalculation(HeaderCell source) { - for (HeaderCell cell : availableCells.values()) { - cell.disableAutoWidthCalculation(); - } - // fire column resize events for all columns but the source of the - // resize action, since an event will fire separately for this. - ArrayList<HeaderCell> columns = new ArrayList<HeaderCell>( - availableCells.values()); - columns.remove(source); - sendColumnWidthUpdates(columns); - forceRealignColumnHeaders(); - } - } - - /** - * A cell in the footer - */ - public class FooterCell extends Widget { - private final Element td = DOM.createTD(); - private final Element captionContainer = DOM.createDiv(); - private char align = ALIGN_LEFT; - private int width = -1; - private float expandRatio = 0; - private final String cid; - boolean definedWidth = false; - private int naturalWidth = -1; - - public FooterCell(String colId, String headerText) { - cid = colId; - - setText(headerText); - - DOM.setElementProperty(captionContainer, "className", CLASSNAME - + "-footer-container"); - - // ensure no clipping initially (problem on column additions) - DOM.setStyleAttribute(captionContainer, "overflow", "visible"); - - DOM.sinkEvents(captionContainer, Event.MOUSEEVENTS); - - DOM.appendChild(td, captionContainer); - - DOM.sinkEvents(td, Event.MOUSEEVENTS | Event.ONDBLCLICK - | Event.ONCONTEXTMENU); - - setElement(td); - } - - /** - * Sets the text of the footer - * - * @param footerText - * The text in the footer - */ - public void setText(String footerText) { - if (footerText == null || footerText.equals("")) { - footerText = " "; - } - - DOM.setInnerHTML(captionContainer, footerText); - } - - /** - * Set alignment of the text in the cell - * - * @param c - * The alignment which can be ALIGN_CENTER, ALIGN_LEFT, - * ALIGN_RIGHT - */ - public void setAlign(char c) { - if (align != c) { - switch (c) { - case ALIGN_CENTER: - DOM.setStyleAttribute(captionContainer, "textAlign", - "center"); - break; - case ALIGN_RIGHT: - DOM.setStyleAttribute(captionContainer, "textAlign", - "right"); - break; - default: - DOM.setStyleAttribute(captionContainer, "textAlign", ""); - break; - } - } - align = c; - } - - /** - * Get the alignment of the text int the cell - * - * @return Returns either ALIGN_CENTER, ALIGN_LEFT or ALIGN_RIGHT - */ - public char getAlign() { - return align; - } - - /** - * Sets the width of the cell - * - * @param w - * The width of the cell - * @param ensureDefinedWidth - * Ensures the the given width is not recalculated - */ - public void setWidth(int w, boolean ensureDefinedWidth) { - - if (ensureDefinedWidth) { - definedWidth = true; - // on column resize expand ratio becomes zero - expandRatio = 0; - } - if (width == w) { - return; - } - if (width == -1) { - // go to default mode, clip content if necessary - DOM.setStyleAttribute(captionContainer, "overflow", ""); - } - width = w; - if (w == -1) { - DOM.setStyleAttribute(captionContainer, "width", ""); - setWidth(""); - } else { - /* - * Reduce width with one pixel for the right border since the - * footers does not have any spacers between them. - */ - final int borderWidths = 1; - - // Set the container width (check for negative value) - captionContainer.getStyle().setPropertyPx("width", - Math.max(w - borderWidths, 0)); - - /* - * if we already have tBody, set the header width properly, if - * not defer it. IE will fail with complex float in table header - * unless TD width is not explicitly set. - */ - if (scrollBody != null) { - int tdWidth = width + scrollBody.getCellExtraWidth() - - borderWidths; - setWidth(Math.max(tdWidth, 0) + "px"); - } else { - Scheduler.get().scheduleDeferred(new Command() { - - @Override - public void execute() { - int tdWidth = width - + scrollBody.getCellExtraWidth() - - borderWidths; - setWidth(Math.max(tdWidth, 0) + "px"); - } - }); - } - } - } - - /** - * Sets the width to undefined - */ - public void setUndefinedWidth() { - setWidth(-1, false); - } - - /** - * Detects if width is fixed by developer on server side or resized to - * current width by user. - * - * @return true if defined, false if "natural" width - */ - public boolean isDefinedWidth() { - return definedWidth && width >= 0; - } - - /** - * Returns the pixels width of the footer cell - * - * @return The width in pixels - */ - public int getWidth() { - return width; - } - - /** - * Sets the expand ratio of the cell - * - * @param floatAttribute - * The expand ratio - */ - public void setExpandRatio(float floatAttribute) { - expandRatio = floatAttribute; - } - - /** - * Returns the expand ration of the cell - * - * @return The expand ratio - */ - public float getExpandRatio() { - return expandRatio; - } - - /** - * Is the cell enabled? - * - * @return True if enabled else False - */ - public boolean isEnabled() { - return getParent() != null; - } - - /** - * Handle column clicking - */ - - @Override - public void onBrowserEvent(Event event) { - if (enabled && event != null) { - handleCaptionEvent(event); - - if (DOM.eventGetType(event) == Event.ONMOUSEUP) { - scrollBodyPanel.setFocus(true); - } - boolean stopPropagation = true; - if (event.getTypeInt() == Event.ONCONTEXTMENU - && !client.hasEventListeners(VScrollTable.this, - TableConstants.FOOTER_CLICK_EVENT_ID)) { - // Show browser context menu if a footer click listener is - // not present - stopPropagation = false; - } - if (stopPropagation) { - event.stopPropagation(); - event.preventDefault(); - } - } - } - - /** - * Handles a event on the captions - * - * @param event - * The event to handle - */ - protected void handleCaptionEvent(Event event) { - if (event.getTypeInt() == Event.ONMOUSEUP - || event.getTypeInt() == Event.ONDBLCLICK) { - fireFooterClickedEvent(event); - } - } - - /** - * Fires a footer click event after the user has clicked a column footer - * cell - * - * @param event - * The click event - */ - private void fireFooterClickedEvent(Event event) { - if (client.hasEventListeners(VScrollTable.this, - TableConstants.FOOTER_CLICK_EVENT_ID)) { - MouseEventDetails details = MouseEventDetailsBuilder - .buildMouseEventDetails(event); - client.updateVariable(paintableId, "footerClickEvent", - details.toString(), false); - client.updateVariable(paintableId, "footerClickCID", cid, true); - } - } - - /** - * Returns the column key of the column - * - * @return The column key - */ - public String getColKey() { - return cid; - } - - /** - * Detects the natural minimum width for the column of this header cell. - * If column is resized by user or the width is defined by server the - * actual width is returned. Else the natural min width is returned. - * - * @param columnIndex - * column index hint, if -1 (unknown) it will be detected - * - * @return - */ - public int getNaturalColumnWidth(int columnIndex) { - if (isDefinedWidth()) { - return width; - } else { - if (naturalWidth < 0) { - // This is recently revealed column. Try to detect a proper - // value (greater of header and data - // cols) - - final int hw = ((Element) getElement().getLastChild()) - .getOffsetWidth() + scrollBody.getCellExtraWidth(); - if (columnIndex < 0) { - columnIndex = 0; - for (Iterator<Widget> it = tHead.iterator(); it - .hasNext(); columnIndex++) { - if (it.next() == this) { - break; - } - } - } - final int cw = scrollBody.getColWidth(columnIndex); - naturalWidth = (hw > cw ? hw : cw); - } - return naturalWidth; - } - } - - public void setNaturalMinimumColumnWidth(int w) { - naturalWidth = w; - } - } - - /** - * HeaderCell that is header cell for row headers. - * - * Reordering disabled and clicking on it resets sorting. - */ - public class RowHeadersFooterCell extends FooterCell { - - RowHeadersFooterCell() { - super(ROW_HEADER_COLUMN_KEY, ""); - } - - @Override - protected void handleCaptionEvent(Event event) { - // NOP: RowHeaders cannot be reordered - // TODO It'd be nice to reset sorting here - } - } - - /** - * The footer of the table which can be seen in the bottom of the Table. - */ - public class TableFooter extends Panel { - - private static final int WRAPPER_WIDTH = 900000; - - ArrayList<Widget> visibleCells = new ArrayList<Widget>(); - HashMap<String, FooterCell> availableCells = new HashMap<String, FooterCell>(); - - Element div = DOM.createDiv(); - Element hTableWrapper = DOM.createDiv(); - Element hTableContainer = DOM.createDiv(); - Element table = DOM.createTable(); - Element headerTableBody = DOM.createTBody(); - Element tr = DOM.createTR(); - - public TableFooter() { - - DOM.setStyleAttribute(hTableWrapper, "overflow", "hidden"); - DOM.setElementProperty(hTableWrapper, "className", CLASSNAME - + "-footer"); - - DOM.appendChild(table, headerTableBody); - DOM.appendChild(headerTableBody, tr); - DOM.appendChild(hTableContainer, table); - DOM.appendChild(hTableWrapper, hTableContainer); - DOM.appendChild(div, hTableWrapper); - setElement(div); - - setStyleName(CLASSNAME + "-footer-wrap"); - - availableCells.put(ROW_HEADER_COLUMN_KEY, - new RowHeadersFooterCell()); - } - - @Override - public void clear() { - for (String cid : availableCells.keySet()) { - removeCell(cid); - } - availableCells.clear(); - availableCells.put(ROW_HEADER_COLUMN_KEY, - new RowHeadersFooterCell()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.user.client.ui.Panel#remove(com.google.gwt.user.client - * .ui.Widget) - */ - - @Override - public boolean remove(Widget w) { - if (visibleCells.contains(w)) { - visibleCells.remove(w); - orphan(w); - DOM.removeChild(DOM.getParent(w.getElement()), w.getElement()); - return true; - } - return false; - } - - /* - * (non-Javadoc) - * - * @see com.google.gwt.user.client.ui.HasWidgets#iterator() - */ - - @Override - public Iterator<Widget> iterator() { - return visibleCells.iterator(); - } - - /** - * Gets a footer cell which represents the given columnId - * - * @param cid - * The columnId - * - * @return The cell - */ - public FooterCell getFooterCell(String cid) { - return availableCells.get(cid); - } - - /** - * Gets a footer cell by using a column index - * - * @param index - * The index of the column - * @return The Cell - */ - public FooterCell getFooterCell(int index) { - if (index < visibleCells.size()) { - return (FooterCell) visibleCells.get(index); - } else { - return null; - } - } - - /** - * Updates the cells contents when updateUIDL request is received - * - * @param uidl - * The UIDL - */ - public void updateCellsFromUIDL(UIDL uidl) { - Iterator<?> columnIterator = uidl.getChildIterator(); - HashSet<String> updated = new HashSet<String>(); - while (columnIterator.hasNext()) { - final UIDL col = (UIDL) columnIterator.next(); - final String cid = col.getStringAttribute("cid"); - updated.add(cid); - - String caption = col.hasAttribute("fcaption") ? col - .getStringAttribute("fcaption") : ""; - FooterCell c = getFooterCell(cid); - if (c == null) { - c = new FooterCell(cid, caption); - availableCells.put(cid, c); - if (initializedAndAttached) { - // we will need a column width recalculation - initializedAndAttached = false; - initialContentReceived = false; - isNewBody = true; - } - } else { - c.setText(caption); - } - - if (col.hasAttribute("align")) { - c.setAlign(col.getStringAttribute("align").charAt(0)); - } else { - c.setAlign(ALIGN_LEFT); - - } - if (col.hasAttribute("width")) { - if (scrollBody == null) { - // Already updated by setColWidth called from - // TableHeads.updateCellsFromUIDL in case of a server - // side resize - final String width = col.getStringAttribute("width"); - c.setWidth(Integer.parseInt(width), true); - } - } else if (recalcWidths) { - c.setUndefinedWidth(); - } - if (col.hasAttribute("er")) { - c.setExpandRatio(col.getFloatAttribute("er")); - } - if (col.hasAttribute("collapsed")) { - // ensure header is properly removed from parent (case when - // collapsing happens via servers side api) - if (c.isAttached()) { - c.removeFromParent(); - headerChangedDuringUpdate = true; - } - } - } - - // check for orphaned header cells - for (Iterator<String> cit = availableCells.keySet().iterator(); cit - .hasNext();) { - String cid = cit.next(); - if (!updated.contains(cid)) { - removeCell(cid); - cit.remove(); - } - } - } - - /** - * Set a footer cell for a specified column index - * - * @param index - * The index - * @param cell - * The footer cell - */ - public void setFooterCell(int index, FooterCell cell) { - if (cell.isEnabled()) { - // we're moving the cell - DOM.removeChild(tr, cell.getElement()); - orphan(cell); - visibleCells.remove(cell); - } - if (index < visibleCells.size()) { - // insert to right slot - DOM.insertChild(tr, cell.getElement(), index); - adopt(cell); - visibleCells.add(index, cell); - } else if (index == visibleCells.size()) { - // simply append - DOM.appendChild(tr, cell.getElement()); - adopt(cell); - visibleCells.add(cell); - } else { - throw new RuntimeException( - "Header cells must be appended in order"); - } - } - - /** - * Remove a cell by using the columnId - * - * @param colKey - * The columnId to remove - */ - public void removeCell(String colKey) { - final FooterCell c = getFooterCell(colKey); - remove(c); - } - - /** - * Enable a column (Sets the footer cell) - * - * @param cid - * The columnId - * @param index - * The index of the column - */ - public void enableColumn(String cid, int index) { - final FooterCell c = getFooterCell(cid); - if (!c.isEnabled() || getFooterCell(index) != c) { - setFooterCell(index, c); - if (initializedAndAttached) { - headerChangedDuringUpdate = true; - } - } - } - - /** - * Disable browser measurement of the table width - */ - public void disableBrowserIntelligence() { - DOM.setStyleAttribute(hTableContainer, "width", WRAPPER_WIDTH - + "px"); - } - - /** - * Enable browser measurement of the table width - */ - public void enableBrowserIntelligence() { - DOM.setStyleAttribute(hTableContainer, "width", ""); - } - - /** - * Set the horizontal position in the cell in the footer. This is done - * when a horizontal scrollbar is present. - * - * @param scrollLeft - * The value of the leftScroll - */ - public void setHorizontalScrollPosition(int scrollLeft) { - hTableWrapper.setScrollLeft(scrollLeft); - } - - /** - * Swap cells when the column are dragged - * - * @param oldIndex - * The old index of the cell - * @param newIndex - * The new index of the cell - */ - public void moveCell(int oldIndex, int newIndex) { - final FooterCell hCell = getFooterCell(oldIndex); - final Element cell = hCell.getElement(); - - visibleCells.remove(oldIndex); - DOM.removeChild(tr, cell); - - DOM.insertChild(tr, cell, newIndex); - visibleCells.add(newIndex, hCell); - } - } - - /** - * This Panel can only contain VScrollTableRow type of widgets. This - * "simulates" very large table, keeping spacers which take room of - * unrendered rows. - * - */ - public class VScrollTableBody extends Panel { - - public static final int DEFAULT_ROW_HEIGHT = 24; - - private double rowHeight = -1; - - private final LinkedList<Widget> renderedRows = new LinkedList<Widget>(); - - /** - * Due some optimizations row height measuring is deferred and initial - * set of rows is rendered detached. Flag set on when table body has - * been attached in dom and rowheight has been measured. - */ - private boolean tBodyMeasurementsDone = false; - - Element preSpacer = DOM.createDiv(); - Element postSpacer = DOM.createDiv(); - - Element container = DOM.createDiv(); - - TableSectionElement tBodyElement = Document.get().createTBodyElement(); - Element table = DOM.createTable(); - - private int firstRendered; - private int lastRendered; - - private char[] aligns; - - protected VScrollTableBody() { - constructDOM(); - setElement(container); - } - - public VScrollTableRow getRowByRowIndex(int indexInTable) { - int internalIndex = indexInTable - firstRendered; - if (internalIndex >= 0 && internalIndex < renderedRows.size()) { - return (VScrollTableRow) renderedRows.get(internalIndex); - } else { - return null; - } - } - - /** - * @return the height of scrollable body, subpixels ceiled. - */ - public int getRequiredHeight() { - return preSpacer.getOffsetHeight() + postSpacer.getOffsetHeight() - + Util.getRequiredHeight(table); - } - - private void constructDOM() { - DOM.setElementProperty(table, "className", CLASSNAME + "-table"); - if (BrowserInfo.get().isIE()) { - table.setPropertyInt("cellSpacing", 0); - } - DOM.setElementProperty(preSpacer, "className", CLASSNAME - + "-row-spacer"); - DOM.setElementProperty(postSpacer, "className", CLASSNAME - + "-row-spacer"); - - table.appendChild(tBodyElement); - DOM.appendChild(container, preSpacer); - DOM.appendChild(container, table); - DOM.appendChild(container, postSpacer); - if (BrowserInfo.get().requiresTouchScrollDelegate()) { - NodeList<Node> childNodes = container.getChildNodes(); - for (int i = 0; i < childNodes.getLength(); i++) { - Element item = (Element) childNodes.getItem(i); - item.getStyle().setProperty("webkitTransform", - "translate3d(0,0,0)"); - } - } - - } - - public int getAvailableWidth() { - int availW = scrollBodyPanel.getOffsetWidth() - getBorderWidth(); - return availW; - } - - public void renderInitialRows(UIDL rowData, int firstIndex, int rows) { - firstRendered = firstIndex; - lastRendered = firstIndex + rows - 1; - final Iterator<?> it = rowData.getChildIterator(); - aligns = tHead.getColumnAlignments(); - while (it.hasNext()) { - final VScrollTableRow row = createRow((UIDL) it.next(), aligns); - addRow(row); - } - if (isAttached()) { - fixSpacers(); - } - } - - public void renderRows(UIDL rowData, int firstIndex, int rows) { - // FIXME REVIEW - aligns = tHead.getColumnAlignments(); - final Iterator<?> it = rowData.getChildIterator(); - if (firstIndex == lastRendered + 1) { - while (it.hasNext()) { - final VScrollTableRow row = prepareRow((UIDL) it.next()); - addRow(row); - lastRendered++; - } - fixSpacers(); - } else if (firstIndex + rows == firstRendered) { - final VScrollTableRow[] rowArray = new VScrollTableRow[rows]; - int i = rows; - while (it.hasNext()) { - i--; - rowArray[i] = prepareRow((UIDL) it.next()); - } - for (i = 0; i < rows; i++) { - addRowBeforeFirstRendered(rowArray[i]); - firstRendered--; - } - } else { - // completely new set of rows - while (lastRendered + 1 > firstRendered) { - unlinkRow(false); - } - final VScrollTableRow row = prepareRow((UIDL) it.next()); - firstRendered = firstIndex; - lastRendered = firstIndex - 1; - addRow(row); - lastRendered++; - setContainerHeight(); - fixSpacers(); - while (it.hasNext()) { - addRow(prepareRow((UIDL) it.next())); - lastRendered++; - } - fixSpacers(); - } - - // this may be a new set of rows due content change, - // ensure we have proper cache rows - ensureCacheFilled(); - } - - /** - * Ensure we have the correct set of rows on client side, e.g. if the - * content on the server side has changed, or the client scroll position - * has changed since the last request. - */ - protected void ensureCacheFilled() { - int reactFirstRow = (int) (firstRowInViewPort - pageLength - * cache_react_rate); - int reactLastRow = (int) (firstRowInViewPort + pageLength + pageLength - * cache_react_rate); - if (reactFirstRow < 0) { - reactFirstRow = 0; - } - if (reactLastRow >= totalRows) { - reactLastRow = totalRows - 1; - } - if (lastRendered < reactFirstRow || firstRendered > reactLastRow) { - /* - * #8040 - scroll position is completely changed since the - * latest request, so request a new set of rows. - * - * TODO: We should probably check whether the fetched rows match - * the current scroll position right when they arrive, so as to - * not waste time rendering a set of rows that will never be - * visible... - */ - rowRequestHandler.setReqFirstRow(reactFirstRow); - rowRequestHandler.setReqRows(reactLastRow - reactFirstRow + 1); - rowRequestHandler.deferRowFetch(1); - } else if (lastRendered < reactLastRow) { - // get some cache rows below visible area - rowRequestHandler.setReqFirstRow(lastRendered + 1); - rowRequestHandler.setReqRows(reactLastRow - lastRendered); - rowRequestHandler.deferRowFetch(1); - } else if (firstRendered > reactFirstRow) { - /* - * Branch for fetching cache above visible area. - * - * If cache needed for both before and after visible area, this - * will be rendered after-cache is received and rendered. So in - * some rare situations the table may make two cache visits to - * server. - */ - rowRequestHandler.setReqFirstRow(reactFirstRow); - rowRequestHandler.setReqRows(firstRendered - reactFirstRow); - rowRequestHandler.deferRowFetch(1); - } - } - - /** - * Inserts rows as provided in the rowData starting at firstIndex. - * - * @param rowData - * @param firstIndex - * @param rows - * the number of rows - * @return a list of the rows added. - */ - protected List<VScrollTableRow> insertRows(UIDL rowData, - int firstIndex, int rows) { - aligns = tHead.getColumnAlignments(); - final Iterator<?> it = rowData.getChildIterator(); - List<VScrollTableRow> insertedRows = new ArrayList<VScrollTableRow>(); - - if (firstIndex == lastRendered + 1) { - while (it.hasNext()) { - final VScrollTableRow row = prepareRow((UIDL) it.next()); - addRow(row); - insertedRows.add(row); - lastRendered++; - } - fixSpacers(); - } else if (firstIndex + rows == firstRendered) { - final VScrollTableRow[] rowArray = new VScrollTableRow[rows]; - int i = rows; - while (it.hasNext()) { - i--; - rowArray[i] = prepareRow((UIDL) it.next()); - } - for (i = 0; i < rows; i++) { - addRowBeforeFirstRendered(rowArray[i]); - insertedRows.add(rowArray[i]); - firstRendered--; - } - } else { - // insert in the middle - int ix = firstIndex; - while (it.hasNext()) { - VScrollTableRow row = prepareRow((UIDL) it.next()); - insertRowAt(row, ix); - insertedRows.add(row); - lastRendered++; - ix++; - } - fixSpacers(); - } - return insertedRows; - } - - protected List<VScrollTableRow> insertAndReindexRows(UIDL rowData, - int firstIndex, int rows) { - List<VScrollTableRow> inserted = insertRows(rowData, firstIndex, - rows); - int actualIxOfFirstRowAfterInserted = firstIndex + rows - - firstRendered; - for (int ix = actualIxOfFirstRowAfterInserted; ix < renderedRows - .size(); ix++) { - VScrollTableRow r = (VScrollTableRow) renderedRows.get(ix); - r.setIndex(r.getIndex() + rows); - } - setContainerHeight(); - return inserted; - } - - protected void insertRowsDeleteBelow(UIDL rowData, int firstIndex, - int rows) { - unlinkAllRowsStartingAt(firstIndex); - insertRows(rowData, firstIndex, rows); - setContainerHeight(); - } - - /** - * This method is used to instantiate new rows for this table. It - * automatically sets correct widths to rows cells and assigns correct - * client reference for child widgets. - * - * This method can be called only after table has been initialized - * - * @param uidl - */ - private VScrollTableRow prepareRow(UIDL uidl) { - final VScrollTableRow row = createRow(uidl, aligns); - row.initCellWidths(); - return row; - } - - protected VScrollTableRow createRow(UIDL uidl, char[] aligns2) { - if (uidl.hasAttribute("gen_html")) { - // This is a generated row. - return new VScrollTableGeneratedRow(uidl, aligns2); - } - return new VScrollTableRow(uidl, aligns2); - } - - private void addRowBeforeFirstRendered(VScrollTableRow row) { - row.setIndex(firstRendered - 1); - if (row.isSelected()) { - row.addStyleName("v-selected"); - } - tBodyElement.insertBefore(row.getElement(), - tBodyElement.getFirstChild()); - adopt(row); - renderedRows.add(0, row); - } - - private void addRow(VScrollTableRow row) { - row.setIndex(firstRendered + renderedRows.size()); - if (row.isSelected()) { - row.addStyleName("v-selected"); - } - tBodyElement.appendChild(row.getElement()); - // Add to renderedRows before adopt so iterator() will return also - // this row if called in an attach handler (#9264) - renderedRows.add(row); - adopt(row); - } - - private void insertRowAt(VScrollTableRow row, int index) { - row.setIndex(index); - if (row.isSelected()) { - row.addStyleName("v-selected"); - } - if (index > 0) { - VScrollTableRow sibling = getRowByRowIndex(index - 1); - tBodyElement - .insertAfter(row.getElement(), sibling.getElement()); - } else { - VScrollTableRow sibling = getRowByRowIndex(index); - tBodyElement.insertBefore(row.getElement(), - sibling.getElement()); - } - adopt(row); - int actualIx = index - firstRendered; - renderedRows.add(actualIx, row); - } - - @Override - public Iterator<Widget> iterator() { - return renderedRows.iterator(); - } - - /** - * @return false if couldn't remove row - */ - protected boolean unlinkRow(boolean fromBeginning) { - if (lastRendered - firstRendered < 0) { - return false; - } - int actualIx; - if (fromBeginning) { - actualIx = 0; - firstRendered++; - } else { - actualIx = renderedRows.size() - 1; - lastRendered--; - } - if (actualIx >= 0) { - unlinkRowAtActualIndex(actualIx); - fixSpacers(); - return true; - } - return false; - } - - protected void unlinkRows(int firstIndex, int count) { - if (count < 1) { - return; - } - if (firstRendered > firstIndex - && firstRendered < firstIndex + count) { - firstIndex = firstRendered; - } - int lastIndex = firstIndex + count - 1; - if (lastRendered < lastIndex) { - lastIndex = lastRendered; - } - for (int ix = lastIndex; ix >= firstIndex; ix--) { - unlinkRowAtActualIndex(actualIndex(ix)); - lastRendered--; - } - fixSpacers(); - } - - protected void unlinkAndReindexRows(int firstIndex, int count) { - unlinkRows(firstIndex, count); - int actualFirstIx = firstIndex - firstRendered; - for (int ix = actualFirstIx; ix < renderedRows.size(); ix++) { - VScrollTableRow r = (VScrollTableRow) renderedRows.get(ix); - r.setIndex(r.getIndex() - count); - } - setContainerHeight(); - } - - protected void unlinkAllRowsStartingAt(int index) { - if (firstRendered > index) { - index = firstRendered; - } - for (int ix = renderedRows.size() - 1; ix >= index; ix--) { - unlinkRowAtActualIndex(actualIndex(ix)); - lastRendered--; - } - fixSpacers(); - } - - private int actualIndex(int index) { - return index - firstRendered; - } - - private void unlinkRowAtActualIndex(int index) { - final VScrollTableRow toBeRemoved = (VScrollTableRow) renderedRows - .get(index); - tBodyElement.removeChild(toBeRemoved.getElement()); - orphan(toBeRemoved); - renderedRows.remove(index); - } - - @Override - public boolean remove(Widget w) { - throw new UnsupportedOperationException(); - } - - /** - * Fix container blocks height according to totalRows to avoid - * "bouncing" when scrolling - */ - private void setContainerHeight() { - fixSpacers(); - DOM.setStyleAttribute(container, "height", - measureRowHeightOffset(totalRows) + "px"); - } - - private void fixSpacers() { - int prepx = measureRowHeightOffset(firstRendered); - if (prepx < 0) { - prepx = 0; - } - preSpacer.getStyle().setPropertyPx("height", prepx); - int postpx = measureRowHeightOffset(totalRows - 1) - - measureRowHeightOffset(lastRendered); - if (postpx < 0) { - postpx = 0; - } - postSpacer.getStyle().setPropertyPx("height", postpx); - } - - public double getRowHeight() { - return getRowHeight(false); - } - - public double getRowHeight(boolean forceUpdate) { - if (tBodyMeasurementsDone && !forceUpdate) { - return rowHeight; - } else { - if (tBodyElement.getRows().getLength() > 0) { - int tableHeight = getTableHeight(); - int rowCount = tBodyElement.getRows().getLength(); - rowHeight = tableHeight / (double) rowCount; - } else { - // Special cases if we can't just measure the current rows - if (!Double.isNaN(lastKnownRowHeight)) { - // Use previous value if available - if (BrowserInfo.get().isIE()) { - /* - * IE needs to reflow the table element at this - * point to work correctly (e.g. - * com.vaadin.tests.components.table. - * ContainerSizeChange) - the other code paths - * already trigger reflows, but here it must be done - * explicitly. - */ - getTableHeight(); - } - rowHeight = lastKnownRowHeight; - } else if (isAttached()) { - // measure row height by adding a dummy row - VScrollTableRow scrollTableRow = new VScrollTableRow(); - tBodyElement.appendChild(scrollTableRow.getElement()); - getRowHeight(forceUpdate); - tBodyElement.removeChild(scrollTableRow.getElement()); - } else { - // TODO investigate if this can never happen anymore - return DEFAULT_ROW_HEIGHT; - } - } - lastKnownRowHeight = rowHeight; - tBodyMeasurementsDone = true; - return rowHeight; - } - } - - public int getTableHeight() { - return table.getOffsetHeight(); - } - - /** - * Returns the width available for column content. - * - * @param columnIndex - * @return - */ - public int getColWidth(int columnIndex) { - if (tBodyMeasurementsDone) { - if (renderedRows.isEmpty()) { - // no rows yet rendered - return 0; - } - for (Widget row : renderedRows) { - if (!(row instanceof VScrollTableGeneratedRow)) { - TableRowElement tr = row.getElement().cast(); - Element wrapperdiv = tr.getCells().getItem(columnIndex) - .getFirstChildElement().cast(); - return wrapperdiv.getOffsetWidth(); - } - } - return 0; - } else { - return 0; - } - } - - /** - * Sets the content width of a column. - * - * Due IE limitation, we must set the width to a wrapper elements inside - * table cells (with overflow hidden, which does not work on td - * elements). - * - * To get this work properly crossplatform, we will also set the width - * of td. - * - * @param colIndex - * @param w - */ - public void setColWidth(int colIndex, int w) { - for (Widget row : renderedRows) { - ((VScrollTableRow) row).setCellWidth(colIndex, w); - } - } - - private int cellExtraWidth = -1; - - /** - * Method to return the space used for cell paddings + border. - */ - private int getCellExtraWidth() { - if (cellExtraWidth < 0) { - detectExtrawidth(); - } - return cellExtraWidth; - } - - private void detectExtrawidth() { - NodeList<TableRowElement> rows = tBodyElement.getRows(); - if (rows.getLength() == 0) { - /* need to temporary add empty row and detect */ - VScrollTableRow scrollTableRow = new VScrollTableRow(); - tBodyElement.appendChild(scrollTableRow.getElement()); - detectExtrawidth(); - tBodyElement.removeChild(scrollTableRow.getElement()); - } else { - boolean noCells = false; - TableRowElement item = rows.getItem(0); - TableCellElement firstTD = item.getCells().getItem(0); - if (firstTD == null) { - // content is currently empty, we need to add a fake cell - // for measuring - noCells = true; - VScrollTableRow next = (VScrollTableRow) iterator().next(); - boolean sorted = tHead.getHeaderCell(0) != null ? tHead - .getHeaderCell(0).isSorted() : false; - next.addCell(null, "", ALIGN_LEFT, "", true, sorted); - firstTD = item.getCells().getItem(0); - } - com.google.gwt.dom.client.Element wrapper = firstTD - .getFirstChildElement(); - cellExtraWidth = firstTD.getOffsetWidth() - - wrapper.getOffsetWidth(); - if (noCells) { - firstTD.getParentElement().removeChild(firstTD); - } - } - } - - private void reLayoutComponents() { - for (Widget w : this) { - VScrollTableRow r = (VScrollTableRow) w; - for (Widget widget : r) { - client.handleComponentRelativeSize(widget); - } - } - } - - public int getLastRendered() { - return lastRendered; - } - - public int getFirstRendered() { - return firstRendered; - } - - public void moveCol(int oldIndex, int newIndex) { - - // loop all rows and move given index to its new place - final Iterator<?> rows = iterator(); - while (rows.hasNext()) { - final VScrollTableRow row = (VScrollTableRow) rows.next(); - - final Element td = DOM.getChild(row.getElement(), oldIndex); - if (td != null) { - DOM.removeChild(row.getElement(), td); - - DOM.insertChild(row.getElement(), td, newIndex); - } - } - - } - - /** - * Restore row visibility which is set to "none" when the row is - * rendered (due a performance optimization). - */ - private void restoreRowVisibility() { - for (Widget row : renderedRows) { - row.getElement().getStyle().setProperty("visibility", ""); - } - } - - public class VScrollTableRow extends Panel implements ActionOwner { - - private static final int TOUCHSCROLL_TIMEOUT = 100; - private static final int DRAGMODE_MULTIROW = 2; - protected ArrayList<Widget> childWidgets = new ArrayList<Widget>(); - private boolean selected = false; - protected final int rowKey; - - private String[] actionKeys = null; - private final TableRowElement rowElement; - private int index; - private Event touchStart; - private static final String ROW_CLASSNAME_EVEN = CLASSNAME + "-row"; - private static final String ROW_CLASSNAME_ODD = CLASSNAME - + "-row-odd"; - private static final int TOUCH_CONTEXT_MENU_TIMEOUT = 500; - private Timer contextTouchTimeout; - private Timer dragTouchTimeout; - private int touchStartY; - private int touchStartX; - private TooltipInfo tooltipInfo = null; - private Map<TableCellElement, TooltipInfo> cellToolTips = new HashMap<TableCellElement, TooltipInfo>(); - private boolean isDragging = false; - - private VScrollTableRow(int rowKey) { - this.rowKey = rowKey; - rowElement = Document.get().createTRElement(); - setElement(rowElement); - DOM.sinkEvents(getElement(), Event.MOUSEEVENTS - | Event.TOUCHEVENTS | Event.ONDBLCLICK - | Event.ONCONTEXTMENU | VTooltip.TOOLTIP_EVENTS); - } - - public VScrollTableRow(UIDL uidl, char[] aligns) { - this(uidl.getIntAttribute("key")); - - /* - * Rendering the rows as hidden improves Firefox and Safari - * performance drastically. - */ - getElement().getStyle().setProperty("visibility", "hidden"); - - String rowStyle = uidl.getStringAttribute("rowstyle"); - if (rowStyle != null) { - addStyleName(CLASSNAME + "-row-" + rowStyle); - } - - String rowDescription = uidl.getStringAttribute("rowdescr"); - if (rowDescription != null && !rowDescription.equals("")) { - tooltipInfo = new TooltipInfo(rowDescription); - } else { - tooltipInfo = null; - } - - tHead.getColumnAlignments(); - int col = 0; - int visibleColumnIndex = -1; - - // row header - if (showRowHeaders) { - boolean sorted = tHead.getHeaderCell(col).isSorted(); - addCell(uidl, buildCaptionHtmlSnippet(uidl), aligns[col++], - "rowheader", true, sorted); - visibleColumnIndex++; - } - - if (uidl.hasAttribute("al")) { - actionKeys = uidl.getStringArrayAttribute("al"); - } - - addCellsFromUIDL(uidl, aligns, col, visibleColumnIndex); - - if (uidl.hasAttribute("selected") && !isSelected()) { - toggleSelection(); - } - } - - public TooltipInfo getTooltipInfo() { - return tooltipInfo; - } - - /** - * Add a dummy row, used for measurements if Table is empty. - */ - public VScrollTableRow() { - this(0); - addStyleName(CLASSNAME + "-row"); - addCell(null, "_", 'b', "", true, false); - } - - protected void initCellWidths() { - final int cells = tHead.getVisibleCellCount(); - for (int i = 0; i < cells; i++) { - int w = VScrollTable.this.getColWidth(getColKeyByIndex(i)); - if (w < 0) { - w = 0; - } - setCellWidth(i, w); - } - } - - protected void setCellWidth(int cellIx, int width) { - final Element cell = DOM.getChild(getElement(), cellIx); - cell.getFirstChildElement().getStyle() - .setPropertyPx("width", width); - cell.getStyle().setPropertyPx("width", width); - } - - protected void addCellsFromUIDL(UIDL uidl, char[] aligns, int col, - int visibleColumnIndex) { - final Iterator<?> cells = uidl.getChildIterator(); - while (cells.hasNext()) { - final Object cell = cells.next(); - visibleColumnIndex++; - - String columnId = visibleColOrder[visibleColumnIndex]; - - String style = ""; - if (uidl.hasAttribute("style-" + columnId)) { - style = uidl.getStringAttribute("style-" + columnId); - } - - String description = null; - if (uidl.hasAttribute("descr-" + columnId)) { - description = uidl.getStringAttribute("descr-" - + columnId); - } - - boolean sorted = tHead.getHeaderCell(col).isSorted(); - if (cell instanceof String) { - addCell(uidl, cell.toString(), aligns[col++], style, - isRenderHtmlInCells(), sorted, description); - } else { - final ComponentConnector cellContent = client - .getPaintable((UIDL) cell); - - addCell(uidl, cellContent.getWidget(), aligns[col++], - style, sorted); - } - } - } - - /** - * Overriding this and returning true causes all text cells to be - * rendered as HTML. - * - * @return always returns false in the default implementation - */ - protected boolean isRenderHtmlInCells() { - return false; - } - - /** - * Detects whether row is visible in tables viewport. - * - * @return - */ - public boolean isInViewPort() { - int absoluteTop = getAbsoluteTop(); - int scrollPosition = scrollBodyPanel.getScrollPosition(); - if (absoluteTop < scrollPosition) { - return false; - } - int maxVisible = scrollPosition - + scrollBodyPanel.getOffsetHeight() - getOffsetHeight(); - if (absoluteTop > maxVisible) { - return false; - } - return true; - } - - /** - * Makes a check based on indexes whether the row is before the - * compared row. - * - * @param row1 - * @return true if this rows index is smaller than in the row1 - */ - public boolean isBefore(VScrollTableRow row1) { - return getIndex() < row1.getIndex(); - } - - /** - * Sets the index of the row in the whole table. Currently used just - * to set even/odd classname - * - * @param indexInWholeTable - */ - private void setIndex(int indexInWholeTable) { - index = indexInWholeTable; - boolean isOdd = indexInWholeTable % 2 == 0; - // Inverted logic to be backwards compatible with earlier 6.4. - // It is very strange because rows 1,3,5 are considered "even" - // and 2,4,6 "odd". - // - // First remove any old styles so that both styles aren't - // applied when indexes are updated. - removeStyleName(ROW_CLASSNAME_ODD); - removeStyleName(ROW_CLASSNAME_EVEN); - if (!isOdd) { - addStyleName(ROW_CLASSNAME_ODD); - } else { - addStyleName(ROW_CLASSNAME_EVEN); - } - } - - public int getIndex() { - return index; - } - - @Override - protected void onDetach() { - super.onDetach(); - client.getContextMenu().ensureHidden(this); - } - - public String getKey() { - return String.valueOf(rowKey); - } - - public void addCell(UIDL rowUidl, String text, char align, - String style, boolean textIsHTML, boolean sorted) { - addCell(rowUidl, text, align, style, textIsHTML, sorted, null); - } - - public void addCell(UIDL rowUidl, String text, char align, - String style, boolean textIsHTML, boolean sorted, - String description) { - // String only content is optimized by not using Label widget - final TableCellElement td = DOM.createTD().cast(); - initCellWithText(text, align, style, textIsHTML, sorted, - description, td); - } - - protected void initCellWithText(String text, char align, - String style, boolean textIsHTML, boolean sorted, - String description, final TableCellElement td) { - final Element container = DOM.createDiv(); - String className = CLASSNAME + "-cell-content"; - if (style != null && !style.equals("")) { - className += " " + CLASSNAME + "-cell-content-" + style; - } - if (sorted) { - className += " " + CLASSNAME + "-cell-content-sorted"; - } - td.setClassName(className); - container.setClassName(CLASSNAME + "-cell-wrapper"); - if (textIsHTML) { - container.setInnerHTML(text); - } else { - container.setInnerText(text); - } - if (align != ALIGN_LEFT) { - switch (align) { - case ALIGN_CENTER: - container.getStyle().setProperty("textAlign", "center"); - break; - case ALIGN_RIGHT: - default: - container.getStyle().setProperty("textAlign", "right"); - break; - } - } - - if (description != null && !description.equals("")) { - TooltipInfo info = new TooltipInfo(description); - cellToolTips.put(td, info); - } else { - cellToolTips.remove(td); - } - - td.appendChild(container); - getElement().appendChild(td); - } - - public void addCell(UIDL rowUidl, Widget w, char align, - String style, boolean sorted) { - final TableCellElement td = DOM.createTD().cast(); - initCellWithWidget(w, align, style, sorted, td); - } - - protected void initCellWithWidget(Widget w, char align, - String style, boolean sorted, final TableCellElement td) { - final Element container = DOM.createDiv(); - String className = CLASSNAME + "-cell-content"; - if (style != null && !style.equals("")) { - className += " " + CLASSNAME + "-cell-content-" + style; - } - if (sorted) { - className += " " + CLASSNAME + "-cell-content-sorted"; - } - td.setClassName(className); - container.setClassName(CLASSNAME + "-cell-wrapper"); - // TODO most components work with this, but not all (e.g. - // Select) - // Old comment: make widget cells respect align. - // text-align:center for IE, margin: auto for others - if (align != ALIGN_LEFT) { - switch (align) { - case ALIGN_CENTER: - container.getStyle().setProperty("textAlign", "center"); - break; - case ALIGN_RIGHT: - default: - container.getStyle().setProperty("textAlign", "right"); - break; - } - } - td.appendChild(container); - getElement().appendChild(td); - // ensure widget not attached to another element (possible tBody - // change) - w.removeFromParent(); - container.appendChild(w.getElement()); - adopt(w); - childWidgets.add(w); - } - - @Override - public Iterator<Widget> iterator() { - return childWidgets.iterator(); - } - - @Override - public boolean remove(Widget w) { - if (childWidgets.contains(w)) { - orphan(w); - DOM.removeChild(DOM.getParent(w.getElement()), - w.getElement()); - childWidgets.remove(w); - return true; - } else { - return false; - } - } - - /** - * If there are registered click listeners, sends a click event and - * returns true. Otherwise, does nothing and returns false. - * - * @param event - * @param targetTdOrTr - * @param immediate - * Whether the event is sent immediately - * @return Whether a click event was sent - */ - private boolean handleClickEvent(Event event, Element targetTdOrTr, - boolean immediate) { - if (!client.hasEventListeners(VScrollTable.this, - TableConstants.ITEM_CLICK_EVENT_ID)) { - // Don't send an event if nobody is listening - return false; - } - - // This row was clicked - client.updateVariable(paintableId, "clickedKey", "" + rowKey, - false); - - if (getElement() == targetTdOrTr.getParentElement()) { - // A specific column was clicked - int childIndex = DOM.getChildIndex(getElement(), - targetTdOrTr); - String colKey = null; - colKey = tHead.getHeaderCell(childIndex).getColKey(); - client.updateVariable(paintableId, "clickedColKey", colKey, - false); - } - - MouseEventDetails details = MouseEventDetailsBuilder - .buildMouseEventDetails(event); - - client.updateVariable(paintableId, "clickEvent", - details.toString(), immediate); - - return true; - } - - public TooltipInfo getTooltip( - com.google.gwt.dom.client.Element target) { - - TooltipInfo info = null; - - if (target.hasTagName("TD")) { - - TableCellElement td = (TableCellElement) target.cast(); - info = cellToolTips.get(td); - } - - if (info == null) { - info = tooltipInfo; - } - - return info; - } - - /** - * Special handler for touch devices that support native scrolling - * - * @return Whether the event was handled by this method. - */ - private boolean handleTouchEvent(final Event event) { - - boolean touchEventHandled = false; - - if (enabled && hasNativeTouchScrolling) { - final Element targetTdOrTr = getEventTargetTdOrTr(event); - final int type = event.getTypeInt(); - - switch (type) { - case Event.ONTOUCHSTART: - touchEventHandled = true; - touchStart = event; - isDragging = false; - Touch touch = event.getChangedTouches().get(0); - // save position to fields, touches in events are same - // instance during the operation. - touchStartX = touch.getClientX(); - touchStartY = touch.getClientY(); - - if (dragmode != 0) { - if (dragTouchTimeout == null) { - dragTouchTimeout = new Timer() { - - @Override - public void run() { - if (touchStart != null) { - // Start a drag if a finger is held - // in place long enough, then moved - isDragging = true; - } - } - }; - } - dragTouchTimeout.schedule(TOUCHSCROLL_TIMEOUT); - } - - if (actionKeys != null) { - if (contextTouchTimeout == null) { - contextTouchTimeout = new Timer() { - - @Override - public void run() { - if (touchStart != null) { - // Open the context menu if finger - // is held in place long enough. - showContextMenu(touchStart); - event.preventDefault(); - touchStart = null; - } - } - }; - } - contextTouchTimeout - .schedule(TOUCH_CONTEXT_MENU_TIMEOUT); - } - break; - case Event.ONTOUCHMOVE: - touchEventHandled = true; - if (isSignificantMove(event)) { - if (contextTouchTimeout != null) { - // Moved finger before the context menu timer - // expired, so let the browser handle this as a - // scroll. - contextTouchTimeout.cancel(); - contextTouchTimeout = null; - } - if (!isDragging && dragTouchTimeout != null) { - // Moved finger before the drag timer expired, - // so let the browser handle this as a scroll. - dragTouchTimeout.cancel(); - dragTouchTimeout = null; - } - - if (dragmode != 0 && touchStart != null - && isDragging) { - event.preventDefault(); - event.stopPropagation(); - startRowDrag(touchStart, type, targetTdOrTr); - } - touchStart = null; - } - break; - case Event.ONTOUCHEND: - case Event.ONTOUCHCANCEL: - touchEventHandled = true; - if (contextTouchTimeout != null) { - contextTouchTimeout.cancel(); - } - if (dragTouchTimeout != null) { - dragTouchTimeout.cancel(); - } - if (touchStart != null) { - event.preventDefault(); - event.stopPropagation(); - if (!BrowserInfo.get().isAndroid()) { - Util.simulateClickFromTouchEvent(touchStart, - this); - } - touchStart = null; - } - isDragging = false; - break; - } - } - return touchEventHandled; - } - - /* - * React on click that occur on content cells only - */ - - @Override - public void onBrowserEvent(final Event event) { - - final boolean touchEventHandled = handleTouchEvent(event); - - if (enabled && !touchEventHandled) { - final int type = event.getTypeInt(); - final Element targetTdOrTr = getEventTargetTdOrTr(event); - if (type == Event.ONCONTEXTMENU) { - showContextMenu(event); - if (enabled - && (actionKeys != null || client - .hasEventListeners( - VScrollTable.this, - TableConstants.ITEM_CLICK_EVENT_ID))) { - /* - * Prevent browser context menu only if there are - * action handlers or item click listeners - * registered - */ - event.stopPropagation(); - event.preventDefault(); - } - return; - } - - boolean targetCellOrRowFound = targetTdOrTr != null; - - switch (type) { - case Event.ONDBLCLICK: - if (targetCellOrRowFound) { - handleClickEvent(event, targetTdOrTr, true); - } - break; - case Event.ONMOUSEUP: - if (targetCellOrRowFound) { - /* - * Queue here, send at the same time as the - * corresponding value change event - see #7127 - */ - boolean clickEventSent = handleClickEvent(event, - targetTdOrTr, false); - - if (event.getButton() == Event.BUTTON_LEFT - && isSelectable()) { - - // Ctrl+Shift click - if ((event.getCtrlKey() || event.getMetaKey()) - && event.getShiftKey() - && isMultiSelectModeDefault()) { - toggleShiftSelection(false); - setRowFocus(this); - - // Ctrl click - } else if ((event.getCtrlKey() || event - .getMetaKey()) - && isMultiSelectModeDefault()) { - boolean wasSelected = isSelected(); - toggleSelection(); - setRowFocus(this); - /* - * next possible range select must start on - * this row - */ - selectionRangeStart = this; - if (wasSelected) { - removeRowFromUnsentSelectionRanges(this); - } - - } else if ((event.getCtrlKey() || event - .getMetaKey()) && isSingleSelectMode()) { - // Ctrl (or meta) click (Single selection) - if (!isSelected() - || (isSelected() && nullSelectionAllowed)) { - - if (!isSelected()) { - deselectAll(); - } - - toggleSelection(); - setRowFocus(this); - } - - } else if (event.getShiftKey() - && isMultiSelectModeDefault()) { - // Shift click - toggleShiftSelection(true); - - } else { - // click - boolean currentlyJustThisRowSelected = selectedRowKeys - .size() == 1 - && selectedRowKeys - .contains(getKey()); - - if (!currentlyJustThisRowSelected) { - if (isSingleSelectMode() - || isMultiSelectModeDefault()) { - /* - * For default multi select mode - * (ctrl/shift) and for single - * select mode we need to clear the - * previous selection before - * selecting a new one when the user - * clicks on a row. Only in - * multiselect/simple mode the old - * selection should remain after a - * normal click. - */ - deselectAll(); - } - toggleSelection(); - } else if ((isSingleSelectMode() || isMultiSelectModeSimple()) - && nullSelectionAllowed) { - toggleSelection(); - }/* - * else NOP to avoid excessive server - * visits (selection is removed with - * CTRL/META click) - */ - - selectionRangeStart = this; - setRowFocus(this); - } - - // Remove IE text selection hack - if (BrowserInfo.get().isIE()) { - ((Element) event.getEventTarget().cast()) - .setPropertyJSO("onselectstart", - null); - } - // Queue value change - sendSelectedRows(false); - } - /* - * Send queued click and value change events if any - * If a click event is sent, send value change with - * it regardless of the immediate flag, see #7127 - */ - if (immediate || clickEventSent) { - client.sendPendingVariableChanges(); - } - } - break; - case Event.ONTOUCHEND: - case Event.ONTOUCHCANCEL: - if (touchStart != null) { - /* - * Touch has not been handled as neither context or - * drag start, handle it as a click. - */ - Util.simulateClickFromTouchEvent(touchStart, this); - touchStart = null; - } - if (contextTouchTimeout != null) { - contextTouchTimeout.cancel(); - } - break; - case Event.ONTOUCHMOVE: - if (isSignificantMove(event)) { - /* - * TODO figure out scroll delegate don't eat events - * if row is selected. Null check for active - * delegate is as a workaround. - */ - if (dragmode != 0 - && touchStart != null - && (TouchScrollDelegate - .getActiveScrollDelegate() == null)) { - startRowDrag(touchStart, type, targetTdOrTr); - } - if (contextTouchTimeout != null) { - contextTouchTimeout.cancel(); - } - /* - * Avoid clicks and drags by clearing touch start - * flag. - */ - touchStart = null; - } - - break; - case Event.ONTOUCHSTART: - touchStart = event; - Touch touch = event.getChangedTouches().get(0); - // save position to fields, touches in events are same - // isntance during the operation. - touchStartX = touch.getClientX(); - touchStartY = touch.getClientY(); - /* - * Prevent simulated mouse events. - */ - touchStart.preventDefault(); - if (dragmode != 0 || actionKeys != null) { - new Timer() { - - @Override - public void run() { - TouchScrollDelegate activeScrollDelegate = TouchScrollDelegate - .getActiveScrollDelegate(); - /* - * If there's a scroll delegate, check if - * we're actually scrolling and handle it. - * If no delegate, do nothing here and let - * the row handle potential drag'n'drop or - * context menu. - */ - if (activeScrollDelegate != null) { - if (activeScrollDelegate.isMoved()) { - /* - * Prevent the row from handling - * touch move/end events (the - * delegate handles those) and from - * doing drag'n'drop or opening a - * context menu. - */ - touchStart = null; - } else { - /* - * Scrolling hasn't started, so - * cancel delegate and let the row - * handle potential drag'n'drop or - * context menu. - */ - activeScrollDelegate - .stopScrolling(); - } - } - } - }.schedule(TOUCHSCROLL_TIMEOUT); - - if (contextTouchTimeout == null - && actionKeys != null) { - contextTouchTimeout = new Timer() { - - @Override - public void run() { - if (touchStart != null) { - showContextMenu(touchStart); - touchStart = null; - } - } - }; - } - if (contextTouchTimeout != null) { - contextTouchTimeout.cancel(); - contextTouchTimeout - .schedule(TOUCH_CONTEXT_MENU_TIMEOUT); - } - } - break; - case Event.ONMOUSEDOWN: - if (targetCellOrRowFound) { - setRowFocus(this); - ensureFocus(); - if (dragmode != 0 - && (event.getButton() == NativeEvent.BUTTON_LEFT)) { - startRowDrag(event, type, targetTdOrTr); - - } else if (event.getCtrlKey() - || event.getShiftKey() - || event.getMetaKey() - && isMultiSelectModeDefault()) { - - // Prevent default text selection in Firefox - event.preventDefault(); - - // Prevent default text selection in IE - if (BrowserInfo.get().isIE()) { - ((Element) event.getEventTarget().cast()) - .setPropertyJSO( - "onselectstart", - getPreventTextSelectionIEHack()); - } - - event.stopPropagation(); - } - } - break; - case Event.ONMOUSEOUT: - break; - default: - break; - } - } - super.onBrowserEvent(event); - } - - private boolean isSignificantMove(Event event) { - if (touchStart == null) { - // no touch start - return false; - } - /* - * TODO calculate based on real distance instead of separate - * axis checks - */ - Touch touch = event.getChangedTouches().get(0); - if (Math.abs(touch.getClientX() - touchStartX) > TouchScrollDelegate.SIGNIFICANT_MOVE_THRESHOLD) { - return true; - } - if (Math.abs(touch.getClientY() - touchStartY) > TouchScrollDelegate.SIGNIFICANT_MOVE_THRESHOLD) { - return true; - } - return false; - } - - /** - * Checks if the row represented by the row key has been selected - * - * @param key - * The generated row key - */ - private boolean rowKeyIsSelected(int rowKey) { - // Check single selections - if (selectedRowKeys.contains("" + rowKey)) { - return true; - } - - // Check range selections - for (SelectionRange r : selectedRowRanges) { - if (r.inRange(getRenderedRowByKey("" + rowKey))) { - return true; - } - } - return false; - } - - protected void startRowDrag(Event event, final int type, - Element targetTdOrTr) { - VTransferable transferable = new VTransferable(); - transferable.setDragSource(ConnectorMap.get(client) - .getConnector(VScrollTable.this)); - transferable.setData("itemId", "" + rowKey); - NodeList<TableCellElement> cells = rowElement.getCells(); - for (int i = 0; i < cells.getLength(); i++) { - if (cells.getItem(i).isOrHasChild(targetTdOrTr)) { - HeaderCell headerCell = tHead.getHeaderCell(i); - transferable.setData("propertyId", headerCell.cid); - break; - } - } - - VDragEvent ev = VDragAndDropManager.get().startDrag( - transferable, event, true); - if (dragmode == DRAGMODE_MULTIROW && isMultiSelectModeAny() - && rowKeyIsSelected(rowKey)) { - - // Create a drag image of ALL rows - ev.createDragImage( - (Element) scrollBody.tBodyElement.cast(), true); - - // Hide rows which are not selected - Element dragImage = ev.getDragImage(); - int i = 0; - for (Iterator<Widget> iterator = scrollBody.iterator(); iterator - .hasNext();) { - VScrollTableRow next = (VScrollTableRow) iterator - .next(); - - Element child = (Element) dragImage.getChild(i++); - - if (!rowKeyIsSelected(next.rowKey)) { - child.getStyle().setVisibility(Visibility.HIDDEN); - } - } - } else { - ev.createDragImage(getElement(), true); - } - if (type == Event.ONMOUSEDOWN) { - event.preventDefault(); - } - event.stopPropagation(); - } - - /** - * Finds the TD that the event interacts with. Returns null if the - * target of the event should not be handled. If the event target is - * the row directly this method returns the TR element instead of - * the TD. - * - * @param event - * @return TD or TR element that the event targets (the actual event - * target is this element or a child of it) - */ - private Element getEventTargetTdOrTr(Event event) { - final Element eventTarget = event.getEventTarget().cast(); - Widget widget = Util.findWidget(eventTarget, null); - final Element thisTrElement = getElement(); - - if (widget != this) { - /* - * This is a workaround to make Labels, read only TextFields - * and Embedded in a Table clickable (see #2688). It is - * really not a fix as it does not work with a custom read - * only components (not extending VLabel/VEmbedded). - */ - while (widget != null && widget.getParent() != this) { - widget = widget.getParent(); - } - - if (!(widget instanceof VLabel) - && !(widget instanceof VEmbedded) - && !(widget instanceof VTextField && ((VTextField) widget) - .isReadOnly())) { - return null; - } - } - if (eventTarget == thisTrElement) { - // This was a click on the TR element - return thisTrElement; - } - - // Iterate upwards until we find the TR element - Element element = eventTarget; - while (element != null - && element.getParentElement().cast() != thisTrElement) { - element = element.getParentElement().cast(); - } - return element; - } - - public void showContextMenu(Event event) { - if (enabled && actionKeys != null) { - // Show context menu if there are registered action handlers - int left = Util.getTouchOrMouseClientX(event); - int top = Util.getTouchOrMouseClientY(event); - top += Window.getScrollTop(); - left += Window.getScrollLeft(); - contextMenu = new ContextMenuDetails(getKey(), left, top); - client.getContextMenu().showAt(this, left, top); - } - } - - /** - * Has the row been selected? - * - * @return Returns true if selected, else false - */ - public boolean isSelected() { - return selected; - } - - /** - * Toggle the selection of the row - */ - public void toggleSelection() { - selected = !selected; - selectionChanged = true; - if (selected) { - selectedRowKeys.add(String.valueOf(rowKey)); - addStyleName("v-selected"); - } else { - removeStyleName("v-selected"); - selectedRowKeys.remove(String.valueOf(rowKey)); - } - } - - /** - * Is called when a user clicks an item when holding SHIFT key down. - * This will select a new range from the last focused row - * - * @param deselectPrevious - * Should the previous selected range be deselected - */ - private void toggleShiftSelection(boolean deselectPrevious) { - - /* - * Ensures that we are in multiselect mode and that we have a - * previous selection which was not a deselection - */ - if (isSingleSelectMode()) { - // No previous selection found - deselectAll(); - toggleSelection(); - return; - } - - // Set the selectable range - VScrollTableRow endRow = this; - VScrollTableRow startRow = selectionRangeStart; - if (startRow == null) { - startRow = focusedRow; - // If start row is null then we have a multipage selection - // from - // above - if (startRow == null) { - startRow = (VScrollTableRow) scrollBody.iterator() - .next(); - setRowFocus(endRow); - } - } - // Deselect previous items if so desired - if (deselectPrevious) { - deselectAll(); - } - - // we'll ensure GUI state from top down even though selection - // was the opposite way - if (!startRow.isBefore(endRow)) { - VScrollTableRow tmp = startRow; - startRow = endRow; - endRow = tmp; - } - SelectionRange range = new SelectionRange(startRow, endRow); - - for (Widget w : scrollBody) { - VScrollTableRow row = (VScrollTableRow) w; - if (range.inRange(row)) { - if (!row.isSelected()) { - row.toggleSelection(); - } - selectedRowKeys.add(row.getKey()); - } - } - - // Add range - if (startRow != endRow) { - selectedRowRanges.add(range); - } - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.ui.IActionOwner#getActions () - */ - - @Override - public Action[] getActions() { - if (actionKeys == null) { - return new Action[] {}; - } - final Action[] actions = new Action[actionKeys.length]; - for (int i = 0; i < actions.length; i++) { - final String actionKey = actionKeys[i]; - final TreeAction a = new TreeAction(this, - String.valueOf(rowKey), actionKey) { - - @Override - public void execute() { - super.execute(); - lazyRevertFocusToRow(VScrollTableRow.this); - } - }; - a.setCaption(getActionCaption(actionKey)); - a.setIconUrl(getActionIcon(actionKey)); - actions[i] = a; - } - return actions; - } - - @Override - public ApplicationConnection getClient() { - return client; - } - - @Override - public String getPaintableId() { - return paintableId; - } - - private int getColIndexOf(Widget child) { - com.google.gwt.dom.client.Element widgetCell = child - .getElement().getParentElement().getParentElement(); - NodeList<TableCellElement> cells = rowElement.getCells(); - for (int i = 0; i < cells.getLength(); i++) { - if (cells.getItem(i) == widgetCell) { - return i; - } - } - return -1; - } - - public Widget getWidgetForPaintable() { - return this; - } - } - - protected class VScrollTableGeneratedRow extends VScrollTableRow { - - private boolean spanColumns; - private boolean htmlContentAllowed; - - public VScrollTableGeneratedRow(UIDL uidl, char[] aligns) { - super(uidl, aligns); - addStyleName("v-table-generated-row"); - } - - public boolean isSpanColumns() { - return spanColumns; - } - - @Override - protected void initCellWidths() { - if (spanColumns) { - setSpannedColumnWidthAfterDOMFullyInited(); - } else { - super.initCellWidths(); - } - } - - private void setSpannedColumnWidthAfterDOMFullyInited() { - // Defer setting width on spanned columns to make sure that - // they are added to the DOM before trying to calculate - // widths. - Scheduler.get().scheduleDeferred(new ScheduledCommand() { - - @Override - public void execute() { - if (showRowHeaders) { - setCellWidth(0, tHead.getHeaderCell(0).getWidth()); - calcAndSetSpanWidthOnCell(1); - } else { - calcAndSetSpanWidthOnCell(0); - } - } - }); - } - - @Override - protected boolean isRenderHtmlInCells() { - return htmlContentAllowed; - } - - @Override - protected void addCellsFromUIDL(UIDL uidl, char[] aligns, int col, - int visibleColumnIndex) { - htmlContentAllowed = uidl.getBooleanAttribute("gen_html"); - spanColumns = uidl.getBooleanAttribute("gen_span"); - - final Iterator<?> cells = uidl.getChildIterator(); - if (spanColumns) { - int colCount = uidl.getChildCount(); - if (cells.hasNext()) { - final Object cell = cells.next(); - if (cell instanceof String) { - addSpannedCell(uidl, cell.toString(), aligns[0], - "", htmlContentAllowed, false, null, - colCount); - } else { - addSpannedCell(uidl, (Widget) cell, aligns[0], "", - false, colCount); - } - } - } else { - super.addCellsFromUIDL(uidl, aligns, col, - visibleColumnIndex); - } - } - - private void addSpannedCell(UIDL rowUidl, Widget w, char align, - String style, boolean sorted, int colCount) { - TableCellElement td = DOM.createTD().cast(); - td.setColSpan(colCount); - initCellWithWidget(w, align, style, sorted, td); - } - - private void addSpannedCell(UIDL rowUidl, String text, char align, - String style, boolean textIsHTML, boolean sorted, - String description, int colCount) { - // String only content is optimized by not using Label widget - final TableCellElement td = DOM.createTD().cast(); - td.setColSpan(colCount); - initCellWithText(text, align, style, textIsHTML, sorted, - description, td); - } - - @Override - protected void setCellWidth(int cellIx, int width) { - if (isSpanColumns()) { - if (showRowHeaders) { - if (cellIx == 0) { - super.setCellWidth(0, width); - } else { - // We need to recalculate the spanning TDs width for - // every cellIx in order to support column resizing. - calcAndSetSpanWidthOnCell(1); - } - } else { - // Same as above. - calcAndSetSpanWidthOnCell(0); - } - } else { - super.setCellWidth(cellIx, width); - } - } - - private void calcAndSetSpanWidthOnCell(final int cellIx) { - int spanWidth = 0; - for (int ix = (showRowHeaders ? 1 : 0); ix < tHead - .getVisibleCellCount(); ix++) { - spanWidth += tHead.getHeaderCell(ix).getOffsetWidth(); - } - Util.setWidthExcludingPaddingAndBorder((Element) getElement() - .getChild(cellIx), spanWidth, 13, false); - } - } - - /** - * Ensure the component has a focus. - * - * TODO the current implementation simply always calls focus for the - * component. In case the Table at some point implements focus/blur - * listeners, this method needs to be evolved to conditionally call - * focus only if not currently focused. - */ - protected void ensureFocus() { - if (!hasFocus) { - scrollBodyPanel.setFocus(true); - } - - } - - } - - /** - * Deselects all items - */ - public void deselectAll() { - for (Widget w : scrollBody) { - VScrollTableRow row = (VScrollTableRow) w; - if (row.isSelected()) { - row.toggleSelection(); - } - } - // still ensure all selects are removed from (not necessary rendered) - selectedRowKeys.clear(); - selectedRowRanges.clear(); - // also notify server that it clears all previous selections (the client - // side does not know about the invisible ones) - instructServerToForgetPreviousSelections(); - } - - /** - * Used in multiselect mode when the client side knows that all selections - * are in the next request. - */ - private void instructServerToForgetPreviousSelections() { - client.updateVariable(paintableId, "clearSelections", true, false); - } - - /** - * Determines the pagelength when the table height is fixed. - */ - public void updatePageLength() { - // Only update if visible and enabled - if (!isVisible() || !enabled) { - return; - } - - if (scrollBody == null) { - return; - } - - if (isDynamicHeight()) { - return; - } - - int rowHeight = (int) Math.round(scrollBody.getRowHeight()); - int bodyH = scrollBodyPanel.getOffsetHeight(); - int rowsAtOnce = bodyH / rowHeight; - boolean anotherPartlyVisible = ((bodyH % rowHeight) != 0); - if (anotherPartlyVisible) { - rowsAtOnce++; - } - if (pageLength != rowsAtOnce) { - pageLength = rowsAtOnce; - client.updateVariable(paintableId, "pagelength", pageLength, false); - - if (!rendering) { - int currentlyVisible = scrollBody.lastRendered - - scrollBody.firstRendered; - if (currentlyVisible < pageLength - && currentlyVisible < totalRows) { - // shake scrollpanel to fill empty space - scrollBodyPanel.setScrollPosition(scrollTop + 1); - scrollBodyPanel.setScrollPosition(scrollTop - 1); - } - - sizeNeedsInit = true; - } - } - - } - - void updateWidth() { - if (!isVisible()) { - /* - * Do not update size when the table is hidden as all column widths - * will be set to zero and they won't be recalculated when the table - * is set visible again (until the size changes again) - */ - return; - } - - if (!isDynamicWidth()) { - int innerPixels = getOffsetWidth() - getBorderWidth(); - if (innerPixels < 0) { - innerPixels = 0; - } - setContentWidth(innerPixels); - - // readjust undefined width columns - triggerLazyColumnAdjustment(false); - - } else { - - sizeNeedsInit = true; - - // readjust undefined width columns - triggerLazyColumnAdjustment(false); - } - - /* - * setting width may affect wheter the component has scrollbars -> needs - * scrolling or not - */ - setProperTabIndex(); - } - - private static final int LAZY_COLUMN_ADJUST_TIMEOUT = 300; - - private final Timer lazyAdjustColumnWidths = new Timer() { - /** - * Check for column widths, and available width, to see if we can fix - * column widths "optimally". Doing this lazily to avoid expensive - * calculation when resizing is not yet finished. - */ - - @Override - public void run() { - if (scrollBody == null) { - // Try again later if we get here before scrollBody has been - // initalized - triggerLazyColumnAdjustment(false); - return; - } - - Iterator<Widget> headCells = tHead.iterator(); - int usedMinimumWidth = 0; - int totalExplicitColumnsWidths = 0; - float expandRatioDivider = 0; - int colIndex = 0; - while (headCells.hasNext()) { - final HeaderCell hCell = (HeaderCell) headCells.next(); - if (hCell.isDefinedWidth()) { - totalExplicitColumnsWidths += hCell.getWidth(); - usedMinimumWidth += hCell.getWidth(); - } else { - usedMinimumWidth += hCell.getNaturalColumnWidth(colIndex); - expandRatioDivider += hCell.getExpandRatio(); - } - colIndex++; - } - - int availW = scrollBody.getAvailableWidth(); - // Hey IE, are you really sure about this? - availW = scrollBody.getAvailableWidth(); - int visibleCellCount = tHead.getVisibleCellCount(); - int totalExtraWidth = scrollBody.getCellExtraWidth() - * visibleCellCount; - if (willHaveScrollbars()) { - totalExtraWidth += Util.getNativeScrollbarSize(); - } - availW -= totalExtraWidth; - int forceScrollBodyWidth = -1; - - int extraSpace = availW - usedMinimumWidth; - if (extraSpace < 0) { - if (getTotalRows() == 0) { - /* - * Too wide header combined with no rows in the table. - * - * No horizontal scrollbars would be displayed because - * there's no rows that grows too wide causing the - * scrollBody container div to overflow. Must explicitely - * force a width to a scrollbar. (see #9187) - */ - forceScrollBodyWidth = usedMinimumWidth + totalExtraWidth; - } - extraSpace = 0; - } - - if (forceScrollBodyWidth > 0) { - scrollBody.container.getStyle().setWidth(forceScrollBodyWidth, - Unit.PX); - } else { - // Clear width that might have been set to force horizontal - // scrolling if there are no rows - scrollBody.container.getStyle().clearWidth(); - } - - int totalUndefinedNaturalWidths = usedMinimumWidth - - totalExplicitColumnsWidths; - - // we have some space that can be divided optimally - HeaderCell hCell; - colIndex = 0; - headCells = tHead.iterator(); - int checksum = 0; - while (headCells.hasNext()) { - hCell = (HeaderCell) headCells.next(); - if (!hCell.isDefinedWidth()) { - int w = hCell.getNaturalColumnWidth(colIndex); - int newSpace; - if (expandRatioDivider > 0) { - // divide excess space by expand ratios - newSpace = Math.round((w + extraSpace - * hCell.getExpandRatio() / expandRatioDivider)); - } else { - if (totalUndefinedNaturalWidths != 0) { - // divide relatively to natural column widths - newSpace = Math.round(w + (float) extraSpace - * (float) w / totalUndefinedNaturalWidths); - } else { - newSpace = w; - } - } - checksum += newSpace; - setColWidth(colIndex, newSpace, false); - } else { - checksum += hCell.getWidth(); - } - colIndex++; - } - - if (extraSpace > 0 && checksum != availW) { - /* - * There might be in some cases a rounding error of 1px when - * extra space is divided so if there is one then we give the - * first undefined column 1 more pixel - */ - headCells = tHead.iterator(); - colIndex = 0; - while (headCells.hasNext()) { - HeaderCell hc = (HeaderCell) headCells.next(); - if (!hc.isDefinedWidth()) { - setColWidth(colIndex, - hc.getWidth() + availW - checksum, false); - break; - } - colIndex++; - } - } - - if (isDynamicHeight() && totalRows == pageLength) { - // fix body height (may vary if lazy loading is offhorizontal - // scrollbar appears/disappears) - int bodyHeight = scrollBody.getRequiredHeight(); - boolean needsSpaceForHorizontalScrollbar = (availW < usedMinimumWidth); - if (needsSpaceForHorizontalScrollbar) { - bodyHeight += Util.getNativeScrollbarSize(); - } - int heightBefore = getOffsetHeight(); - scrollBodyPanel.setHeight(bodyHeight + "px"); - if (heightBefore != getOffsetHeight()) { - Util.notifyParentOfSizeChange(VScrollTable.this, false); - } - } - scrollBody.reLayoutComponents(); - Scheduler.get().scheduleDeferred(new Command() { - - @Override - public void execute() { - Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement()); - } - }); - - forceRealignColumnHeaders(); - } - - }; - - private void forceRealignColumnHeaders() { - if (BrowserInfo.get().isIE()) { - /* - * IE does not fire onscroll event if scroll position is reverted to - * 0 due to the content element size growth. Ensure headers are in - * sync with content manually. Safe to use null event as we don't - * actually use the event object in listener. - */ - onScroll(null); - } - } - - /** - * helper to set pixel size of head and body part - * - * @param pixels - */ - private void setContentWidth(int pixels) { - tHead.setWidth(pixels + "px"); - scrollBodyPanel.setWidth(pixels + "px"); - tFoot.setWidth(pixels + "px"); - } - - private int borderWidth = -1; - - /** - * @return border left + border right - */ - private int getBorderWidth() { - if (borderWidth < 0) { - borderWidth = Util.measureHorizontalPaddingAndBorder( - scrollBodyPanel.getElement(), 2); - if (borderWidth < 0) { - borderWidth = 0; - } - } - return borderWidth; - } - - /** - * Ensures scrollable area is properly sized. This method is used when fixed - * size is used. - */ - private int containerHeight; - - private void setContainerHeight() { - if (!isDynamicHeight()) { - containerHeight = getOffsetHeight(); - containerHeight -= showColHeaders ? tHead.getOffsetHeight() : 0; - containerHeight -= tFoot.getOffsetHeight(); - containerHeight -= getContentAreaBorderHeight(); - if (containerHeight < 0) { - containerHeight = 0; - } - scrollBodyPanel.setHeight(containerHeight + "px"); - } - } - - private int contentAreaBorderHeight = -1; - private int scrollLeft; - private int scrollTop; - VScrollTableDropHandler dropHandler; - private boolean navKeyDown; - boolean multiselectPending; - - /** - * @return border top + border bottom of the scrollable area of table - */ - private int getContentAreaBorderHeight() { - if (contentAreaBorderHeight < 0) { - - DOM.setStyleAttribute(scrollBodyPanel.getElement(), "overflow", - "hidden"); - int oh = scrollBodyPanel.getOffsetHeight(); - int ch = scrollBodyPanel.getElement() - .getPropertyInt("clientHeight"); - contentAreaBorderHeight = oh - ch; - DOM.setStyleAttribute(scrollBodyPanel.getElement(), "overflow", - "auto"); - } - return contentAreaBorderHeight; - } - - @Override - public void setHeight(String height) { - if (height.length() == 0 - && getElement().getStyle().getHeight().length() != 0) { - /* - * Changing from defined to undefined size -> should do a size init - * to take page length into account again - */ - sizeNeedsInit = true; - } - super.setHeight(height); - } - - void updateHeight() { - setContainerHeight(); - - if (initializedAndAttached) { - updatePageLength(); - } - if (!rendering) { - // Webkit may sometimes get an odd rendering bug (white space - // between header and body), see bug #3875. Running - // overflow hack here to shake body element a bit. - // We must run the fix as a deferred command to prevent it from - // overwriting the scroll position with an outdated value, see - // #7607. - Scheduler.get().scheduleDeferred(new Command() { - - @Override - public void execute() { - Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement()); - } - }); - } - - triggerLazyColumnAdjustment(false); - - /* - * setting height may affect wheter the component has scrollbars -> - * needs scrolling or not - */ - setProperTabIndex(); - - } - - /* - * Overridden due Table might not survive of visibility change (scroll pos - * lost). Example ITabPanel just set contained components invisible and back - * when changing tabs. - */ - - @Override - public void setVisible(boolean visible) { - if (isVisible() != visible) { - super.setVisible(visible); - if (initializedAndAttached) { - if (visible) { - Scheduler.get().scheduleDeferred(new Command() { - - @Override - public void execute() { - scrollBodyPanel - .setScrollPosition(measureRowHeightOffset(firstRowInViewPort)); - } - }); - } - } - } - } - - /** - * Helper function to build html snippet for column or row headers - * - * @param uidl - * possibly with values caption and icon - * @return html snippet containing possibly an icon + caption text - */ - protected String buildCaptionHtmlSnippet(UIDL uidl) { - String s = uidl.hasAttribute("caption") ? uidl - .getStringAttribute("caption") : ""; - if (uidl.hasAttribute("icon")) { - s = "<img src=\"" - + Util.escapeAttribute(client.translateVaadinUri(uidl - .getStringAttribute("icon"))) - + "\" alt=\"icon\" class=\"v-icon\">" + s; - } - return s; - } - - /** - * This method has logic which rows needs to be requested from server when - * user scrolls - */ - - @Override - public void onScroll(ScrollEvent event) { - scrollLeft = scrollBodyPanel.getElement().getScrollLeft(); - scrollTop = scrollBodyPanel.getScrollPosition(); - /* - * #6970 - IE sometimes fires scroll events for a detached table. - * - * FIXME initializedAndAttached should probably be renamed - its name - * doesn't seem to reflect its semantics. onDetach() doesn't set it to - * false, and changing that might break something else, so we need to - * check isAttached() separately. - */ - if (!initializedAndAttached || !isAttached()) { - return; - } - if (!enabled) { - scrollBodyPanel - .setScrollPosition(measureRowHeightOffset(firstRowInViewPort)); - return; - } - - rowRequestHandler.cancel(); - - if (BrowserInfo.get().isSafari() && event != null && scrollTop == 0) { - // due to the webkitoverflowworkaround, top may sometimes report 0 - // for webkit, although it really is not. Expecting to have the - // correct - // value available soon. - Scheduler.get().scheduleDeferred(new Command() { - - @Override - public void execute() { - onScroll(null); - } - }); - return; - } - - // fix headers horizontal scrolling - tHead.setHorizontalScrollPosition(scrollLeft); - - // fix footers horizontal scrolling - tFoot.setHorizontalScrollPosition(scrollLeft); - - firstRowInViewPort = calcFirstRowInViewPort(); - if (firstRowInViewPort > totalRows - pageLength) { - firstRowInViewPort = totalRows - pageLength; - } - - int postLimit = (int) (firstRowInViewPort + (pageLength - 1) + pageLength - * cache_react_rate); - if (postLimit > totalRows - 1) { - postLimit = totalRows - 1; - } - int preLimit = (int) (firstRowInViewPort - pageLength - * cache_react_rate); - if (preLimit < 0) { - preLimit = 0; - } - final int lastRendered = scrollBody.getLastRendered(); - final int firstRendered = scrollBody.getFirstRendered(); - - if (postLimit <= lastRendered && preLimit >= firstRendered) { - // we're within no-react area, no need to request more rows - // remember which firstvisible we requested, in case the server has - // a differing opinion - lastRequestedFirstvisible = firstRowInViewPort; - client.updateVariable(paintableId, "firstvisible", - firstRowInViewPort, false); - return; - } - - if (firstRowInViewPort - pageLength * cache_rate > lastRendered - || firstRowInViewPort + pageLength + pageLength * cache_rate < firstRendered) { - // need a totally new set of rows - rowRequestHandler - .setReqFirstRow((firstRowInViewPort - (int) (pageLength * cache_rate))); - int last = firstRowInViewPort + (int) (cache_rate * pageLength) - + pageLength - 1; - if (last >= totalRows) { - last = totalRows - 1; - } - rowRequestHandler.setReqRows(last - - rowRequestHandler.getReqFirstRow() + 1); - rowRequestHandler.deferRowFetch(); - return; - } - if (preLimit < firstRendered) { - // need some rows to the beginning of the rendered area - rowRequestHandler - .setReqFirstRow((int) (firstRowInViewPort - pageLength - * cache_rate)); - rowRequestHandler.setReqRows(firstRendered - - rowRequestHandler.getReqFirstRow()); - rowRequestHandler.deferRowFetch(); - - return; - } - if (postLimit > lastRendered) { - // need some rows to the end of the rendered area - rowRequestHandler.setReqFirstRow(lastRendered + 1); - rowRequestHandler.setReqRows((int) ((firstRowInViewPort - + pageLength + pageLength * cache_rate) - lastRendered)); - rowRequestHandler.deferRowFetch(); - } - } - - protected int calcFirstRowInViewPort() { - return (int) Math.ceil(scrollTop / scrollBody.getRowHeight()); - } - - @Override - public VScrollTableDropHandler getDropHandler() { - return dropHandler; - } - - private static class TableDDDetails { - int overkey = -1; - VerticalDropLocation dropLocation; - String colkey; - - @Override - public boolean equals(Object obj) { - if (obj instanceof TableDDDetails) { - TableDDDetails other = (TableDDDetails) obj; - return dropLocation == other.dropLocation - && overkey == other.overkey - && ((colkey != null && colkey.equals(other.colkey)) || (colkey == null && other.colkey == null)); - } - return false; - } - - // - // public int hashCode() { - // return overkey; - // } - } - - public class VScrollTableDropHandler extends VAbstractDropHandler { - - private static final String ROWSTYLEBASE = "v-table-row-drag-"; - private TableDDDetails dropDetails; - private TableDDDetails lastEmphasized; - - @Override - public void dragEnter(VDragEvent drag) { - updateDropDetails(drag); - super.dragEnter(drag); - } - - private void updateDropDetails(VDragEvent drag) { - dropDetails = new TableDDDetails(); - Element elementOver = drag.getElementOver(); - - VScrollTableRow row = Util.findWidget(elementOver, getRowClass()); - if (row != null) { - dropDetails.overkey = row.rowKey; - Element tr = row.getElement(); - Element element = elementOver; - while (element != null && element.getParentElement() != tr) { - element = (Element) element.getParentElement(); - } - int childIndex = DOM.getChildIndex(tr, element); - dropDetails.colkey = tHead.getHeaderCell(childIndex) - .getColKey(); - dropDetails.dropLocation = DDUtil.getVerticalDropLocation( - row.getElement(), drag.getCurrentGwtEvent(), 0.2); - } - - drag.getDropDetails().put("itemIdOver", dropDetails.overkey + ""); - drag.getDropDetails().put( - "detail", - dropDetails.dropLocation != null ? dropDetails.dropLocation - .toString() : null); - - } - - private Class<? extends Widget> getRowClass() { - // get the row type this way to make dd work in derived - // implementations - return scrollBody.iterator().next().getClass(); - } - - @Override - public void dragOver(VDragEvent drag) { - TableDDDetails oldDetails = dropDetails; - updateDropDetails(drag); - if (!oldDetails.equals(dropDetails)) { - deEmphasis(); - final TableDDDetails newDetails = dropDetails; - VAcceptCallback cb = new VAcceptCallback() { - - @Override - public void accepted(VDragEvent event) { - if (newDetails.equals(dropDetails)) { - dragAccepted(event); - } - /* - * Else new target slot already defined, ignore - */ - } - }; - validate(cb, drag); - } - } - - @Override - public void dragLeave(VDragEvent drag) { - deEmphasis(); - super.dragLeave(drag); - } - - @Override - public boolean drop(VDragEvent drag) { - deEmphasis(); - return super.drop(drag); - } - - private void deEmphasis() { - UIObject.setStyleName(getElement(), CLASSNAME + "-drag", false); - if (lastEmphasized == null) { - return; - } - for (Widget w : scrollBody.renderedRows) { - VScrollTableRow row = (VScrollTableRow) w; - if (lastEmphasized != null - && row.rowKey == lastEmphasized.overkey) { - String stylename = ROWSTYLEBASE - + lastEmphasized.dropLocation.toString() - .toLowerCase(); - VScrollTableRow.setStyleName(row.getElement(), stylename, - false); - lastEmphasized = null; - return; - } - } - } - - /** - * TODO needs different drop modes ?? (on cells, on rows), now only - * supports rows - */ - private void emphasis(TableDDDetails details) { - deEmphasis(); - UIObject.setStyleName(getElement(), CLASSNAME + "-drag", true); - // iterate old and new emphasized row - for (Widget w : scrollBody.renderedRows) { - VScrollTableRow row = (VScrollTableRow) w; - if (details != null && details.overkey == row.rowKey) { - String stylename = ROWSTYLEBASE - + details.dropLocation.toString().toLowerCase(); - VScrollTableRow.setStyleName(row.getElement(), stylename, - true); - lastEmphasized = details; - return; - } - } - } - - @Override - protected void dragAccepted(VDragEvent drag) { - emphasis(dropDetails); - } - - @Override - public ComponentConnector getConnector() { - return ConnectorMap.get(client).getConnector(VScrollTable.this); - } - - @Override - public ApplicationConnection getApplicationConnection() { - return client; - } - - } - - protected VScrollTableRow getFocusedRow() { - return focusedRow; - } - - /** - * Moves the selection head to a specific row - * - * @param row - * The row to where the selection head should move - * @return Returns true if focus was moved successfully, else false - */ - public boolean setRowFocus(VScrollTableRow row) { - - if (!isSelectable()) { - return false; - } - - // Remove previous selection - if (focusedRow != null && focusedRow != row) { - focusedRow.removeStyleName(CLASSNAME_SELECTION_FOCUS); - } - - if (row != null) { - - // Apply focus style to new selection - row.addStyleName(CLASSNAME_SELECTION_FOCUS); - - /* - * Trying to set focus on already focused row - */ - if (row == focusedRow) { - return false; - } - - // Set new focused row - focusedRow = row; - - ensureRowIsVisible(row); - - return true; - } - - return false; - } - - /** - * Ensures that the row is visible - * - * @param row - * The row to ensure is visible - */ - private void ensureRowIsVisible(VScrollTableRow row) { - if (BrowserInfo.get().isTouchDevice()) { - // Skip due to android devices that have broken scrolltop will may - // get odd scrolling here. - return; - } - Util.scrollIntoViewVertically(row.getElement()); - } - - /** - * Handles the keyboard events handled by the table - * - * @param event - * The keyboard event received - * @return true iff the navigation event was handled - */ - protected boolean handleNavigation(int keycode, boolean ctrl, boolean shift) { - if (keycode == KeyCodes.KEY_TAB || keycode == KeyCodes.KEY_SHIFT) { - // Do not handle tab key - return false; - } - - // Down navigation - if (!isSelectable() && keycode == getNavigationDownKey()) { - scrollBodyPanel.setScrollPosition(scrollBodyPanel - .getScrollPosition() + scrollingVelocity); - return true; - } else if (keycode == getNavigationDownKey()) { - if (isMultiSelectModeAny() && moveFocusDown()) { - selectFocusedRow(ctrl, shift); - - } else if (isSingleSelectMode() && !shift && moveFocusDown()) { - selectFocusedRow(ctrl, shift); - } - return true; - } - - // Up navigation - if (!isSelectable() && keycode == getNavigationUpKey()) { - scrollBodyPanel.setScrollPosition(scrollBodyPanel - .getScrollPosition() - scrollingVelocity); - return true; - } else if (keycode == getNavigationUpKey()) { - if (isMultiSelectModeAny() && moveFocusUp()) { - selectFocusedRow(ctrl, shift); - } else if (isSingleSelectMode() && !shift && moveFocusUp()) { - selectFocusedRow(ctrl, shift); - } - return true; - } - - if (keycode == getNavigationLeftKey()) { - // Left navigation - scrollBodyPanel.setHorizontalScrollPosition(scrollBodyPanel - .getHorizontalScrollPosition() - scrollingVelocity); - return true; - - } else if (keycode == getNavigationRightKey()) { - // Right navigation - scrollBodyPanel.setHorizontalScrollPosition(scrollBodyPanel - .getHorizontalScrollPosition() + scrollingVelocity); - return true; - } - - // Select navigation - if (isSelectable() && keycode == getNavigationSelectKey()) { - if (isSingleSelectMode()) { - boolean wasSelected = focusedRow.isSelected(); - deselectAll(); - if (!wasSelected || !nullSelectionAllowed) { - focusedRow.toggleSelection(); - } - } else { - focusedRow.toggleSelection(); - removeRowFromUnsentSelectionRanges(focusedRow); - } - - sendSelectedRows(); - return true; - } - - // Page Down navigation - if (keycode == getNavigationPageDownKey()) { - if (isSelectable()) { - /* - * If selectable we plagiate MSW behaviour: first scroll to the - * end of current view. If at the end, scroll down one page - * length and keep the selected row in the bottom part of - * visible area. - */ - if (!isFocusAtTheEndOfTable()) { - VScrollTableRow lastVisibleRowInViewPort = scrollBody - .getRowByRowIndex(firstRowInViewPort - + getFullyVisibleRowCount() - 1); - if (lastVisibleRowInViewPort != null - && lastVisibleRowInViewPort != focusedRow) { - // focused row is not at the end of the table, move - // focus and select the last visible row - setRowFocus(lastVisibleRowInViewPort); - selectFocusedRow(ctrl, shift); - sendSelectedRows(); - } else { - int indexOfToBeFocused = focusedRow.getIndex() - + getFullyVisibleRowCount(); - if (indexOfToBeFocused >= totalRows) { - indexOfToBeFocused = totalRows - 1; - } - VScrollTableRow toBeFocusedRow = scrollBody - .getRowByRowIndex(indexOfToBeFocused); - - if (toBeFocusedRow != null) { - /* - * if the next focused row is rendered - */ - setRowFocus(toBeFocusedRow); - selectFocusedRow(ctrl, shift); - // TODO needs scrollintoview ? - sendSelectedRows(); - } else { - // scroll down by pixels and return, to wait for - // new rows, then select the last item in the - // viewport - selectLastItemInNextRender = true; - multiselectPending = shift; - scrollByPagelenght(1); - } - } - } - } else { - /* No selections, go page down by scrolling */ - scrollByPagelenght(1); - } - return true; - } - - // Page Up navigation - if (keycode == getNavigationPageUpKey()) { - if (isSelectable()) { - /* - * If selectable we plagiate MSW behaviour: first scroll to the - * end of current view. If at the end, scroll down one page - * length and keep the selected row in the bottom part of - * visible area. - */ - if (!isFocusAtTheBeginningOfTable()) { - VScrollTableRow firstVisibleRowInViewPort = scrollBody - .getRowByRowIndex(firstRowInViewPort); - if (firstVisibleRowInViewPort != null - && firstVisibleRowInViewPort != focusedRow) { - // focus is not at the beginning of the table, move - // focus and select the first visible row - setRowFocus(firstVisibleRowInViewPort); - selectFocusedRow(ctrl, shift); - sendSelectedRows(); - } else { - int indexOfToBeFocused = focusedRow.getIndex() - - getFullyVisibleRowCount(); - if (indexOfToBeFocused < 0) { - indexOfToBeFocused = 0; - } - VScrollTableRow toBeFocusedRow = scrollBody - .getRowByRowIndex(indexOfToBeFocused); - - if (toBeFocusedRow != null) { // if the next focused row - // is rendered - setRowFocus(toBeFocusedRow); - selectFocusedRow(ctrl, shift); - // TODO needs scrollintoview ? - sendSelectedRows(); - } else { - // unless waiting for the next rowset already - // scroll down by pixels and return, to wait for - // new rows, then select the last item in the - // viewport - selectFirstItemInNextRender = true; - multiselectPending = shift; - scrollByPagelenght(-1); - } - } - } - } else { - /* No selections, go page up by scrolling */ - scrollByPagelenght(-1); - } - - return true; - } - - // Goto start navigation - if (keycode == getNavigationStartKey()) { - scrollBodyPanel.setScrollPosition(0); - if (isSelectable()) { - if (focusedRow != null && focusedRow.getIndex() == 0) { - return false; - } else { - VScrollTableRow rowByRowIndex = (VScrollTableRow) scrollBody - .iterator().next(); - if (rowByRowIndex.getIndex() == 0) { - setRowFocus(rowByRowIndex); - selectFocusedRow(ctrl, shift); - sendSelectedRows(); - } else { - // first row of table will come in next row fetch - if (ctrl) { - focusFirstItemInNextRender = true; - } else { - selectFirstItemInNextRender = true; - multiselectPending = shift; - } - } - } - } - return true; - } - - // Goto end navigation - if (keycode == getNavigationEndKey()) { - scrollBodyPanel.setScrollPosition(scrollBody.getOffsetHeight()); - if (isSelectable()) { - final int lastRendered = scrollBody.getLastRendered(); - if (lastRendered + 1 == totalRows) { - VScrollTableRow rowByRowIndex = scrollBody - .getRowByRowIndex(lastRendered); - if (focusedRow != rowByRowIndex) { - setRowFocus(rowByRowIndex); - selectFocusedRow(ctrl, shift); - sendSelectedRows(); - } - } else { - if (ctrl) { - focusLastItemInNextRender = true; - } else { - selectLastItemInNextRender = true; - multiselectPending = shift; - } - } - } - return true; - } - - return false; - } - - private boolean isFocusAtTheBeginningOfTable() { - return focusedRow.getIndex() == 0; - } - - private boolean isFocusAtTheEndOfTable() { - return focusedRow.getIndex() + 1 >= totalRows; - } - - private int getFullyVisibleRowCount() { - return (int) (scrollBodyPanel.getOffsetHeight() / scrollBody - .getRowHeight()); - } - - private void scrollByPagelenght(int i) { - int pixels = i * scrollBodyPanel.getOffsetHeight(); - int newPixels = scrollBodyPanel.getScrollPosition() + pixels; - if (newPixels < 0) { - newPixels = 0; - } // else if too high, NOP (all know browsers accept illegally big - // values here) - scrollBodyPanel.setScrollPosition(newPixels); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event - * .dom.client.FocusEvent) - */ - - @Override - public void onFocus(FocusEvent event) { - if (isFocusable()) { - hasFocus = true; - - // Focus a row if no row is in focus - if (focusedRow == null) { - focusRowFromBody(); - } else { - setRowFocus(focusedRow); - } - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event - * .dom.client.BlurEvent) - */ - - @Override - public void onBlur(BlurEvent event) { - hasFocus = false; - navKeyDown = false; - - if (BrowserInfo.get().isIE()) { - // IE sometimes moves focus to a clicked table cell... - Element focusedElement = Util.getIEFocusedElement(); - if (Util.getConnectorForElement(client, getParent(), focusedElement) == this) { - // ..in that case, steal the focus back to the focus handler - // but not if focus is in a child component instead (#7965) - focus(); - return; - } - } - - if (isFocusable()) { - // Unfocus any row - setRowFocus(null); - } - } - - /** - * Removes a key from a range if the key is found in a selected range - * - * @param key - * The key to remove - */ - private void removeRowFromUnsentSelectionRanges(VScrollTableRow row) { - Collection<SelectionRange> newRanges = null; - for (Iterator<SelectionRange> iterator = selectedRowRanges.iterator(); iterator - .hasNext();) { - SelectionRange range = iterator.next(); - if (range.inRange(row)) { - // Split the range if given row is in range - Collection<SelectionRange> splitranges = range.split(row); - if (newRanges == null) { - newRanges = new ArrayList<SelectionRange>(); - } - newRanges.addAll(splitranges); - iterator.remove(); - } - } - if (newRanges != null) { - selectedRowRanges.addAll(newRanges); - } - } - - /** - * Can the Table be focused? - * - * @return True if the table can be focused, else false - */ - public boolean isFocusable() { - if (scrollBody != null && enabled) { - return !(!hasHorizontalScrollbar() && !hasVerticalScrollbar() && !isSelectable()); - } - return false; - } - - private boolean hasHorizontalScrollbar() { - return scrollBody.getOffsetWidth() > scrollBodyPanel.getOffsetWidth(); - } - - private boolean hasVerticalScrollbar() { - return scrollBody.getOffsetHeight() > scrollBodyPanel.getOffsetHeight(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.Focusable#focus() - */ - - @Override - public void focus() { - if (isFocusable()) { - scrollBodyPanel.focus(); - } - } - - /** - * Sets the proper tabIndex for scrollBodyPanel (the focusable elemen in the - * component). - * - * If the component has no explicit tabIndex a zero is given (default - * tabbing order based on dom hierarchy) or -1 if the component does not - * need to gain focus. The component needs no focus if it has no scrollabars - * (not scrollable) and not selectable. Note that in the future shortcut - * actions may need focus. - * - */ - void setProperTabIndex() { - int storedScrollTop = 0; - int storedScrollLeft = 0; - - if (BrowserInfo.get().getOperaVersion() >= 11) { - // Workaround for Opera scroll bug when changing tabIndex (#6222) - storedScrollTop = scrollBodyPanel.getScrollPosition(); - storedScrollLeft = scrollBodyPanel.getHorizontalScrollPosition(); - } - - if (tabIndex == 0 && !isFocusable()) { - scrollBodyPanel.setTabIndex(-1); - } else { - scrollBodyPanel.setTabIndex(tabIndex); - } - - if (BrowserInfo.get().getOperaVersion() >= 11) { - // Workaround for Opera scroll bug when changing tabIndex (#6222) - scrollBodyPanel.setScrollPosition(storedScrollTop); - scrollBodyPanel.setHorizontalScrollPosition(storedScrollLeft); - } - } - - public void startScrollingVelocityTimer() { - if (scrollingVelocityTimer == null) { - scrollingVelocityTimer = new Timer() { - - @Override - public void run() { - scrollingVelocity++; - } - }; - scrollingVelocityTimer.scheduleRepeating(100); - } - } - - public void cancelScrollingVelocityTimer() { - if (scrollingVelocityTimer != null) { - // Remove velocityTimer if it exists and the Table is disabled - scrollingVelocityTimer.cancel(); - scrollingVelocityTimer = null; - scrollingVelocity = 10; - } - } - - /** - * - * @param keyCode - * @return true if the given keyCode is used by the table for navigation - */ - private boolean isNavigationKey(int keyCode) { - return keyCode == getNavigationUpKey() - || keyCode == getNavigationLeftKey() - || keyCode == getNavigationRightKey() - || keyCode == getNavigationDownKey() - || keyCode == getNavigationPageUpKey() - || keyCode == getNavigationPageDownKey() - || keyCode == getNavigationEndKey() - || keyCode == getNavigationStartKey(); - } - - public void lazyRevertFocusToRow(final VScrollTableRow currentlyFocusedRow) { - Scheduler.get().scheduleFinally(new ScheduledCommand() { - - @Override - public void execute() { - if (currentlyFocusedRow != null) { - setRowFocus(currentlyFocusedRow); - } else { - VConsole.log("no row?"); - focusRowFromBody(); - } - scrollBody.ensureFocus(); - } - }); - } - - @Override - public Action[] getActions() { - if (bodyActionKeys == null) { - return new Action[] {}; - } - final Action[] actions = new Action[bodyActionKeys.length]; - for (int i = 0; i < actions.length; i++) { - final String actionKey = bodyActionKeys[i]; - Action bodyAction = new TreeAction(this, null, actionKey); - bodyAction.setCaption(getActionCaption(actionKey)); - bodyAction.setIconUrl(getActionIcon(actionKey)); - actions[i] = bodyAction; - } - return actions; - } - - @Override - public ApplicationConnection getClient() { - return client; - } - - @Override - public String getPaintableId() { - return paintableId; - } - - /** - * Add this to the element mouse down event by using element.setPropertyJSO - * ("onselectstart",applyDisableTextSelectionIEHack()); Remove it then again - * when the mouse is depressed in the mouse up event. - * - * @return Returns the JSO preventing text selection - */ - private static native JavaScriptObject getPreventTextSelectionIEHack() - /*-{ - return function(){ return false; }; - }-*/; - - public void triggerLazyColumnAdjustment(boolean now) { - lazyAdjustColumnWidths.cancel(); - if (now) { - lazyAdjustColumnWidths.run(); - } else { - lazyAdjustColumnWidths.schedule(LAZY_COLUMN_ADJUST_TIMEOUT); - } - } - - private boolean isDynamicWidth() { - ComponentConnector paintable = ConnectorMap.get(client).getConnector( - this); - return paintable.isUndefinedWidth(); - } - - private boolean isDynamicHeight() { - ComponentConnector paintable = ConnectorMap.get(client).getConnector( - this); - if (paintable == null) { - // This should be refactored. As isDynamicHeight can be called from - // a timer it is possible that the connector has been unregistered - // when this method is called, causing getConnector to return null. - return false; - } - return paintable.isUndefinedHeight(); - } - - private void debug(String msg) { - if (enableDebug) { - VConsole.error(msg); - } - } - - public Widget getWidgetForPaintable() { - return this; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetBaseConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetBaseConnector.java deleted file mode 100644 index e8a1c709c4..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetBaseConnector.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.tabsheet; - -import java.util.ArrayList; -import java.util.Iterator; - -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ui.tabsheet.TabsheetBaseConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector; - -public abstract class TabsheetBaseConnector extends - AbstractComponentContainerConnector implements Paintable { - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - getWidget().client = client; - - if (!isRealUpdate(uidl)) { - return; - } - - // Update member references - getWidget().id = uidl.getId(); - getWidget().disabled = !isEnabled(); - - // Render content - final UIDL tabs = uidl.getChildUIDL(0); - - // Widgets in the TabSheet before update - ArrayList<Widget> oldWidgets = new ArrayList<Widget>(); - for (Iterator<Widget> iterator = getWidget().getWidgetIterator(); iterator - .hasNext();) { - oldWidgets.add(iterator.next()); - } - - // Clear previous values - getWidget().tabKeys.clear(); - getWidget().disabledTabKeys.clear(); - - int index = 0; - for (final Iterator<Object> it = tabs.getChildIterator(); it.hasNext();) { - final UIDL tab = (UIDL) it.next(); - final String key = tab.getStringAttribute("key"); - final boolean selected = tab.getBooleanAttribute("selected"); - final boolean hidden = tab.getBooleanAttribute("hidden"); - - if (tab.getBooleanAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DISABLED)) { - getWidget().disabledTabKeys.add(key); - } - - getWidget().tabKeys.add(key); - - if (selected) { - getWidget().activeTabIndex = index; - } - getWidget().renderTab(tab, index, selected, hidden); - index++; - } - - int tabCount = getWidget().getTabCount(); - while (tabCount-- > index) { - getWidget().removeTab(index); - } - - for (int i = 0; i < getWidget().getTabCount(); i++) { - ComponentConnector p = getWidget().getTab(i); - // null for PlaceHolder widgets - if (p != null) { - oldWidgets.remove(p.getWidget()); - } - } - - // Detach any old tab widget, should be max 1 - for (Iterator<Widget> iterator = oldWidgets.iterator(); iterator - .hasNext();) { - Widget oldWidget = iterator.next(); - if (oldWidget.isAttached()) { - oldWidget.removeFromParent(); - } - } - - } - - @Override - public VTabsheetBase getWidget() { - return (VTabsheetBase) super.getWidget(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetConnector.java deleted file mode 100644 index 76c56ba2ed..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetConnector.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.tabsheet; - -import com.google.gwt.dom.client.Element; -import com.google.gwt.user.client.DOM; -import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.TooltipInfo; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout; -import com.vaadin.terminal.gwt.client.ui.layout.MayScrollChildren; -import com.vaadin.ui.TabSheet; - -@Connect(TabSheet.class) -public class TabsheetConnector extends TabsheetBaseConnector implements - SimpleManagedLayout, MayScrollChildren { - - // Can't use "style" as it's already in use - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - if (isRealUpdate(uidl)) { - // Handle stylename changes before generics (might affect size - // calculations) - getWidget().handleStyleNames(uidl, getState()); - } - - super.updateFromUIDL(uidl, client); - if (!isRealUpdate(uidl)) { - return; - } - - // tabs; push or not - if (!isUndefinedWidth()) { - DOM.setStyleAttribute(getWidget().tabs, "overflow", "hidden"); - } else { - getWidget().showAllTabs(); - DOM.setStyleAttribute(getWidget().tabs, "width", ""); - DOM.setStyleAttribute(getWidget().tabs, "overflow", "visible"); - getWidget().updateDynamicWidth(); - } - - if (!isUndefinedHeight()) { - // Must update height after the styles have been set - getWidget().updateContentNodeHeight(); - getWidget().updateOpenTabSize(); - } - - getWidget().iLayout(); - - // Re run relative size update to ensure optimal scrollbars - // TODO isolate to situation that visible tab has undefined height - try { - client.handleComponentRelativeSize(getWidget().tp - .getWidget(getWidget().tp.getVisibleWidget())); - } catch (Exception e) { - // Ignore, most likely empty tabsheet - } - - getWidget().waitingForResponse = false; - } - - @Override - public VTabsheet getWidget() { - return (VTabsheet) super.getWidget(); - } - - @Override - public void updateCaption(ComponentConnector component) { - /* Tabsheet does not render its children's captions */ - } - - @Override - public void layout() { - VTabsheet tabsheet = getWidget(); - - tabsheet.updateContentNodeHeight(); - - if (isUndefinedWidth()) { - tabsheet.contentNode.getStyle().setProperty("width", ""); - } else { - int contentWidth = tabsheet.getOffsetWidth() - - tabsheet.getContentAreaBorderWidth(); - if (contentWidth < 0) { - contentWidth = 0; - } - tabsheet.contentNode.getStyle().setProperty("width", - contentWidth + "px"); - } - - tabsheet.updateOpenTabSize(); - if (isUndefinedWidth()) { - tabsheet.updateDynamicWidth(); - } - - tabsheet.iLayout(); - - } - - @Override - public TooltipInfo getTooltipInfo(Element element) { - - TooltipInfo info = null; - - // Find a tooltip for the tab, if the element is a tab - if (element != getWidget().getElement()) { - Object node = Util.findWidget( - (com.google.gwt.user.client.Element) element, - VTabsheet.TabCaption.class); - - if (node != null) { - VTabsheet.TabCaption caption = (VTabsheet.TabCaption) node; - info = caption.getTooltipInfo(); - } - } - - // If not tab tooltip was found, use the default - if (info == null) { - info = super.getTooltipInfo(element); - } - - return info; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java b/client/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java deleted file mode 100644 index bec36aed4b..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java +++ /dev/null @@ -1,1250 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.tabsheet; - -import java.util.Iterator; -import java.util.List; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.dom.client.DivElement; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Visibility; -import com.google.gwt.dom.client.TableCellElement; -import com.google.gwt.dom.client.TableElement; -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.HasBlurHandlers; -import com.google.gwt.event.dom.client.HasFocusHandlers; -import com.google.gwt.event.dom.client.HasKeyDownHandlers; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.ComplexPanel; -import com.google.gwt.user.client.ui.SimplePanel; -import com.google.gwt.user.client.ui.Widget; -import com.google.gwt.user.client.ui.impl.FocusImpl; -import com.vaadin.shared.ComponentState; -import com.vaadin.shared.EventId; -import com.vaadin.shared.ui.tabsheet.TabsheetBaseConstants; -import com.vaadin.shared.ui.tabsheet.TabsheetConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.Focusable; -import com.vaadin.terminal.gwt.client.TooltipInfo; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.VCaption; -import com.vaadin.terminal.gwt.client.ui.label.VLabel; - -public class VTabsheet extends VTabsheetBase implements Focusable, - FocusHandler, BlurHandler, KeyDownHandler { - - private static class VCloseEvent { - private Tab tab; - - VCloseEvent(Tab tab) { - this.tab = tab; - } - - public Tab getTab() { - return tab; - } - - } - - private interface VCloseHandler { - public void onClose(VCloseEvent event); - } - - /** - * Representation of a single "tab" shown in the TabBar - * - */ - private static class Tab extends SimplePanel implements HasFocusHandlers, - HasBlurHandlers, HasKeyDownHandlers { - private static final String TD_CLASSNAME = CLASSNAME + "-tabitemcell"; - private static final String TD_FIRST_CLASSNAME = TD_CLASSNAME - + "-first"; - private static final String TD_SELECTED_CLASSNAME = TD_CLASSNAME - + "-selected"; - private static final String TD_SELECTED_FIRST_CLASSNAME = TD_SELECTED_CLASSNAME - + "-first"; - private static final String TD_DISABLED_CLASSNAME = TD_CLASSNAME - + "-disabled"; - - private static final String DIV_CLASSNAME = CLASSNAME + "-tabitem"; - private static final String DIV_SELECTED_CLASSNAME = DIV_CLASSNAME - + "-selected"; - - private TabCaption tabCaption; - Element td = getElement(); - private VCloseHandler closeHandler; - - private boolean enabledOnServer = true; - private Element div; - private TabBar tabBar; - private boolean hiddenOnServer = false; - - private String styleName; - - private Tab(TabBar tabBar) { - super(DOM.createTD()); - this.tabBar = tabBar; - setStyleName(td, TD_CLASSNAME); - - div = DOM.createDiv(); - focusImpl.setTabIndex(td, -1); - setStyleName(div, DIV_CLASSNAME); - - DOM.appendChild(td, div); - - tabCaption = new TabCaption(this, getTabsheet() - .getApplicationConnection()); - add(tabCaption); - - addFocusHandler(getTabsheet()); - addBlurHandler(getTabsheet()); - addKeyDownHandler(getTabsheet()); - } - - public boolean isHiddenOnServer() { - return hiddenOnServer; - } - - public void setHiddenOnServer(boolean hiddenOnServer) { - this.hiddenOnServer = hiddenOnServer; - } - - @Override - protected Element getContainerElement() { - // Attach caption element to div, not td - return div; - } - - public boolean isEnabledOnServer() { - return enabledOnServer; - } - - public void setEnabledOnServer(boolean enabled) { - enabledOnServer = enabled; - setStyleName(td, TD_DISABLED_CLASSNAME, !enabled); - if (!enabled) { - focusImpl.setTabIndex(td, -1); - } - } - - public void addClickHandler(ClickHandler handler) { - tabCaption.addClickHandler(handler); - } - - public void setCloseHandler(VCloseHandler closeHandler) { - this.closeHandler = closeHandler; - } - - /** - * Toggles the style names for the Tab - * - * @param selected - * true if the Tab is selected - * @param first - * true if the Tab is the first visible Tab - */ - public void setStyleNames(boolean selected, boolean first) { - setStyleName(td, TD_FIRST_CLASSNAME, first); - setStyleName(td, TD_SELECTED_CLASSNAME, selected); - setStyleName(td, TD_SELECTED_FIRST_CLASSNAME, selected && first); - setStyleName(div, DIV_SELECTED_CLASSNAME, selected); - } - - public void setTabulatorIndex(int tabIndex) { - focusImpl.setTabIndex(td, tabIndex); - } - - public boolean isClosable() { - return tabCaption.isClosable(); - } - - public void onClose() { - closeHandler.onClose(new VCloseEvent(this)); - } - - public VTabsheet getTabsheet() { - return tabBar.getTabsheet(); - } - - public void updateFromUIDL(UIDL tabUidl) { - tabCaption.updateCaption(tabUidl); - - // Apply the styleName set for the tab - String newStyleName = tabUidl - .getStringAttribute(TabsheetConstants.TAB_STYLE_NAME); - // Find the nth td element - if (newStyleName != null && newStyleName.length() != 0) { - if (!newStyleName.equals(styleName)) { - // If we have a new style name - if (styleName != null && styleName.length() != 0) { - // Remove old style name if present - td.removeClassName(TD_CLASSNAME + "-" + styleName); - } - // Set new style name - td.addClassName(TD_CLASSNAME + "-" + newStyleName); - styleName = newStyleName; - } - } else if (styleName != null) { - // Remove the set stylename if no stylename is present in the - // uidl - td.removeClassName(TD_CLASSNAME + "-" + styleName); - styleName = null; - } - } - - public void recalculateCaptionWidth() { - tabCaption.setWidth(tabCaption.getRequiredWidth() + "px"); - } - - @Override - public HandlerRegistration addFocusHandler(FocusHandler handler) { - return addDomHandler(handler, FocusEvent.getType()); - } - - @Override - public HandlerRegistration addBlurHandler(BlurHandler handler) { - return addDomHandler(handler, BlurEvent.getType()); - } - - @Override - public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) { - return addDomHandler(handler, KeyDownEvent.getType()); - } - - public void focus() { - focusImpl.focus(td); - } - - public void blur() { - focusImpl.blur(td); - } - } - - public static class TabCaption extends VCaption { - - private boolean closable = false; - private Element closeButton; - private Tab tab; - private ApplicationConnection client; - - TabCaption(Tab tab, ApplicationConnection client) { - super(client); - this.client = client; - this.tab = tab; - } - - public boolean updateCaption(UIDL uidl) { - if (uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DESCRIPTION)) { - setTooltipInfo(new TooltipInfo( - uidl.getStringAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DESCRIPTION), - uidl.getStringAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_ERROR_MESSAGE))); - } else { - setTooltipInfo(null); - } - - // TODO need to call this instead of super because the caption does - // not have an owner - boolean ret = updateCaptionWithoutOwner( - uidl.getStringAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_CAPTION), - uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DISABLED), - uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DESCRIPTION), - uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_ERROR_MESSAGE), - uidl.getStringAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_ICON)); - - setClosable(uidl.hasAttribute("closable")); - - return ret; - } - - private VTabsheet getTabsheet() { - return tab.getTabsheet(); - } - - @Override - public void onBrowserEvent(Event event) { - if (closable && event.getTypeInt() == Event.ONCLICK - && event.getEventTarget().cast() == closeButton) { - tab.onClose(); - event.stopPropagation(); - event.preventDefault(); - } - - super.onBrowserEvent(event); - - if (event.getTypeInt() == Event.ONLOAD) { - getTabsheet().tabSizeMightHaveChanged(getTab()); - } - } - - public Tab getTab() { - return tab; - } - - public void setClosable(boolean closable) { - this.closable = closable; - if (closable && closeButton == null) { - closeButton = DOM.createSpan(); - closeButton.setInnerHTML("×"); - closeButton - .setClassName(VTabsheet.CLASSNAME + "-caption-close"); - getElement().insertBefore(closeButton, - getElement().getLastChild()); - } else if (!closable && closeButton != null) { - getElement().removeChild(closeButton); - closeButton = null; - } - if (closable) { - addStyleDependentName("closable"); - } else { - removeStyleDependentName("closable"); - } - } - - public boolean isClosable() { - return closable; - } - - @Override - public int getRequiredWidth() { - int width = super.getRequiredWidth(); - if (closeButton != null) { - width += Util.getRequiredWidth(closeButton); - } - return width; - } - - public Element getCloseButton() { - return closeButton; - } - - } - - static class TabBar extends ComplexPanel implements ClickHandler, - VCloseHandler { - - private final Element tr = DOM.createTR(); - - private final Element spacerTd = DOM.createTD(); - - private Tab selected; - - private VTabsheet tabsheet; - - TabBar(VTabsheet tabsheet) { - this.tabsheet = tabsheet; - - Element el = DOM.createTable(); - Element tbody = DOM.createTBody(); - DOM.appendChild(el, tbody); - DOM.appendChild(tbody, tr); - setStyleName(spacerTd, CLASSNAME + "-spacertd"); - DOM.appendChild(tr, spacerTd); - DOM.appendChild(spacerTd, DOM.createDiv()); - setElement(el); - } - - @Override - public void onClose(VCloseEvent event) { - Tab tab = event.getTab(); - if (!tab.isEnabledOnServer()) { - return; - } - int tabIndex = getWidgetIndex(tab); - getTabsheet().sendTabClosedEvent(tabIndex); - } - - protected Element getContainerElement() { - return tr; - } - - public int getTabCount() { - return getWidgetCount(); - } - - public Tab addTab() { - Tab t = new Tab(this); - int tabIndex = getTabCount(); - - // Logical attach - insert(t, tr, tabIndex, true); - - if (tabIndex == 0) { - // Set the "first" style - t.setStyleNames(false, true); - } - - t.addClickHandler(this); - t.setCloseHandler(this); - - return t; - } - - @Override - public void onClick(ClickEvent event) { - TabCaption caption = (TabCaption) event.getSource(); - Element targetElement = event.getNativeEvent().getEventTarget() - .cast(); - // the tab should not be focused if the close button was clicked - if (targetElement == caption.getCloseButton()) { - return; - } - - int index = getWidgetIndex(caption.getParent()); - // IE needs explicit focus() - if (BrowserInfo.get().isIE()) { - getTabsheet().focus(); - } - getTabsheet().onTabSelected(index); - } - - public VTabsheet getTabsheet() { - return tabsheet; - } - - public Tab getTab(int index) { - if (index < 0 || index >= getTabCount()) { - return null; - } - return (Tab) super.getWidget(index); - } - - public void selectTab(int index) { - final Tab newSelected = getTab(index); - final Tab oldSelected = selected; - - newSelected.setStyleNames(true, isFirstVisibleTab(index)); - newSelected.setTabulatorIndex(getTabsheet().tabulatorIndex); - - if (oldSelected != null && oldSelected != newSelected) { - oldSelected.setStyleNames(false, - isFirstVisibleTab(getWidgetIndex(oldSelected))); - oldSelected.setTabulatorIndex(-1); - } - - // Update the field holding the currently selected tab - selected = newSelected; - - // The selected tab might need more (or less) space - newSelected.recalculateCaptionWidth(); - getTab(tabsheet.activeTabIndex).recalculateCaptionWidth(); - } - - public void removeTab(int i) { - Tab tab = getTab(i); - if (tab == null) { - return; - } - - remove(tab); - - /* - * If this widget was selected we need to unmark it as the last - * selected - */ - if (tab == selected) { - selected = null; - } - - // FIXME: Shouldn't something be selected instead? - } - - private boolean isFirstVisibleTab(int index) { - return getFirstVisibleTab() == index; - } - - /** - * Returns the index of the first visible tab - * - * @return - */ - private int getFirstVisibleTab() { - return getNextVisibleTab(-1); - } - - /** - * Find the next visible tab. Returns -1 if none is found. - * - * @param i - * @return - */ - private int getNextVisibleTab(int i) { - int tabs = getTabCount(); - do { - i++; - } while (i < tabs && getTab(i).isHiddenOnServer()); - - if (i == tabs) { - return -1; - } else { - return i; - } - } - - /** - * Find the previous visible tab. Returns -1 if none is found. - * - * @param i - * @return - */ - private int getPreviousVisibleTab(int i) { - do { - i--; - } while (i >= 0 && getTab(i).isHiddenOnServer()); - - return i; - - } - - public int scrollLeft(int currentFirstVisible) { - int prevVisible = getPreviousVisibleTab(currentFirstVisible); - if (prevVisible == -1) { - return -1; - } - - Tab newFirst = getTab(prevVisible); - newFirst.setVisible(true); - newFirst.recalculateCaptionWidth(); - - return prevVisible; - } - - public int scrollRight(int currentFirstVisible) { - int nextVisible = getNextVisibleTab(currentFirstVisible); - if (nextVisible == -1) { - return -1; - } - Tab currentFirst = getTab(currentFirstVisible); - currentFirst.setVisible(false); - currentFirst.recalculateCaptionWidth(); - return nextVisible; - } - } - - public static final String CLASSNAME = "v-tabsheet"; - - public static final String TABS_CLASSNAME = "v-tabsheet-tabcontainer"; - public static final String SCROLLER_CLASSNAME = "v-tabsheet-scroller"; - - final Element tabs; // tabbar and 'scroller' container - Tab focusedTab; - /** - * The tabindex property (position in the browser's focus cycle.) Named like - * this to avoid confusion with activeTabIndex. - */ - int tabulatorIndex = 0; - - private static final FocusImpl focusImpl = FocusImpl.getFocusImplForPanel(); - - private final Element scroller; // tab-scroller element - private final Element scrollerNext; // tab-scroller next button element - private final Element scrollerPrev; // tab-scroller prev button element - - /** - * The index of the first visible tab (when scrolled) - */ - private int scrollerIndex = 0; - - final TabBar tb = new TabBar(this); - final VTabsheetPanel tp = new VTabsheetPanel(); - final Element contentNode; - - private final Element deco; - - boolean waitingForResponse; - - private String currentStyle; - - /** - * @return Whether the tab could be selected or not. - */ - private boolean onTabSelected(final int tabIndex) { - Tab tab = tb.getTab(tabIndex); - if (client == null || disabled || waitingForResponse) { - return false; - } - if (!tab.isEnabledOnServer() || tab.isHiddenOnServer()) { - return false; - } - if (activeTabIndex != tabIndex) { - tb.selectTab(tabIndex); - - // If this TabSheet already has focus, set the new selected tab - // as focused. - if (focusedTab != null) { - focusedTab = tab; - } - - addStyleDependentName("loading"); - // Hide the current contents so a loading indicator can be shown - // instead - Widget currentlyDisplayedWidget = tp.getWidget(tp - .getVisibleWidget()); - currentlyDisplayedWidget.getElement().getParentElement().getStyle() - .setVisibility(Visibility.HIDDEN); - client.updateVariable(id, "selected", tabKeys.get(tabIndex) - .toString(), true); - waitingForResponse = true; - } - // Note that we return true when tabIndex == activeTabIndex; the active - // tab could be selected, it's just a no-op. - return true; - } - - public ApplicationConnection getApplicationConnection() { - return client; - } - - public void tabSizeMightHaveChanged(Tab tab) { - // icon onloads may change total width of tabsheet - if (isDynamicWidth()) { - updateDynamicWidth(); - } - updateTabScroller(); - - } - - void sendTabClosedEvent(int tabIndex) { - client.updateVariable(id, "close", tabKeys.get(tabIndex), true); - } - - boolean isDynamicWidth() { - ComponentConnector paintable = ConnectorMap.get(client).getConnector( - this); - return paintable.isUndefinedWidth(); - } - - boolean isDynamicHeight() { - ComponentConnector paintable = ConnectorMap.get(client).getConnector( - this); - return paintable.isUndefinedHeight(); - } - - public VTabsheet() { - super(CLASSNAME); - - addHandler(this, FocusEvent.getType()); - addHandler(this, BlurEvent.getType()); - - // Tab scrolling - DOM.setStyleAttribute(getElement(), "overflow", "hidden"); - tabs = DOM.createDiv(); - DOM.setElementProperty(tabs, "className", TABS_CLASSNAME); - scroller = DOM.createDiv(); - - DOM.setElementProperty(scroller, "className", SCROLLER_CLASSNAME); - scrollerPrev = DOM.createButton(); - DOM.setElementProperty(scrollerPrev, "className", SCROLLER_CLASSNAME - + "Prev"); - DOM.sinkEvents(scrollerPrev, Event.ONCLICK); - scrollerNext = DOM.createButton(); - DOM.setElementProperty(scrollerNext, "className", SCROLLER_CLASSNAME - + "Next"); - DOM.sinkEvents(scrollerNext, Event.ONCLICK); - DOM.appendChild(getElement(), tabs); - - // Tabs - tp.setStyleName(CLASSNAME + "-tabsheetpanel"); - contentNode = DOM.createDiv(); - - deco = DOM.createDiv(); - - addStyleDependentName("loading"); // Indicate initial progress - tb.setStyleName(CLASSNAME + "-tabs"); - DOM.setElementProperty(contentNode, "className", CLASSNAME + "-content"); - DOM.setElementProperty(deco, "className", CLASSNAME + "-deco"); - - add(tb, tabs); - DOM.appendChild(scroller, scrollerPrev); - DOM.appendChild(scroller, scrollerNext); - - DOM.appendChild(getElement(), contentNode); - add(tp, contentNode); - DOM.appendChild(getElement(), deco); - - DOM.appendChild(tabs, scroller); - - // TODO Use for Safari only. Fix annoying 1px first cell in TabBar. - // DOM.setStyleAttribute(DOM.getFirstChild(DOM.getFirstChild(DOM - // .getFirstChild(tb.getElement()))), "display", "none"); - - } - - @Override - public void onBrowserEvent(Event event) { - if (event.getTypeInt() == Event.ONCLICK) { - // Tab scrolling - if (isScrolledTabs() && DOM.eventGetTarget(event) == scrollerPrev) { - int newFirstIndex = tb.scrollLeft(scrollerIndex); - if (newFirstIndex != -1) { - scrollerIndex = newFirstIndex; - updateTabScroller(); - } - return; - } else if (isClippedTabs() - && DOM.eventGetTarget(event) == scrollerNext) { - int newFirstIndex = tb.scrollRight(scrollerIndex); - - if (newFirstIndex != -1) { - scrollerIndex = newFirstIndex; - updateTabScroller(); - } - return; - } - } - super.onBrowserEvent(event); - } - - /** - * Checks if the tab with the selected index has been scrolled out of the - * view (on the left side). - * - * @param index - * @return - */ - private boolean scrolledOutOfView(int index) { - return scrollerIndex > index; - } - - void handleStyleNames(UIDL uidl, ComponentState state) { - // Add proper stylenames for all elements (easier to prevent unwanted - // style inheritance) - if (state.hasStyles()) { - final List<String> styles = state.getStyles(); - if (!currentStyle.equals(styles.toString())) { - currentStyle = styles.toString(); - final String tabsBaseClass = TABS_CLASSNAME; - String tabsClass = tabsBaseClass; - final String contentBaseClass = CLASSNAME + "-content"; - String contentClass = contentBaseClass; - final String decoBaseClass = CLASSNAME + "-deco"; - String decoClass = decoBaseClass; - for (String style : styles) { - tb.addStyleDependentName(style); - tabsClass += " " + tabsBaseClass + "-" + style; - contentClass += " " + contentBaseClass + "-" + style; - decoClass += " " + decoBaseClass + "-" + style; - } - DOM.setElementProperty(tabs, "className", tabsClass); - DOM.setElementProperty(contentNode, "className", contentClass); - DOM.setElementProperty(deco, "className", decoClass); - borderW = -1; - } - } else { - tb.setStyleName(CLASSNAME + "-tabs"); - DOM.setElementProperty(tabs, "className", TABS_CLASSNAME); - DOM.setElementProperty(contentNode, "className", CLASSNAME - + "-content"); - DOM.setElementProperty(deco, "className", CLASSNAME + "-deco"); - } - - if (uidl.hasAttribute("hidetabs")) { - tb.setVisible(false); - addStyleName(CLASSNAME + "-hidetabs"); - } else { - tb.setVisible(true); - removeStyleName(CLASSNAME + "-hidetabs"); - } - } - - void updateDynamicWidth() { - // Find width consumed by tabs - TableCellElement spacerCell = ((TableElement) tb.getElement().cast()) - .getRows().getItem(0).getCells().getItem(tb.getTabCount()); - - int spacerWidth = spacerCell.getOffsetWidth(); - DivElement div = (DivElement) spacerCell.getFirstChildElement(); - - int spacerMinWidth = spacerCell.getOffsetWidth() - div.getOffsetWidth(); - - int tabsWidth = tb.getOffsetWidth() - spacerWidth + spacerMinWidth; - - // Find content width - Style style = tp.getElement().getStyle(); - String overflow = style.getProperty("overflow"); - style.setProperty("overflow", "hidden"); - style.setPropertyPx("width", tabsWidth); - - boolean hasTabs = tp.getWidgetCount() > 0; - - Style wrapperstyle = null; - if (hasTabs) { - wrapperstyle = tp.getWidget(tp.getVisibleWidget()).getElement() - .getParentElement().getStyle(); - wrapperstyle.setPropertyPx("width", tabsWidth); - } - // Get content width from actual widget - - int contentWidth = 0; - if (hasTabs) { - contentWidth = tp.getWidget(tp.getVisibleWidget()).getOffsetWidth(); - } - style.setProperty("overflow", overflow); - - // Set widths to max(tabs,content) - if (tabsWidth < contentWidth) { - tabsWidth = contentWidth; - } - - int outerWidth = tabsWidth + getContentAreaBorderWidth(); - - tabs.getStyle().setPropertyPx("width", outerWidth); - style.setPropertyPx("width", tabsWidth); - if (hasTabs) { - wrapperstyle.setPropertyPx("width", tabsWidth); - } - - contentNode.getStyle().setPropertyPx("width", tabsWidth); - super.setWidth(outerWidth + "px"); - updateOpenTabSize(); - } - - @Override - protected void renderTab(final UIDL tabUidl, int index, boolean selected, - boolean hidden) { - Tab tab = tb.getTab(index); - if (tab == null) { - tab = tb.addTab(); - } - tab.updateFromUIDL(tabUidl); - tab.setEnabledOnServer((!disabledTabKeys.contains(tabKeys.get(index)))); - tab.setHiddenOnServer(hidden); - - if (scrolledOutOfView(index)) { - // Should not set tabs visible if they are scrolled out of view - hidden = true; - } - // Set the current visibility of the tab (in the browser) - tab.setVisible(!hidden); - - /* - * Force the width of the caption container so the content will not wrap - * and tabs won't be too narrow in certain browsers - */ - tab.recalculateCaptionWidth(); - - UIDL tabContentUIDL = null; - ComponentConnector tabContentPaintable = null; - Widget tabContentWidget = null; - if (tabUidl.getChildCount() > 0) { - tabContentUIDL = tabUidl.getChildUIDL(0); - tabContentPaintable = client.getPaintable(tabContentUIDL); - tabContentWidget = tabContentPaintable.getWidget(); - } - - if (tabContentPaintable != null) { - /* This is a tab with content information */ - - int oldIndex = tp.getWidgetIndex(tabContentWidget); - if (oldIndex != -1 && oldIndex != index) { - /* - * The tab has previously been rendered in another position so - * we must move the cached content to correct position - */ - tp.insert(tabContentWidget, index); - } - } else { - /* A tab whose content has not yet been loaded */ - - /* - * Make sure there is a corresponding empty tab in tp. The same - * operation as the moving above but for not-loaded tabs. - */ - if (index < tp.getWidgetCount()) { - Widget oldWidget = tp.getWidget(index); - if (!(oldWidget instanceof PlaceHolder)) { - tp.insert(new PlaceHolder(), index); - } - } - - } - - if (selected) { - renderContent(tabContentUIDL); - tb.selectTab(index); - } else { - if (tabContentUIDL != null) { - // updating a drawn child on hidden tab - if (tp.getWidgetIndex(tabContentWidget) < 0) { - tp.insert(tabContentWidget, index); - } - } else if (tp.getWidgetCount() <= index) { - tp.add(new PlaceHolder()); - } - } - } - - public class PlaceHolder extends VLabel { - public PlaceHolder() { - super(""); - } - } - - @Override - protected void selectTab(int index, final UIDL contentUidl) { - if (index != activeTabIndex) { - activeTabIndex = index; - tb.selectTab(activeTabIndex); - } - renderContent(contentUidl); - } - - private void renderContent(final UIDL contentUIDL) { - final ComponentConnector content = client.getPaintable(contentUIDL); - Widget newWidget = content.getWidget(); - if (tp.getWidgetCount() > activeTabIndex) { - Widget old = tp.getWidget(activeTabIndex); - if (old != newWidget) { - tp.remove(activeTabIndex); - ConnectorMap paintableMap = ConnectorMap.get(client); - if (paintableMap.isConnector(old)) { - paintableMap.unregisterConnector(paintableMap - .getConnector(old)); - } - tp.insert(content.getWidget(), activeTabIndex); - } - } else { - tp.add(content.getWidget()); - } - - tp.showWidget(activeTabIndex); - - VTabsheet.this.iLayout(); - /* - * The size of a cached, relative sized component must be updated to - * report correct size to updateOpenTabSize(). - */ - if (contentUIDL.getBooleanAttribute("cached")) { - client.handleComponentRelativeSize(content.getWidget()); - } - updateOpenTabSize(); - VTabsheet.this.removeStyleDependentName("loading"); - } - - void updateContentNodeHeight() { - if (!isDynamicHeight()) { - int contentHeight = getOffsetHeight(); - contentHeight -= DOM.getElementPropertyInt(deco, "offsetHeight"); - contentHeight -= tb.getOffsetHeight(); - if (contentHeight < 0) { - contentHeight = 0; - } - - // Set proper values for content element - DOM.setStyleAttribute(contentNode, "height", contentHeight + "px"); - } else { - DOM.setStyleAttribute(contentNode, "height", ""); - } - } - - public void iLayout() { - updateTabScroller(); - } - - /** - * Sets the size of the visible tab (component). As the tab is set to - * position: absolute (to work around a firefox flickering bug) we must keep - * this up-to-date by hand. - */ - void updateOpenTabSize() { - /* - * The overflow=auto element must have a height specified, otherwise it - * will be just as high as the contents and no scrollbars will appear - */ - int height = -1; - int width = -1; - int minWidth = 0; - - if (!isDynamicHeight()) { - height = contentNode.getOffsetHeight(); - } - if (!isDynamicWidth()) { - width = contentNode.getOffsetWidth() - getContentAreaBorderWidth(); - } else { - /* - * If the tabbar is wider than the content we need to use the tabbar - * width as minimum width so scrollbars get placed correctly (at the - * right edge). - */ - minWidth = tb.getOffsetWidth() - getContentAreaBorderWidth(); - } - tp.fixVisibleTabSize(width, height, minWidth); - - } - - /** - * Layouts the tab-scroller elements, and applies styles. - */ - private void updateTabScroller() { - if (!isDynamicWidth()) { - ComponentConnector paintable = ConnectorMap.get(client) - .getConnector(this); - DOM.setStyleAttribute(tabs, "width", paintable.getState() - .getWidth()); - } - - // Make sure scrollerIndex is valid - if (scrollerIndex < 0 || scrollerIndex > tb.getTabCount()) { - scrollerIndex = tb.getFirstVisibleTab(); - } else if (tb.getTabCount() > 0 - && tb.getTab(scrollerIndex).isHiddenOnServer()) { - scrollerIndex = tb.getNextVisibleTab(scrollerIndex); - } - - boolean scrolled = isScrolledTabs(); - boolean clipped = isClippedTabs(); - if (tb.getTabCount() > 0 && tb.isVisible() && (scrolled || clipped)) { - DOM.setStyleAttribute(scroller, "display", ""); - DOM.setElementProperty(scrollerPrev, "className", - SCROLLER_CLASSNAME + (scrolled ? "Prev" : "Prev-disabled")); - DOM.setElementProperty(scrollerNext, "className", - SCROLLER_CLASSNAME + (clipped ? "Next" : "Next-disabled")); - } else { - DOM.setStyleAttribute(scroller, "display", "none"); - } - - if (BrowserInfo.get().isSafari()) { - // fix tab height for safari, bugs sometimes if tabs contain icons - String property = tabs.getStyle().getProperty("height"); - if (property == null || property.equals("")) { - tabs.getStyle().setPropertyPx("height", tb.getOffsetHeight()); - } - /* - * another hack for webkits. tabscroller sometimes drops without - * "shaking it" reproducable in - * com.vaadin.tests.components.tabsheet.TabSheetIcons - */ - final Style style = scroller.getStyle(); - style.setProperty("whiteSpace", "normal"); - Scheduler.get().scheduleDeferred(new Command() { - - @Override - public void execute() { - style.setProperty("whiteSpace", ""); - } - }); - } - - } - - void showAllTabs() { - scrollerIndex = tb.getFirstVisibleTab(); - for (int i = 0; i < tb.getTabCount(); i++) { - Tab t = tb.getTab(i); - if (!t.isHiddenOnServer()) { - t.setVisible(true); - } - } - } - - private boolean isScrolledTabs() { - return scrollerIndex > tb.getFirstVisibleTab(); - } - - private boolean isClippedTabs() { - return (tb.getOffsetWidth() - DOM.getElementPropertyInt((Element) tb - .getContainerElement().getLastChild().cast(), "offsetWidth")) > getOffsetWidth() - - (isScrolledTabs() ? scroller.getOffsetWidth() : 0); - } - - private boolean isClipped(Tab tab) { - return tab.getAbsoluteLeft() + tab.getOffsetWidth() > getAbsoluteLeft() - + getOffsetWidth() - scroller.getOffsetWidth(); - } - - @Override - protected void clearPaintables() { - - int i = tb.getTabCount(); - while (i > 0) { - tb.removeTab(--i); - } - tp.clear(); - - } - - @Override - protected Iterator<Widget> getWidgetIterator() { - return tp.iterator(); - } - - private int borderW = -1; - - int getContentAreaBorderWidth() { - if (borderW < 0) { - borderW = Util.measureHorizontalBorder(contentNode); - } - return borderW; - } - - @Override - protected int getTabCount() { - return tb.getTabCount(); - } - - @Override - protected ComponentConnector getTab(int index) { - if (tp.getWidgetCount() > index) { - Widget widget = tp.getWidget(index); - return ConnectorMap.get(client).getConnector(widget); - } - return null; - } - - @Override - protected void removeTab(int index) { - tb.removeTab(index); - /* - * This must be checked because renderTab automatically removes the - * active tab content when it changes - */ - if (tp.getWidgetCount() > index) { - tp.remove(index); - } - } - - @Override - public void onBlur(BlurEvent event) { - if (focusedTab != null && event.getSource() instanceof Tab) { - focusedTab = null; - if (client.hasEventListeners(this, EventId.BLUR)) { - client.updateVariable(id, EventId.BLUR, "", true); - } - } - } - - @Override - public void onFocus(FocusEvent event) { - if (focusedTab == null && event.getSource() instanceof Tab) { - focusedTab = (Tab) event.getSource(); - if (client.hasEventListeners(this, EventId.FOCUS)) { - client.updateVariable(id, EventId.FOCUS, "", true); - } - } - } - - @Override - public void focus() { - tb.getTab(activeTabIndex).focus(); - } - - public void blur() { - tb.getTab(activeTabIndex).blur(); - } - - @Override - public void onKeyDown(KeyDownEvent event) { - if (event.getSource() instanceof Tab) { - int keycode = event.getNativeEvent().getKeyCode(); - - if (keycode == getPreviousTabKey()) { - selectPreviousTab(); - } else if (keycode == getNextTabKey()) { - selectNextTab(); - } else if (keycode == getCloseTabKey()) { - Tab tab = tb.getTab(activeTabIndex); - if (tab.isClosable()) { - tab.onClose(); - } - } - } - } - - /** - * @return The key code of the keyboard shortcut that selects the previous - * tab in a focused tabsheet. - */ - protected int getPreviousTabKey() { - return KeyCodes.KEY_LEFT; - } - - /** - * @return The key code of the keyboard shortcut that selects the next tab - * in a focused tabsheet. - */ - protected int getNextTabKey() { - return KeyCodes.KEY_RIGHT; - } - - /** - * @return The key code of the keyboard shortcut that closes the currently - * selected tab in a focused tabsheet. - */ - protected int getCloseTabKey() { - return KeyCodes.KEY_DELETE; - } - - private void selectPreviousTab() { - int newTabIndex = activeTabIndex; - // Find the previous visible and enabled tab if any. - do { - newTabIndex--; - } while (newTabIndex >= 0 && !onTabSelected(newTabIndex)); - - if (newTabIndex >= 0) { - activeTabIndex = newTabIndex; - if (isScrolledTabs()) { - // Scroll until the new active tab is visible - int newScrollerIndex = scrollerIndex; - while (tb.getTab(activeTabIndex).getAbsoluteLeft() < getAbsoluteLeft() - && newScrollerIndex != -1) { - newScrollerIndex = tb.scrollLeft(newScrollerIndex); - } - scrollerIndex = newScrollerIndex; - updateTabScroller(); - } - } - } - - private void selectNextTab() { - int newTabIndex = activeTabIndex; - // Find the next visible and enabled tab if any. - do { - newTabIndex++; - } while (newTabIndex < getTabCount() && !onTabSelected(newTabIndex)); - - if (newTabIndex < getTabCount()) { - activeTabIndex = newTabIndex; - if (isClippedTabs()) { - // Scroll until the new active tab is completely visible - int newScrollerIndex = scrollerIndex; - while (isClipped(tb.getTab(activeTabIndex)) - && newScrollerIndex != -1) { - newScrollerIndex = tb.scrollRight(newScrollerIndex); - } - scrollerIndex = newScrollerIndex; - updateTabScroller(); - } - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetBase.java b/client/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetBase.java deleted file mode 100644 index b9a68dc4af..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetBase.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.tabsheet; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.ui.ComplexPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.UIDL; - -public abstract class VTabsheetBase extends ComplexPanel { - - protected String id; - protected ApplicationConnection client; - - protected final ArrayList<String> tabKeys = new ArrayList<String>(); - protected int activeTabIndex = 0; - protected boolean disabled; - protected boolean readonly; - protected Set<String> disabledTabKeys = new HashSet<String>(); - - public VTabsheetBase(String classname) { - setElement(DOM.createDiv()); - setStyleName(classname); - } - - /** - * @return a list of currently shown Widgets - */ - abstract protected Iterator<Widget> getWidgetIterator(); - - /** - * Clears current tabs and contents - */ - abstract protected void clearPaintables(); - - /** - * Implement in extending classes. This method should render needed elements - * and set the visibility of the tab according to the 'selected' parameter. - */ - protected abstract void renderTab(final UIDL tabUidl, int index, - boolean selected, boolean hidden); - - /** - * Implement in extending classes. This method should render any previously - * non-cached content and set the activeTabIndex property to the specified - * index. - */ - protected abstract void selectTab(int index, final UIDL contentUidl); - - /** - * Implement in extending classes. This method should return the number of - * tabs currently rendered. - */ - protected abstract int getTabCount(); - - /** - * Implement in extending classes. This method should return the Paintable - * corresponding to the given index. - */ - protected abstract ComponentConnector getTab(int index); - - /** - * Implement in extending classes. This method should remove the rendered - * tab with the specified index. - */ - protected abstract void removeTab(int index); -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java b/client/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java deleted file mode 100644 index e48f7ffa1f..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.tabsheet; - -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.ComplexPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate; -import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate.TouchScrollHandler; - -/** - * A panel that displays all of its child widgets in a 'deck', where only one - * can be visible at a time. It is used by - * {@link com.vaadin.terminal.gwt.client.ui.tabsheet.VTabsheet}. - * - * This class has the same basic functionality as the GWT DeckPanel - * {@link com.google.gwt.user.client.ui.DeckPanel}, with the exception that it - * doesn't manipulate the child widgets' width and height attributes. - */ -public class VTabsheetPanel extends ComplexPanel { - - private Widget visibleWidget; - - private final TouchScrollHandler touchScrollHandler; - - /** - * Creates an empty tabsheet panel. - */ - public VTabsheetPanel() { - setElement(DOM.createDiv()); - touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this); - } - - /** - * Adds the specified widget to the deck. - * - * @param w - * the widget to be added - */ - @Override - public void add(Widget w) { - Element el = createContainerElement(); - DOM.appendChild(getElement(), el); - super.add(w, el); - } - - private Element createContainerElement() { - Element el = DOM.createDiv(); - DOM.setStyleAttribute(el, "position", "absolute"); - hide(el); - touchScrollHandler.addElement(el); - return el; - } - - /** - * Gets the index of the currently-visible widget. - * - * @return the visible widget's index - */ - public int getVisibleWidget() { - return getWidgetIndex(visibleWidget); - } - - /** - * Inserts a widget before the specified index. - * - * @param w - * the widget to be inserted - * @param beforeIndex - * the index before which it will be inserted - * @throws IndexOutOfBoundsException - * if <code>beforeIndex</code> is out of range - */ - public void insert(Widget w, int beforeIndex) { - Element el = createContainerElement(); - DOM.insertChild(getElement(), el, beforeIndex); - super.insert(w, el, beforeIndex, false); - } - - @Override - public boolean remove(Widget w) { - Element child = w.getElement(); - Element parent = null; - if (child != null) { - parent = DOM.getParent(child); - } - final boolean removed = super.remove(w); - if (removed) { - if (visibleWidget == w) { - visibleWidget = null; - } - if (parent != null) { - DOM.removeChild(getElement(), parent); - } - touchScrollHandler.removeElement(parent); - } - return removed; - } - - /** - * Shows the widget at the specified index. This causes the currently- - * visible widget to be hidden. - * - * @param index - * the index of the widget to be shown - */ - public void showWidget(int index) { - checkIndexBoundsForAccess(index); - Widget newVisible = getWidget(index); - if (visibleWidget != newVisible) { - if (visibleWidget != null) { - hide(DOM.getParent(visibleWidget.getElement())); - } - visibleWidget = newVisible; - touchScrollHandler.setElements(visibleWidget.getElement() - .getParentElement()); - } - // Always ensure the selected tab is visible. If server prevents a tab - // change we might end up here with visibleWidget == newVisible but its - // parent is still hidden. - unHide(DOM.getParent(visibleWidget.getElement())); - } - - private void hide(Element e) { - DOM.setStyleAttribute(e, "visibility", "hidden"); - DOM.setStyleAttribute(e, "top", "-100000px"); - DOM.setStyleAttribute(e, "left", "-100000px"); - } - - private void unHide(Element e) { - DOM.setStyleAttribute(e, "top", "0px"); - DOM.setStyleAttribute(e, "left", "0px"); - DOM.setStyleAttribute(e, "visibility", ""); - } - - public void fixVisibleTabSize(int width, int height, int minWidth) { - if (visibleWidget == null) { - return; - } - - boolean dynamicHeight = false; - - if (height < 0) { - height = visibleWidget.getOffsetHeight(); - dynamicHeight = true; - } - if (width < 0) { - width = visibleWidget.getOffsetWidth(); - } - if (width < minWidth) { - width = minWidth; - } - - Element wrapperDiv = (Element) visibleWidget.getElement() - .getParentElement(); - - // width first - getElement().getStyle().setPropertyPx("width", width); - wrapperDiv.getStyle().setPropertyPx("width", width); - - if (dynamicHeight) { - // height of widget might have changed due wrapping - height = visibleWidget.getOffsetHeight(); - } - // v-tabsheet-tabsheetpanel height - getElement().getStyle().setPropertyPx("height", height); - - // widget wrapper height - if (dynamicHeight) { - wrapperDiv.getStyle().clearHeight(); - } else { - // widget wrapper height - wrapperDiv.getStyle().setPropertyPx("height", height); - } - } - - public void replaceComponent(Widget oldComponent, Widget newComponent) { - boolean isVisible = (visibleWidget == oldComponent); - int widgetIndex = getWidgetIndex(oldComponent); - remove(oldComponent); - insert(newComponent, widgetIndex); - if (isVisible) { - showWidget(widgetIndex); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/textarea/TextAreaConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/textarea/TextAreaConnector.java deleted file mode 100644 index d5abed4fa9..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/textarea/TextAreaConnector.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.textarea; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.textarea.TextAreaState; -import com.vaadin.terminal.gwt.client.ui.textfield.TextFieldConnector; -import com.vaadin.ui.TextArea; - -@Connect(TextArea.class) -public class TextAreaConnector extends TextFieldConnector { - - @Override - public TextAreaState getState() { - return (TextAreaState) super.getState(); - } - - @Override - public VTextArea getWidget() { - return (VTextArea) super.getWidget(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/textarea/VTextArea.java b/client/src/com/vaadin/terminal/gwt/client/ui/textarea/VTextArea.java deleted file mode 100644 index e1df1ba0db..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/textarea/VTextArea.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.textarea; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.dom.client.Style.Overflow; -import com.google.gwt.dom.client.TextAreaElement; -import com.google.gwt.event.dom.client.ChangeEvent; -import com.google.gwt.event.dom.client.ChangeHandler; -import com.google.gwt.event.dom.client.KeyUpEvent; -import com.google.gwt.event.dom.client.KeyUpHandler; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Event; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.textfield.VTextField; - -/** - * This class represents a multiline textfield (textarea). - * - * TODO consider replacing this with a RichTextArea based implementation. IE - * does not support CSS height for textareas in Strict mode :-( - * - * @author Vaadin Ltd. - * - */ -public class VTextArea extends VTextField { - public static final String CLASSNAME = "v-textarea"; - private boolean wordwrap = true; - private MaxLengthHandler maxLengthHandler = new MaxLengthHandler(); - private boolean browserSupportsMaxLengthAttribute = browserSupportsMaxLengthAttribute(); - - public VTextArea() { - super(DOM.createTextArea()); - setStyleName(CLASSNAME); - if (!browserSupportsMaxLengthAttribute) { - addKeyUpHandler(maxLengthHandler); - addChangeHandler(maxLengthHandler); - sinkEvents(Event.ONPASTE); - } - } - - public TextAreaElement getTextAreaElement() { - return super.getElement().cast(); - } - - public void setRows(int rows) { - getTextAreaElement().setRows(rows); - } - - private class MaxLengthHandler implements KeyUpHandler, ChangeHandler { - - @Override - public void onKeyUp(KeyUpEvent event) { - enforceMaxLength(); - } - - public void onPaste(Event event) { - enforceMaxLength(); - } - - @Override - public void onChange(ChangeEvent event) { - // Opera does not support paste events so this enforces max length - // for Opera. - enforceMaxLength(); - } - - } - - protected void enforceMaxLength() { - if (getMaxLength() >= 0) { - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - if (getText().length() > getMaxLength()) { - setText(getText().substring(0, getMaxLength())); - } - } - }); - } - } - - protected boolean browserSupportsMaxLengthAttribute() { - BrowserInfo info = BrowserInfo.get(); - if (info.isFirefox() && info.isBrowserVersionNewerOrEqual(4, 0)) { - return true; - } - if (info.isSafari() && info.isBrowserVersionNewerOrEqual(5, 0)) { - return true; - } - if (info.isIE() && info.isBrowserVersionNewerOrEqual(10, 0)) { - return true; - } - if (info.isAndroid() && info.isBrowserVersionNewerOrEqual(2, 3)) { - return true; - } - return false; - } - - @Override - protected void updateMaxLength(int maxLength) { - if (browserSupportsMaxLengthAttribute) { - super.updateMaxLength(maxLength); - } else { - // Events handled by MaxLengthHandler. This call enforces max length - // when the max length value has changed - enforceMaxLength(); - } - } - - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - if (event.getTypeInt() == Event.ONPASTE) { - maxLengthHandler.onPaste(event); - } - } - - - @Override - public int getCursorPos() { - // This is needed so that TextBoxImplIE6 is used to return the correct - // position for old Internet Explorer versions where it has to be - // detected in a different way. - return getImpl().getTextAreaCursorPos(getElement()); - } - - @Override - protected void setMaxLengthToElement(int newMaxLength) { - // There is no maxlength property for textarea. The maximum length is - // enforced by the KEYUP handler - - } - - public void setWordwrap(boolean wordwrap) { - if (wordwrap == this.wordwrap) { - return; // No change - } - - if (wordwrap) { - getElement().removeAttribute("wrap"); - getElement().getStyle().clearOverflow(); - } else { - getElement().setAttribute("wrap", "off"); - getElement().getStyle().setOverflow(Overflow.AUTO); - } - if (BrowserInfo.get().isOpera()) { - // Opera fails to dynamically update the wrap attribute so we detach - // and reattach the whole TextArea. - Util.detachAttach(getElement()); - } - this.wordwrap = wordwrap; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/textfield/TextFieldConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/textfield/TextFieldConnector.java deleted file mode 100644 index d16c01bd27..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/textfield/TextFieldConnector.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.textfield; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.Event; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.shared.ui.textfield.AbstractTextFieldState; -import com.vaadin.shared.ui.textfield.TextFieldConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.AbstractFieldConnector; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutActionListener; -import com.vaadin.ui.TextField; - -@Connect(value = TextField.class, loadStyle = LoadStyle.EAGER) -public class TextFieldConnector extends AbstractFieldConnector implements - Paintable, BeforeShortcutActionListener { - - @Override - public AbstractTextFieldState getState() { - return (AbstractTextFieldState) super.getState(); - } - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - // Save details - getWidget().client = client; - getWidget().paintableId = uidl.getId(); - - if (!isRealUpdate(uidl)) { - return; - } - - getWidget().setReadOnly(isReadOnly()); - - getWidget().setInputPrompt(getState().getInputPrompt()); - getWidget().setMaxLength(getState().getMaxLength()); - getWidget().setImmediate(getState().isImmediate()); - - getWidget().listenTextChangeEvents = hasEventListener("ie"); - if (getWidget().listenTextChangeEvents) { - getWidget().textChangeEventMode = uidl - .getStringAttribute(TextFieldConstants.ATTR_TEXTCHANGE_EVENTMODE); - if (getWidget().textChangeEventMode - .equals(TextFieldConstants.TEXTCHANGE_MODE_EAGER)) { - getWidget().textChangeEventTimeout = 1; - } else { - getWidget().textChangeEventTimeout = uidl - .getIntAttribute(TextFieldConstants.ATTR_TEXTCHANGE_TIMEOUT); - if (getWidget().textChangeEventTimeout < 1) { - // Sanitize and allow lazy/timeout with timeout set to 0 to - // work as eager - getWidget().textChangeEventTimeout = 1; - } - } - getWidget().sinkEvents(VTextField.TEXTCHANGE_EVENTS); - getWidget().attachCutEventListener(getWidget().getElement()); - } - getWidget().setColumns(getState().getColumns()); - - final String text = getState().getText(); - - /* - * We skip the text content update if field has been repainted, but text - * has not been changed. Additional sanity check verifies there is no - * change in the que (in which case we count more on the server side - * value). - */ - if (!(uidl - .getBooleanAttribute(TextFieldConstants.ATTR_NO_VALUE_CHANGE_BETWEEN_PAINTS) - && getWidget().valueBeforeEdit != null && text - .equals(getWidget().valueBeforeEdit))) { - getWidget().updateFieldContent(text); - } - - if (uidl.hasAttribute("selpos")) { - final int pos = uidl.getIntAttribute("selpos"); - final int length = uidl.getIntAttribute("sellen"); - /* - * Gecko defers setting the text so we need to defer the selection. - */ - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - getWidget().setSelectionRange(pos, length); - } - }); - } - } - - @Override - public VTextField getWidget() { - return (VTextField) super.getWidget(); - } - - @Override - public void onBeforeShortcutAction(Event e) { - getWidget().valueChange(false); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/textfield/VTextField.java b/client/src/com/vaadin/terminal/gwt/client/ui/textfield/VTextField.java deleted file mode 100644 index 8f07c67c96..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/textfield/VTextField.java +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.textfield; - -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.ChangeEvent; -import com.google.gwt.event.dom.client.ChangeHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.ui.TextBoxBase; -import com.vaadin.shared.EventId; -import com.vaadin.shared.ui.textfield.TextFieldConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.Field; - -/** - * This class represents a basic text input field with one row. - * - * @author Vaadin Ltd. - * - */ -public class VTextField extends TextBoxBase implements Field, ChangeHandler, -FocusHandler, BlurHandler, KeyDownHandler { - - /** - * The input node CSS classname. - */ - public static final String CLASSNAME = "v-textfield"; - /** - * This CSS classname is added to the input node on hover. - */ - public static final String CLASSNAME_FOCUS = "focus"; - - protected String paintableId; - - protected ApplicationConnection client; - - protected String valueBeforeEdit = null; - - /** - * Set to false if a text change event has been sent since the last value - * change event. This means that {@link #valueBeforeEdit} should not be - * trusted when determining whether a text change even should be sent. - */ - private boolean valueBeforeEditIsSynced = true; - - private boolean immediate = false; - private int maxLength = -1; - - private static final String CLASSNAME_PROMPT = "prompt"; - private static final String TEXTCHANGE_MODE_TIMEOUT = "TIMEOUT"; - - private String inputPrompt = null; - private boolean prompting = false; - private int lastCursorPos = -1; - - public VTextField() { - this(DOM.createInputText()); - } - - protected VTextField(Element node) { - super(node); - setStyleName(CLASSNAME); - addChangeHandler(this); - if (BrowserInfo.get().isIE()) { - // IE does not send change events when pressing enter in a text - // input so we handle it using a key listener instead - addKeyDownHandler(this); - } - addFocusHandler(this); - addBlurHandler(this); - } - - /* - * TODO When GWT adds ONCUT, add it there and remove workaround. See - * http://code.google.com/p/google-web-toolkit/issues/detail?id=4030 - * - * Also note that the cut/paste are not totally crossbrowsers compatible. - * E.g. in Opera mac works via context menu, but on via File->Paste/Cut. - * Opera might need the polling method for 100% working textchanceevents. - * Eager polling for a change is bit dum and heavy operation, so I guess we - * should first try to survive without. - */ - protected static final int TEXTCHANGE_EVENTS = Event.ONPASTE - | Event.KEYEVENTS | Event.ONMOUSEUP; - - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - - if (listenTextChangeEvents - && (event.getTypeInt() & TEXTCHANGE_EVENTS) == event - .getTypeInt()) { - deferTextChangeEvent(); - } - - } - - /* - * TODO optimize this so that only changes are sent + make the value change - * event just a flag that moves the current text to value - */ - private String lastTextChangeString = null; - - private String getLastCommunicatedString() { - return lastTextChangeString; - } - - private void communicateTextValueToServer() { - String text = getText(); - if (prompting) { - // Input prompt visible, text is actually "" - text = ""; - } - if (!text.equals(getLastCommunicatedString())) { - if (valueBeforeEditIsSynced && text.equals(valueBeforeEdit)) { - /* - * Value change for the current text has been enqueued since the - * last text change event was sent, but we can't know that it - * has been sent to the server. Ensure that all pending changes - * are sent now. Sending a value change without a text change - * will simulate a TextChangeEvent on the server. - */ - client.sendPendingVariableChanges(); - } else { - // Default case - just send an immediate text change message - client.updateVariable(paintableId, - TextFieldConstants.VAR_CUR_TEXT, text, true); - - // Shouldn't investigate valueBeforeEdit to avoid duplicate text - // change events as the states are not in sync any more - valueBeforeEditIsSynced = false; - } - lastTextChangeString = text; - } - } - - private Timer textChangeEventTrigger = new Timer() { - - @Override - public void run() { - if (isAttached()) { - updateCursorPosition(); - communicateTextValueToServer(); - scheduled = false; - } - } - }; - private boolean scheduled = false; - protected boolean listenTextChangeEvents; - protected String textChangeEventMode; - protected int textChangeEventTimeout; - - private void deferTextChangeEvent() { - if (textChangeEventMode.equals(TEXTCHANGE_MODE_TIMEOUT) && scheduled) { - return; - } else { - textChangeEventTrigger.cancel(); - } - textChangeEventTrigger.schedule(getTextChangeEventTimeout()); - scheduled = true; - } - - private int getTextChangeEventTimeout() { - return textChangeEventTimeout; - } - - @Override - public void setReadOnly(boolean readOnly) { - boolean wasReadOnly = isReadOnly(); - - if (readOnly) { - setTabIndex(-1); - } else if (wasReadOnly && !readOnly && getTabIndex() == -1) { - /* - * Need to manually set tab index to 0 since server will not send - * the tab index if it is 0. - */ - setTabIndex(0); - } - - super.setReadOnly(readOnly); - } - - protected void updateFieldContent(final String text) { - setPrompting(inputPrompt != null && focusedTextField != this - && (text.equals(""))); - - String fieldValue; - if (prompting) { - fieldValue = isReadOnly() ? "" : inputPrompt; - addStyleDependentName(CLASSNAME_PROMPT); - } else { - fieldValue = text; - removeStyleDependentName(CLASSNAME_PROMPT); - } - setText(fieldValue); - - lastTextChangeString = valueBeforeEdit = text; - valueBeforeEditIsSynced = true; - } - - protected void onCut() { - if (listenTextChangeEvents) { - deferTextChangeEvent(); - } - } - - protected native void attachCutEventListener(Element el) - /*-{ - var me = this; - el.oncut = $entry(function() { - me.@com.vaadin.terminal.gwt.client.ui.textfield.VTextField::onCut()(); - }); - }-*/; - - protected native void detachCutEventListener(Element el) - /*-{ - el.oncut = null; - }-*/; - - @Override - protected void onDetach() { - super.onDetach(); - detachCutEventListener(getElement()); - if (focusedTextField == this) { - focusedTextField = null; - } - } - - @Override - protected void onAttach() { - super.onAttach(); - if (listenTextChangeEvents) { - detachCutEventListener(getElement()); - } - } - - protected void setMaxLength(int newMaxLength) { - if (newMaxLength >= 0 && newMaxLength != maxLength) { - maxLength = newMaxLength; - updateMaxLength(maxLength); - } else if (maxLength != -1) { - maxLength = -1; - updateMaxLength(maxLength); - } - - } - - /** - * This method is reponsible for updating the DOM or otherwise ensuring that - * the given max length is enforced. Called when the max length for the - * field has changed. - * - * @param maxLength - * The new max length - */ - protected void updateMaxLength(int maxLength) { - if (maxLength >= 0) { - getElement().setPropertyInt("maxLength", maxLength); - } else { - getElement().removeAttribute("maxLength"); - - } - setMaxLengthToElement(maxLength); - } - - protected void setMaxLengthToElement(int newMaxLength) { - if (newMaxLength >= 0) { - getElement().setPropertyInt("maxLength", newMaxLength); - } else { - getElement().removeAttribute("maxLength"); - } - } - - public int getMaxLength() { - return maxLength; - } - - @Override - public void onChange(ChangeEvent event) { - valueChange(false); - } - - /** - * Called when the field value might have changed and/or the field was - * blurred. These are combined so the blur event is sent in the same batch - * as a possible value change event (these are often connected). - * - * @param blurred - * true if the field was blurred - */ - public void valueChange(boolean blurred) { - if (client != null && paintableId != null) { - boolean sendBlurEvent = false; - boolean sendValueChange = false; - - if (blurred && client.hasEventListeners(this, EventId.BLUR)) { - sendBlurEvent = true; - client.updateVariable(paintableId, EventId.BLUR, "", false); - } - - String newText = getText(); - if (!prompting && newText != null - && !newText.equals(valueBeforeEdit)) { - sendValueChange = immediate; - client.updateVariable(paintableId, "text", newText, false); - valueBeforeEdit = newText; - valueBeforeEditIsSynced = true; - } - - /* - * also send cursor position, no public api yet but for easier - * extension - */ - updateCursorPosition(); - - if (sendBlurEvent || sendValueChange) { - /* - * Avoid sending text change event as we will simulate it on the - * server side before value change events. - */ - textChangeEventTrigger.cancel(); - scheduled = false; - client.sendPendingVariableChanges(); - } - } - } - - /** - * Updates the cursor position variable if it has changed since the last - * update. - * - * @return true iff the value was updated - */ - protected boolean updateCursorPosition() { - if (Util.isAttachedAndDisplayed(this)) { - int cursorPos = getCursorPos(); - if (lastCursorPos != cursorPos) { - client.updateVariable(paintableId, - TextFieldConstants.VAR_CURSOR, cursorPos, false); - lastCursorPos = cursorPos; - return true; - } - } - return false; - } - - private static VTextField focusedTextField; - - public static void flushChangesFromFocusedTextField() { - if (focusedTextField != null) { - focusedTextField.onChange(null); - } - } - - @Override - public void onFocus(FocusEvent event) { - addStyleDependentName(CLASSNAME_FOCUS); - if (prompting) { - setText(""); - removeStyleDependentName(CLASSNAME_PROMPT); - setPrompting(false); - } - focusedTextField = this; - if (client.hasEventListeners(this, EventId.FOCUS)) { - client.updateVariable(paintableId, EventId.FOCUS, "", true); - } - } - - @Override - public void onBlur(BlurEvent event) { - // this is called twice on Chrome when e.g. changing tab while prompting - // field focused - do not change settings on the second time - if (focusedTextField != this) { - return; - } - removeStyleDependentName(CLASSNAME_FOCUS); - focusedTextField = null; - String text = getText(); - setPrompting(inputPrompt != null && (text == null || "".equals(text))); - if (prompting) { - setText(isReadOnly() ? "" : inputPrompt); - addStyleDependentName(CLASSNAME_PROMPT); - } - - valueChange(true); - } - - private void setPrompting(boolean prompting) { - this.prompting = prompting; - } - - public void setColumns(int columns) { - if (columns <= 0) { - return; - } - - setWidth(columns + "em"); - } - - @Override - public void onKeyDown(KeyDownEvent event) { - if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { - valueChange(false); - } - } - - public void setImmediate(boolean immediate) { - this.immediate = immediate; - } - - public void setInputPrompt(String inputPrompt) { - this.inputPrompt = inputPrompt; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/tree/TreeConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/tree/TreeConnector.java deleted file mode 100644 index a97a4b521f..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/tree/TreeConnector.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.tree; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import com.google.gwt.dom.client.Element; -import com.vaadin.shared.AbstractFieldState; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.tree.TreeConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.TooltipInfo; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; -import com.vaadin.terminal.gwt.client.ui.tree.VTree.TreeNode; -import com.vaadin.ui.Tree; - -@Connect(Tree.class) -public class TreeConnector extends AbstractComponentConnector implements - Paintable { - - protected final Map<TreeNode, TooltipInfo> tooltipMap = new HashMap<TreeNode, TooltipInfo>(); - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (!isRealUpdate(uidl)) { - return; - } - - getWidget().rendering = true; - - getWidget().client = client; - - if (uidl.hasAttribute("partialUpdate")) { - handleUpdate(uidl); - getWidget().rendering = false; - return; - } - - getWidget().paintableId = uidl.getId(); - - getWidget().immediate = getState().isImmediate(); - - getWidget().disabled = !isEnabled(); - getWidget().readonly = isReadOnly(); - - getWidget().dragMode = uidl.hasAttribute("dragMode") ? uidl - .getIntAttribute("dragMode") : 0; - - getWidget().isNullSelectionAllowed = uidl - .getBooleanAttribute("nullselect"); - - if (uidl.hasAttribute("alb")) { - getWidget().bodyActionKeys = uidl.getStringArrayAttribute("alb"); - } - - getWidget().body.clear(); - // clear out any references to nodes that no longer are attached - getWidget().clearNodeToKeyMap(); - tooltipMap.clear(); - - TreeNode childTree = null; - UIDL childUidl = null; - for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) { - childUidl = (UIDL) i.next(); - if ("actions".equals(childUidl.getTag())) { - updateActionMap(childUidl); - continue; - } else if ("-ac".equals(childUidl.getTag())) { - getWidget().updateDropHandler(childUidl); - continue; - } - childTree = getWidget().new TreeNode(); - getConnection().getVTooltip().connectHandlersToWidget(childTree); - updateNodeFromUIDL(childTree, childUidl); - getWidget().body.add(childTree); - childTree.addStyleDependentName("root"); - childTree.childNodeContainer.addStyleDependentName("root"); - } - if (childTree != null && childUidl != null) { - boolean leaf = !childUidl.getTag().equals("node"); - childTree.addStyleDependentName(leaf ? "leaf-last" : "last"); - childTree.childNodeContainer.addStyleDependentName("last"); - } - final String selectMode = uidl.getStringAttribute("selectmode"); - getWidget().selectable = !"none".equals(selectMode); - getWidget().isMultiselect = "multi".equals(selectMode); - - if (getWidget().isMultiselect) { - if (BrowserInfo.get().isTouchDevice()) { - // Always use the simple mode for touch devices that do not have - // shift/ctrl keys (#8595) - getWidget().multiSelectMode = VTree.MULTISELECT_MODE_SIMPLE; - } else { - getWidget().multiSelectMode = uidl - .getIntAttribute("multiselectmode"); - } - } - - getWidget().selectedIds = uidl.getStringArrayVariableAsSet("selected"); - - // Update lastSelection and focusedNode to point to *actual* nodes again - // after the old ones have been cleared from the body. This fixes focus - // and keyboard navigation issues as described in #7057 and other - // tickets. - if (getWidget().lastSelection != null) { - getWidget().lastSelection = getWidget().getNodeByKey( - getWidget().lastSelection.key); - } - if (getWidget().focusedNode != null) { - getWidget().setFocusedNode( - getWidget().getNodeByKey(getWidget().focusedNode.key)); - } - - if (getWidget().lastSelection == null - && getWidget().focusedNode == null - && !getWidget().selectedIds.isEmpty()) { - getWidget().setFocusedNode( - getWidget().getNodeByKey( - getWidget().selectedIds.iterator().next())); - getWidget().focusedNode.setFocused(false); - } - - getWidget().rendering = false; - - } - - @Override - public VTree getWidget() { - return (VTree) super.getWidget(); - } - - private void handleUpdate(UIDL uidl) { - final TreeNode rootNode = getWidget().getNodeByKey( - uidl.getStringAttribute("rootKey")); - if (rootNode != null) { - if (!rootNode.getState()) { - // expanding node happened server side - rootNode.setState(true, false); - } - renderChildNodes(rootNode, (Iterator) uidl.getChildIterator()); - } - } - - /** - * Registers action for the root and also for individual nodes - * - * @param uidl - */ - private void updateActionMap(UIDL uidl) { - final Iterator<?> it = uidl.getChildIterator(); - while (it.hasNext()) { - final UIDL action = (UIDL) it.next(); - final String key = action.getStringAttribute("key"); - final String caption = action - .getStringAttribute(TreeConstants.ATTRIBUTE_ACTION_CAPTION); - String iconUrl = null; - if (action.hasAttribute(TreeConstants.ATTRIBUTE_ACTION_ICON)) { - iconUrl = getConnection() - .translateVaadinUri( - action.getStringAttribute(TreeConstants.ATTRIBUTE_ACTION_ICON)); - } - getWidget().registerAction(key, caption, iconUrl); - } - - } - - public void updateNodeFromUIDL(TreeNode treeNode, UIDL uidl) { - String nodeKey = uidl.getStringAttribute("key"); - treeNode.setText(uidl - .getStringAttribute(TreeConstants.ATTRIBUTE_NODE_CAPTION)); - treeNode.key = nodeKey; - - getWidget().registerNode(treeNode); - - if (uidl.hasAttribute("al")) { - treeNode.actionKeys = uidl.getStringArrayAttribute("al"); - } - - if (uidl.getTag().equals("node")) { - if (uidl.getChildCount() == 0) { - treeNode.childNodeContainer.setVisible(false); - } else { - renderChildNodes(treeNode, (Iterator) uidl.getChildIterator()); - treeNode.childrenLoaded = true; - } - } else { - treeNode.addStyleName(TreeNode.CLASSNAME + "-leaf"); - } - if (uidl.hasAttribute(TreeConstants.ATTRIBUTE_NODE_STYLE)) { - treeNode.setNodeStyleName(uidl - .getStringAttribute(TreeConstants.ATTRIBUTE_NODE_STYLE)); - } - - String description = uidl.getStringAttribute("descr"); - if (description != null) { - tooltipMap.put(treeNode, new TooltipInfo(description)); - } - - if (uidl.getBooleanAttribute("expanded") && !treeNode.getState()) { - treeNode.setState(true, false); - } - - if (uidl.getBooleanAttribute("selected")) { - treeNode.setSelected(true); - // ensure that identifier is in selectedIds array (this may be a - // partial update) - getWidget().selectedIds.add(nodeKey); - } - - treeNode.setIcon(uidl - .getStringAttribute(TreeConstants.ATTRIBUTE_NODE_ICON)); - } - - void renderChildNodes(TreeNode containerNode, Iterator<UIDL> i) { - containerNode.childNodeContainer.clear(); - containerNode.childNodeContainer.setVisible(true); - while (i.hasNext()) { - final UIDL childUidl = i.next(); - // actions are in bit weird place, don't mix them with children, - // but current node's actions - if ("actions".equals(childUidl.getTag())) { - updateActionMap(childUidl); - continue; - } - final TreeNode childTree = getWidget().new TreeNode(); - getConnection().getVTooltip().connectHandlersToWidget(childTree); - updateNodeFromUIDL(childTree, childUidl); - containerNode.childNodeContainer.add(childTree); - if (!i.hasNext()) { - childTree - .addStyleDependentName(childTree.isLeaf() ? "leaf-last" - : "last"); - childTree.childNodeContainer.addStyleDependentName("last"); - } - } - containerNode.childrenLoaded = true; - } - - @Override - public boolean isReadOnly() { - return super.isReadOnly() || getState().isPropertyReadOnly(); - } - - @Override - public AbstractFieldState getState() { - return (AbstractFieldState) super.getState(); - } - - @Override - public TooltipInfo getTooltipInfo(Element element) { - - TooltipInfo info = null; - - // Try to find a tooltip for a node - if (element != getWidget().getElement()) { - Object node = Util.findWidget( - (com.google.gwt.user.client.Element) element, - TreeNode.class); - - if (node != null) { - TreeNode tnode = (TreeNode) node; - if (tnode.isCaptionElement(element)) { - info = tooltipMap.get(tnode); - } - } - } - - // If no tooltip found for the node or if the target was not a node, use - // the default tooltip - if (info == null) { - info = super.getTooltipInfo(element); - } - - return info; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/tree/VTree.java b/client/src/com/vaadin/terminal/gwt/client/ui/tree/VTree.java deleted file mode 100644 index 40c5e4b8af..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/tree/VTree.java +++ /dev/null @@ -1,2137 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.tree; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.dom.client.Node; -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.ContextMenuEvent; -import com.google.gwt.event.dom.client.ContextMenuHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.SimplePanel; -import com.google.gwt.user.client.ui.UIObject; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.dd.VerticalDropLocation; -import com.vaadin.shared.ui.tree.TreeConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.Action; -import com.vaadin.terminal.gwt.client.ui.ActionOwner; -import com.vaadin.terminal.gwt.client.ui.FocusElementPanel; -import com.vaadin.terminal.gwt.client.ui.Icon; -import com.vaadin.terminal.gwt.client.ui.SubPartAware; -import com.vaadin.terminal.gwt.client.ui.TreeAction; -import com.vaadin.terminal.gwt.client.ui.VLazyExecutor; -import com.vaadin.terminal.gwt.client.ui.dd.DDUtil; -import com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler; -import com.vaadin.terminal.gwt.client.ui.dd.VAcceptCallback; -import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager; -import com.vaadin.terminal.gwt.client.ui.dd.VDragEvent; -import com.vaadin.terminal.gwt.client.ui.dd.VDropHandler; -import com.vaadin.terminal.gwt.client.ui.dd.VHasDropHandler; -import com.vaadin.terminal.gwt.client.ui.dd.VTransferable; - -/** - * - */ -public class VTree extends FocusElementPanel implements VHasDropHandler, -FocusHandler, BlurHandler, KeyPressHandler, KeyDownHandler, -SubPartAware, ActionOwner { - - public static final String CLASSNAME = "v-tree"; - - /** - * Click selects the current node, ctrl/shift toggles multi selection - */ - public static final int MULTISELECT_MODE_DEFAULT = 0; - - /** - * Click/touch on node toggles its selected status - */ - public static final int MULTISELECT_MODE_SIMPLE = 1; - - private static final int CHARCODE_SPACE = 32; - - final FlowPanel body = new FlowPanel(); - - Set<String> selectedIds = new HashSet<String>(); - ApplicationConnection client; - String paintableId; - boolean selectable; - boolean isMultiselect; - private String currentMouseOverKey; - TreeNode lastSelection; - TreeNode focusedNode; - int multiSelectMode = MULTISELECT_MODE_DEFAULT; - - private final HashMap<String, TreeNode> keyToNode = new HashMap<String, TreeNode>(); - - /** - * This map contains captions and icon urls for actions like: * "33_c" -> - * "Edit" * "33_i" -> "http://dom.com/edit.png" - */ - private final HashMap<String, String> actionMap = new HashMap<String, String>(); - - boolean immediate; - - boolean isNullSelectionAllowed = true; - - boolean disabled = false; - - boolean readonly; - - boolean rendering; - - private VAbstractDropHandler dropHandler; - - int dragMode; - - private boolean selectionHasChanged = false; - - String[] bodyActionKeys; - - public VLazyExecutor iconLoaded = new VLazyExecutor(50, - new ScheduledCommand() { - - @Override - public void execute() { - Util.notifyParentOfSizeChange(VTree.this, true); - } - - }); - - public VTree() { - super(); - setStyleName(CLASSNAME); - add(body); - - addFocusHandler(this); - addBlurHandler(this); - - /* - * Listen to context menu events on the empty space in the tree - */ - sinkEvents(Event.ONCONTEXTMENU); - addDomHandler(new ContextMenuHandler() { - @Override - public void onContextMenu(ContextMenuEvent event) { - handleBodyContextMenu(event); - } - }, ContextMenuEvent.getType()); - - /* - * Firefox auto-repeat works correctly only if we use a key press - * handler, other browsers handle it correctly when using a key down - * handler - */ - if (BrowserInfo.get().isGecko() || BrowserInfo.get().isOpera()) { - addKeyPressHandler(this); - } else { - addKeyDownHandler(this); - } - - /* - * We need to use the sinkEvents method to catch the keyUp events so we - * can cache a single shift. KeyUpHandler cannot do this. At the same - * time we catch the mouse down and up events so we can apply the text - * selection patch in IE - */ - sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP | Event.ONKEYUP); - - /* - * Re-set the tab index to make sure that the FocusElementPanel's - * (super) focus element gets the tab index and not the element - * containing the tree. - */ - setTabIndex(0); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt.user - * .client.Event) - */ - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - if (event.getTypeInt() == Event.ONMOUSEDOWN) { - // Prevent default text selection in IE - if (BrowserInfo.get().isIE()) { - ((Element) event.getEventTarget().cast()).setPropertyJSO( - "onselectstart", applyDisableTextSelectionIEHack()); - } - } else if (event.getTypeInt() == Event.ONMOUSEUP) { - // Remove IE text selection hack - if (BrowserInfo.get().isIE()) { - ((Element) event.getEventTarget().cast()).setPropertyJSO( - "onselectstart", null); - } - } else if (event.getTypeInt() == Event.ONKEYUP) { - if (selectionHasChanged) { - if (event.getKeyCode() == getNavigationDownKey() - && !event.getShiftKey()) { - sendSelectionToServer(); - event.preventDefault(); - } else if (event.getKeyCode() == getNavigationUpKey() - && !event.getShiftKey()) { - sendSelectionToServer(); - event.preventDefault(); - } else if (event.getKeyCode() == KeyCodes.KEY_SHIFT) { - sendSelectionToServer(); - event.preventDefault(); - } else if (event.getKeyCode() == getNavigationSelectKey()) { - sendSelectionToServer(); - event.preventDefault(); - } - } - } - } - - public String getActionCaption(String actionKey) { - return actionMap.get(actionKey + "_c"); - } - - public String getActionIcon(String actionKey) { - return actionMap.get(actionKey + "_i"); - } - - /** - * Returns the first root node of the tree or null if there are no root - * nodes. - * - * @return The first root {@link TreeNode} - */ - protected TreeNode getFirstRootNode() { - if (body.getWidgetCount() == 0) { - return null; - } - return (TreeNode) body.getWidget(0); - } - - /** - * Returns the last root node of the tree or null if there are no root - * nodes. - * - * @return The last root {@link TreeNode} - */ - protected TreeNode getLastRootNode() { - if (body.getWidgetCount() == 0) { - return null; - } - return (TreeNode) body.getWidget(body.getWidgetCount() - 1); - } - - /** - * Returns a list of all root nodes in the Tree in the order they appear in - * the tree. - * - * @return A list of all root {@link TreeNode}s. - */ - protected List<TreeNode> getRootNodes() { - ArrayList<TreeNode> rootNodes = new ArrayList<TreeNode>(); - for (int i = 0; i < body.getWidgetCount(); i++) { - rootNodes.add((TreeNode) body.getWidget(i)); - } - return rootNodes; - } - - private void updateTreeRelatedDragData(VDragEvent drag) { - - currentMouseOverKey = findCurrentMouseOverKey(drag.getElementOver()); - - drag.getDropDetails().put("itemIdOver", currentMouseOverKey); - if (currentMouseOverKey != null) { - TreeNode treeNode = getNodeByKey(currentMouseOverKey); - VerticalDropLocation detail = treeNode.getDropDetail(drag - .getCurrentGwtEvent()); - Boolean overTreeNode = null; - if (treeNode != null && !treeNode.isLeaf() - && detail == VerticalDropLocation.MIDDLE) { - overTreeNode = true; - } - drag.getDropDetails().put("itemIdOverIsNode", overTreeNode); - drag.getDropDetails().put("detail", detail); - } else { - drag.getDropDetails().put("itemIdOverIsNode", null); - drag.getDropDetails().put("detail", null); - } - - } - - private String findCurrentMouseOverKey(Element elementOver) { - TreeNode treeNode = Util.findWidget(elementOver, TreeNode.class); - return treeNode == null ? null : treeNode.key; - } - - void updateDropHandler(UIDL childUidl) { - if (dropHandler == null) { - dropHandler = new VAbstractDropHandler() { - - @Override - public void dragEnter(VDragEvent drag) { - } - - @Override - protected void dragAccepted(final VDragEvent drag) { - - } - - @Override - public void dragOver(final VDragEvent currentDrag) { - final Object oldIdOver = currentDrag.getDropDetails().get( - "itemIdOver"); - final VerticalDropLocation oldDetail = (VerticalDropLocation) currentDrag - .getDropDetails().get("detail"); - - updateTreeRelatedDragData(currentDrag); - final VerticalDropLocation detail = (VerticalDropLocation) currentDrag - .getDropDetails().get("detail"); - boolean nodeHasChanged = (currentMouseOverKey != null && currentMouseOverKey != oldIdOver) - || (currentMouseOverKey == null && oldIdOver != null); - boolean detailHasChanded = (detail != null && detail != oldDetail) - || (detail == null && oldDetail != null); - - if (nodeHasChanged || detailHasChanded) { - final String newKey = currentMouseOverKey; - TreeNode treeNode = keyToNode.get(oldIdOver); - if (treeNode != null) { - // clear old styles - treeNode.emphasis(null); - } - if (newKey != null) { - validate(new VAcceptCallback() { - @Override - public void accepted(VDragEvent event) { - VerticalDropLocation curDetail = (VerticalDropLocation) event - .getDropDetails().get("detail"); - if (curDetail == detail - && newKey.equals(currentMouseOverKey)) { - getNodeByKey(newKey).emphasis(detail); - } - /* - * Else drag is already on a different - * node-detail pair, new criteria check is - * going on - */ - } - }, currentDrag); - - } - } - - } - - @Override - public void dragLeave(VDragEvent drag) { - cleanUp(); - } - - private void cleanUp() { - if (currentMouseOverKey != null) { - getNodeByKey(currentMouseOverKey).emphasis(null); - currentMouseOverKey = null; - } - } - - @Override - public boolean drop(VDragEvent drag) { - cleanUp(); - return super.drop(drag); - } - - @Override - public ComponentConnector getConnector() { - return ConnectorMap.get(client).getConnector(VTree.this); - } - - @Override - public ApplicationConnection getApplicationConnection() { - return client; - } - - }; - } - dropHandler.updateAcceptRules(childUidl); - } - - public void setSelected(TreeNode treeNode, boolean selected) { - if (selected) { - if (!isMultiselect) { - while (selectedIds.size() > 0) { - final String id = selectedIds.iterator().next(); - final TreeNode oldSelection = getNodeByKey(id); - if (oldSelection != null) { - // can be null if the node is not visible (parent - // collapsed) - oldSelection.setSelected(false); - } - selectedIds.remove(id); - } - } - treeNode.setSelected(true); - selectedIds.add(treeNode.key); - } else { - if (!isNullSelectionAllowed) { - if (!isMultiselect || selectedIds.size() == 1) { - return; - } - } - selectedIds.remove(treeNode.key); - treeNode.setSelected(false); - } - - sendSelectionToServer(); - } - - /** - * Sends the selection to the server - */ - private void sendSelectionToServer() { - Command command = new Command() { - @Override - public void execute() { - client.updateVariable(paintableId, "selected", - selectedIds.toArray(new String[selectedIds.size()]), - immediate); - selectionHasChanged = false; - } - }; - - /* - * Delaying the sending of the selection in webkit to ensure the - * selection is always sent when the tree has focus and after click - * events have been processed. This is due to the focusing - * implementation in FocusImplSafari which uses timeouts when focusing - * and blurring. - */ - if (BrowserInfo.get().isWebkit()) { - Scheduler.get().scheduleDeferred(command); - } else { - command.execute(); - } - } - - /** - * Is a node selected in the tree - * - * @param treeNode - * The node to check - * @return - */ - public boolean isSelected(TreeNode treeNode) { - return selectedIds.contains(treeNode.key); - } - - public class TreeNode extends SimplePanel implements ActionOwner { - - public static final String CLASSNAME = "v-tree-node"; - public static final String CLASSNAME_FOCUSED = CLASSNAME + "-focused"; - - public String key; - - String[] actionKeys = null; - - boolean childrenLoaded; - - Element nodeCaptionDiv; - - protected Element nodeCaptionSpan; - - FlowPanel childNodeContainer; - - private boolean open; - - private Icon icon; - - private Event mouseDownEvent; - - private int cachedHeight = -1; - - private boolean focused = false; - - public TreeNode() { - constructDom(); - sinkEvents(Event.ONCLICK | Event.ONDBLCLICK | Event.MOUSEEVENTS - | Event.TOUCHEVENTS | Event.ONCONTEXTMENU); - } - - public VerticalDropLocation getDropDetail(NativeEvent currentGwtEvent) { - if (cachedHeight < 0) { - /* - * Height is cached to avoid flickering (drop hints may change - * the reported offsetheight -> would change the drop detail) - */ - cachedHeight = nodeCaptionDiv.getOffsetHeight(); - } - VerticalDropLocation verticalDropLocation = DDUtil - .getVerticalDropLocation(nodeCaptionDiv, cachedHeight, - currentGwtEvent, 0.15); - return verticalDropLocation; - } - - protected void emphasis(VerticalDropLocation detail) { - String base = "v-tree-node-drag-"; - UIObject.setStyleName(getElement(), base + "top", - VerticalDropLocation.TOP == detail); - UIObject.setStyleName(getElement(), base + "bottom", - VerticalDropLocation.BOTTOM == detail); - UIObject.setStyleName(getElement(), base + "center", - VerticalDropLocation.MIDDLE == detail); - base = "v-tree-node-caption-drag-"; - UIObject.setStyleName(nodeCaptionDiv, base + "top", - VerticalDropLocation.TOP == detail); - UIObject.setStyleName(nodeCaptionDiv, base + "bottom", - VerticalDropLocation.BOTTOM == detail); - UIObject.setStyleName(nodeCaptionDiv, base + "center", - VerticalDropLocation.MIDDLE == detail); - - // also add classname to "folder node" into which the drag is - // targeted - - TreeNode folder = null; - /* Possible parent of this TreeNode will be stored here */ - TreeNode parentFolder = getParentNode(); - - // TODO fix my bugs - if (isLeaf()) { - folder = parentFolder; - // note, parent folder may be null if this is root node => no - // folder target exists - } else { - if (detail == VerticalDropLocation.TOP) { - folder = parentFolder; - } else { - folder = this; - } - // ensure we remove the dragfolder classname from the previous - // folder node - setDragFolderStyleName(this, false); - setDragFolderStyleName(parentFolder, false); - } - if (folder != null) { - setDragFolderStyleName(folder, detail != null); - } - - } - - private TreeNode getParentNode() { - Widget parent2 = getParent().getParent(); - if (parent2 instanceof TreeNode) { - return (TreeNode) parent2; - } - return null; - } - - private void setDragFolderStyleName(TreeNode folder, boolean add) { - if (folder != null) { - UIObject.setStyleName(folder.getElement(), - "v-tree-node-dragfolder", add); - UIObject.setStyleName(folder.nodeCaptionDiv, - "v-tree-node-caption-dragfolder", add); - } - } - - /** - * Handles mouse selection - * - * @param ctrl - * Was the ctrl-key pressed - * @param shift - * Was the shift-key pressed - * @return Returns true if event was handled, else false - */ - private boolean handleClickSelection(final boolean ctrl, - final boolean shift) { - - // always when clicking an item, focus it - setFocusedNode(this, false); - - if (!BrowserInfo.get().isOpera()) { - /* - * Ensure that the tree's focus element also gains focus - * (TreeNodes focus is faked using FocusElementPanel in browsers - * other than Opera). - */ - focus(); - } - - executeEventCommand(new ScheduledCommand() { - - @Override - public void execute() { - - if (multiSelectMode == MULTISELECT_MODE_SIMPLE - || !isMultiselect) { - toggleSelection(); - lastSelection = TreeNode.this; - } else if (multiSelectMode == MULTISELECT_MODE_DEFAULT) { - // Handle ctrl+click - if (isMultiselect && ctrl && !shift) { - toggleSelection(); - lastSelection = TreeNode.this; - - // Handle shift+click - } else if (isMultiselect && !ctrl && shift) { - deselectAll(); - selectNodeRange(lastSelection.key, key); - sendSelectionToServer(); - - // Handle ctrl+shift click - } else if (isMultiselect && ctrl && shift) { - selectNodeRange(lastSelection.key, key); - - // Handle click - } else { - // TODO should happen only if this alone not yet - // selected, - // now sending excess server calls - deselectAll(); - toggleSelection(); - lastSelection = TreeNode.this; - } - } - } - }); - - return true; - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt - * .user.client.Event) - */ - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - final int type = DOM.eventGetType(event); - final Element target = DOM.eventGetTarget(event); - - if (type == Event.ONLOAD && target == icon.getElement()) { - iconLoaded.trigger(); - } - - if (disabled) { - return; - } - - final boolean inCaption = isCaptionElement(target); - if (inCaption - && client.hasEventListeners(VTree.this, - TreeConstants.ITEM_CLICK_EVENT_ID) - - && (type == Event.ONDBLCLICK || type == Event.ONMOUSEUP)) { - fireClick(event); - } - if (type == Event.ONCLICK) { - if (getElement() == target) { - // state change - toggleState(); - } else if (!readonly && inCaption) { - if (selectable) { - // caption click = selection change && possible click - // event - if (handleClickSelection( - event.getCtrlKey() || event.getMetaKey(), - event.getShiftKey())) { - event.preventDefault(); - } - } else { - // Not selectable, only focus the node. - setFocusedNode(this); - } - } - event.stopPropagation(); - } else if (type == Event.ONCONTEXTMENU) { - showContextMenu(event); - } - - if (dragMode != 0 || dropHandler != null) { - if (type == Event.ONMOUSEDOWN || type == Event.ONTOUCHSTART) { - if (nodeCaptionDiv.isOrHasChild((Node) event - .getEventTarget().cast())) { - if (dragMode > 0 - && (type == Event.ONTOUCHSTART || event - .getButton() == NativeEvent.BUTTON_LEFT)) { - mouseDownEvent = event; // save event for possible - // dd operation - if (type == Event.ONMOUSEDOWN) { - event.preventDefault(); // prevent text - // selection - } else { - /* - * FIXME We prevent touch start event to be used - * as a scroll start event. Note that we cannot - * easily distinguish whether the user wants to - * drag or scroll. The same issue is in table - * that has scrollable area and has drag and - * drop enable. Some kind of timer might be used - * to resolve the issue. - */ - event.stopPropagation(); - } - } - } - } else if (type == Event.ONMOUSEMOVE - || type == Event.ONMOUSEOUT - || type == Event.ONTOUCHMOVE) { - - if (mouseDownEvent != null) { - // start actual drag on slight move when mouse is down - VTransferable t = new VTransferable(); - t.setDragSource(ConnectorMap.get(client).getConnector( - VTree.this)); - t.setData("itemId", key); - VDragEvent drag = VDragAndDropManager.get().startDrag( - t, mouseDownEvent, true); - - drag.createDragImage(nodeCaptionDiv, true); - event.stopPropagation(); - - mouseDownEvent = null; - } - } else if (type == Event.ONMOUSEUP) { - mouseDownEvent = null; - } - if (type == Event.ONMOUSEOVER) { - mouseDownEvent = null; - currentMouseOverKey = key; - event.stopPropagation(); - } - - } else if (type == Event.ONMOUSEDOWN - && event.getButton() == NativeEvent.BUTTON_LEFT) { - event.preventDefault(); // text selection - } - } - - /** - * Checks if the given element is the caption or the icon. - * - * @param target - * The element to check - * @return true if the element is the caption or the icon - */ - public boolean isCaptionElement(com.google.gwt.dom.client.Element target) { - return (target == nodeCaptionSpan || (icon != null && target == icon - .getElement())); - } - - private void fireClick(final Event evt) { - /* - * Ensure we have focus in tree before sending variables. Otherwise - * previously modified field may contain dirty variables. - */ - if (!treeHasFocus) { - if (BrowserInfo.get().isOpera()) { - if (focusedNode == null) { - getNodeByKey(key).setFocused(true); - } else { - focusedNode.setFocused(true); - } - } else { - focus(); - } - } - - final MouseEventDetails details = MouseEventDetailsBuilder - .buildMouseEventDetails(evt); - - executeEventCommand(new ScheduledCommand() { - - @Override - public void execute() { - // Determine if we should send the event immediately to the - // server. We do not want to send the event if there is a - // selection event happening after this. In all other cases - // we want to send it immediately. - boolean sendClickEventNow = true; - - if (details.getButton() == NativeEvent.BUTTON_LEFT - && immediate && selectable) { - // Probably a selection that will cause a value change - // event to be sent - sendClickEventNow = false; - - // The exception is that user clicked on the - // currently selected row and null selection is not - // allowed == no selection event - if (isSelected() && selectedIds.size() == 1 - && !isNullSelectionAllowed) { - sendClickEventNow = true; - } - } - - client.updateVariable(paintableId, "clickedKey", key, false); - client.updateVariable(paintableId, "clickEvent", - details.toString(), sendClickEventNow); - } - }); - } - - /* - * Must wait for Safari to focus before sending click and value change - * events (see #6373, #6374) - */ - private void executeEventCommand(ScheduledCommand command) { - if (BrowserInfo.get().isWebkit() && !treeHasFocus) { - Scheduler.get().scheduleDeferred(command); - } else { - command.execute(); - } - } - - private void toggleSelection() { - if (selectable) { - VTree.this.setSelected(this, !isSelected()); - } - } - - private void toggleState() { - setState(!getState(), true); - } - - protected void constructDom() { - addStyleName(CLASSNAME); - - nodeCaptionDiv = DOM.createDiv(); - DOM.setElementProperty(nodeCaptionDiv, "className", CLASSNAME - + "-caption"); - Element wrapper = DOM.createDiv(); - nodeCaptionSpan = DOM.createSpan(); - DOM.appendChild(getElement(), nodeCaptionDiv); - DOM.appendChild(nodeCaptionDiv, wrapper); - DOM.appendChild(wrapper, nodeCaptionSpan); - - if (BrowserInfo.get().isOpera()) { - /* - * Focus the caption div of the node to get keyboard navigation - * to work without scrolling up or down when focusing a node. - */ - nodeCaptionDiv.setTabIndex(-1); - } - - childNodeContainer = new FlowPanel(); - childNodeContainer.setStyleName(CLASSNAME + "-children"); - setWidget(childNodeContainer); - } - - public boolean isLeaf() { - String[] styleNames = getStyleName().split(" "); - for (String styleName : styleNames) { - if (styleName.equals(CLASSNAME + "-leaf")) { - return true; - } - } - return false; - } - - void setState(boolean state, boolean notifyServer) { - if (open == state) { - return; - } - if (state) { - if (!childrenLoaded && notifyServer) { - client.updateVariable(paintableId, "requestChildTree", - true, false); - } - if (notifyServer) { - client.updateVariable(paintableId, "expand", - new String[] { key }, true); - } - addStyleName(CLASSNAME + "-expanded"); - childNodeContainer.setVisible(true); - - } else { - removeStyleName(CLASSNAME + "-expanded"); - childNodeContainer.setVisible(false); - if (notifyServer) { - client.updateVariable(paintableId, "collapse", - new String[] { key }, true); - } - } - open = state; - - if (!rendering) { - Util.notifyParentOfSizeChange(VTree.this, false); - } - } - - boolean getState() { - return open; - } - - void setText(String text) { - DOM.setInnerText(nodeCaptionSpan, text); - } - - public boolean isChildrenLoaded() { - return childrenLoaded; - } - - /** - * Returns the children of the node - * - * @return A set of tree nodes - */ - public List<TreeNode> getChildren() { - List<TreeNode> nodes = new LinkedList<TreeNode>(); - - if (!isLeaf() && isChildrenLoaded()) { - Iterator<Widget> iter = childNodeContainer.iterator(); - while (iter.hasNext()) { - TreeNode node = (TreeNode) iter.next(); - nodes.add(node); - } - } - return nodes; - } - - @Override - public Action[] getActions() { - if (actionKeys == null) { - return new Action[] {}; - } - final Action[] actions = new Action[actionKeys.length]; - for (int i = 0; i < actions.length; i++) { - final String actionKey = actionKeys[i]; - final TreeAction a = new TreeAction(this, String.valueOf(key), - actionKey); - a.setCaption(getActionCaption(actionKey)); - a.setIconUrl(getActionIcon(actionKey)); - actions[i] = a; - } - return actions; - } - - @Override - public ApplicationConnection getClient() { - return client; - } - - @Override - public String getPaintableId() { - return paintableId; - } - - /** - * Adds/removes Vaadin specific style name. This method ought to be - * called only from VTree. - * - * @param selected - */ - protected void setSelected(boolean selected) { - // add style name to caption dom structure only, not to subtree - setStyleName(nodeCaptionDiv, "v-tree-node-selected", selected); - } - - protected boolean isSelected() { - return VTree.this.isSelected(this); - } - - /** - * Travels up the hierarchy looking for this node - * - * @param child - * The child which grandparent this is or is not - * @return True if this is a grandparent of the child node - */ - public boolean isGrandParentOf(TreeNode child) { - TreeNode currentNode = child; - boolean isGrandParent = false; - while (currentNode != null) { - currentNode = currentNode.getParentNode(); - if (currentNode == this) { - isGrandParent = true; - break; - } - } - return isGrandParent; - } - - public boolean isSibling(TreeNode node) { - return node.getParentNode() == getParentNode(); - } - - public void showContextMenu(Event event) { - if (!readonly && !disabled) { - if (actionKeys != null) { - int left = event.getClientX(); - int top = event.getClientY(); - top += Window.getScrollTop(); - left += Window.getScrollLeft(); - client.getContextMenu().showAt(this, left, top); - } - event.stopPropagation(); - event.preventDefault(); - } - } - - /* - * (non-Javadoc) - * - * @see com.google.gwt.user.client.ui.Widget#onDetach() - */ - @Override - protected void onDetach() { - super.onDetach(); - client.getContextMenu().ensureHidden(this); - } - - /* - * (non-Javadoc) - * - * @see com.google.gwt.user.client.ui.UIObject#toString() - */ - @Override - public String toString() { - return nodeCaptionSpan.getInnerText(); - } - - /** - * Is the node focused? - * - * @param focused - * True if focused, false if not - */ - public void setFocused(boolean focused) { - if (!this.focused && focused) { - nodeCaptionDiv.addClassName(CLASSNAME_FOCUSED); - - this.focused = focused; - if (BrowserInfo.get().isOpera()) { - nodeCaptionDiv.focus(); - } - treeHasFocus = true; - } else if (this.focused && !focused) { - nodeCaptionDiv.removeClassName(CLASSNAME_FOCUSED); - this.focused = focused; - treeHasFocus = false; - } - } - - /** - * Scrolls the caption into view - */ - public void scrollIntoView() { - Util.scrollIntoViewVertically(nodeCaptionDiv); - } - - public void setIcon(String iconUrl) { - if (iconUrl != null) { - // Add icon if not present - if (icon == null) { - icon = new Icon(client); - DOM.insertBefore(DOM.getFirstChild(nodeCaptionDiv), - icon.getElement(), nodeCaptionSpan); - } - icon.setUri(iconUrl); - } else { - // Remove icon if present - if (icon != null) { - DOM.removeChild(DOM.getFirstChild(nodeCaptionDiv), - icon.getElement()); - icon = null; - } - } - } - - public void setNodeStyleName(String styleName) { - addStyleName(TreeNode.CLASSNAME + "-" + styleName); - setStyleName(nodeCaptionDiv, TreeNode.CLASSNAME + "-caption-" - + styleName, true); - childNodeContainer.addStyleName(TreeNode.CLASSNAME + "-children-" - + styleName); - - } - - } - - @Override - public VDropHandler getDropHandler() { - return dropHandler; - } - - public TreeNode getNodeByKey(String key) { - return keyToNode.get(key); - } - - /** - * Deselects all items in the tree - */ - public void deselectAll() { - for (String key : selectedIds) { - TreeNode node = keyToNode.get(key); - if (node != null) { - node.setSelected(false); - } - } - selectedIds.clear(); - selectionHasChanged = true; - } - - /** - * Selects a range of nodes - * - * @param startNodeKey - * The start node key - * @param endNodeKey - * The end node key - */ - private void selectNodeRange(String startNodeKey, String endNodeKey) { - - TreeNode startNode = keyToNode.get(startNodeKey); - TreeNode endNode = keyToNode.get(endNodeKey); - - // The nodes have the same parent - if (startNode.getParent() == endNode.getParent()) { - doSiblingSelection(startNode, endNode); - - // The start node is a grandparent of the end node - } else if (startNode.isGrandParentOf(endNode)) { - doRelationSelection(startNode, endNode); - - // The end node is a grandparent of the start node - } else if (endNode.isGrandParentOf(startNode)) { - doRelationSelection(endNode, startNode); - - } else { - doNoRelationSelection(startNode, endNode); - } - } - - /** - * Selects a node and deselect all other nodes - * - * @param node - * The node to select - */ - private void selectNode(TreeNode node, boolean deselectPrevious) { - if (deselectPrevious) { - deselectAll(); - } - - if (node != null) { - node.setSelected(true); - selectedIds.add(node.key); - lastSelection = node; - } - selectionHasChanged = true; - } - - /** - * Deselects a node - * - * @param node - * The node to deselect - */ - private void deselectNode(TreeNode node) { - node.setSelected(false); - selectedIds.remove(node.key); - selectionHasChanged = true; - } - - /** - * Selects all the open children to a node - * - * @param node - * The parent node - */ - private void selectAllChildren(TreeNode node, boolean includeRootNode) { - if (includeRootNode) { - node.setSelected(true); - selectedIds.add(node.key); - } - - for (TreeNode child : node.getChildren()) { - if (!child.isLeaf() && child.getState()) { - selectAllChildren(child, true); - } else { - child.setSelected(true); - selectedIds.add(child.key); - } - } - selectionHasChanged = true; - } - - /** - * Selects all children until a stop child is reached - * - * @param root - * The root not to start from - * @param stopNode - * The node to finish with - * @param includeRootNode - * Should the root node be selected - * @param includeStopNode - * Should the stop node be selected - * - * @return Returns false if the stop child was found, else true if all - * children was selected - */ - private boolean selectAllChildrenUntil(TreeNode root, TreeNode stopNode, - boolean includeRootNode, boolean includeStopNode) { - if (includeRootNode) { - root.setSelected(true); - selectedIds.add(root.key); - } - if (root.getState() && root != stopNode) { - for (TreeNode child : root.getChildren()) { - if (!child.isLeaf() && child.getState() && child != stopNode) { - if (!selectAllChildrenUntil(child, stopNode, true, - includeStopNode)) { - return false; - } - } else if (child == stopNode) { - if (includeStopNode) { - child.setSelected(true); - selectedIds.add(child.key); - } - return false; - } else { - child.setSelected(true); - selectedIds.add(child.key); - } - } - } - selectionHasChanged = true; - - return true; - } - - /** - * Select a range between two nodes which have no relation to each other - * - * @param startNode - * The start node to start the selection from - * @param endNode - * The end node to end the selection to - */ - private void doNoRelationSelection(TreeNode startNode, TreeNode endNode) { - - TreeNode commonParent = getCommonGrandParent(startNode, endNode); - TreeNode startBranch = null, endBranch = null; - - // Find the children of the common parent - List<TreeNode> children; - if (commonParent != null) { - children = commonParent.getChildren(); - } else { - children = getRootNodes(); - } - - // Find the start and end branches - for (TreeNode node : children) { - if (nodeIsInBranch(startNode, node)) { - startBranch = node; - } - if (nodeIsInBranch(endNode, node)) { - endBranch = node; - } - } - - // Swap nodes if necessary - if (children.indexOf(startBranch) > children.indexOf(endBranch)) { - TreeNode temp = startBranch; - startBranch = endBranch; - endBranch = temp; - - temp = startNode; - startNode = endNode; - endNode = temp; - } - - // Select all children under the start node - selectAllChildren(startNode, true); - TreeNode startParent = startNode.getParentNode(); - TreeNode currentNode = startNode; - while (startParent != null && startParent != commonParent) { - List<TreeNode> startChildren = startParent.getChildren(); - for (int i = startChildren.indexOf(currentNode) + 1; i < startChildren - .size(); i++) { - selectAllChildren(startChildren.get(i), true); - } - - currentNode = startParent; - startParent = startParent.getParentNode(); - } - - // Select nodes until the end node is reached - for (int i = children.indexOf(startBranch) + 1; i <= children - .indexOf(endBranch); i++) { - selectAllChildrenUntil(children.get(i), endNode, true, true); - } - - // Ensure end node was selected - endNode.setSelected(true); - selectedIds.add(endNode.key); - selectionHasChanged = true; - } - - /** - * Examines the children of the branch node and returns true if a node is in - * that branch - * - * @param node - * The node to search for - * @param branch - * The branch to search in - * @return True if found, false if not found - */ - private boolean nodeIsInBranch(TreeNode node, TreeNode branch) { - if (node == branch) { - return true; - } - for (TreeNode child : branch.getChildren()) { - if (child == node) { - return true; - } - if (!child.isLeaf() && child.getState()) { - if (nodeIsInBranch(node, child)) { - return true; - } - } - } - return false; - } - - /** - * Selects a range of items which are in direct relation with each other.<br/> - * NOTE: The start node <b>MUST</b> be before the end node! - * - * @param startNode - * - * @param endNode - */ - private void doRelationSelection(TreeNode startNode, TreeNode endNode) { - TreeNode currentNode = endNode; - while (currentNode != startNode) { - currentNode.setSelected(true); - selectedIds.add(currentNode.key); - - // Traverse children above the selection - List<TreeNode> subChildren = currentNode.getParentNode() - .getChildren(); - if (subChildren.size() > 1) { - selectNodeRange(subChildren.iterator().next().key, - currentNode.key); - } else if (subChildren.size() == 1) { - TreeNode n = subChildren.get(0); - n.setSelected(true); - selectedIds.add(n.key); - } - - currentNode = currentNode.getParentNode(); - } - startNode.setSelected(true); - selectedIds.add(startNode.key); - selectionHasChanged = true; - } - - /** - * Selects a range of items which have the same parent. - * - * @param startNode - * The start node - * @param endNode - * The end node - */ - private void doSiblingSelection(TreeNode startNode, TreeNode endNode) { - TreeNode parent = startNode.getParentNode(); - - List<TreeNode> children; - if (parent == null) { - // Topmost parent - children = getRootNodes(); - } else { - children = parent.getChildren(); - } - - // Swap start and end point if needed - if (children.indexOf(startNode) > children.indexOf(endNode)) { - TreeNode temp = startNode; - startNode = endNode; - endNode = temp; - } - - Iterator<TreeNode> childIter = children.iterator(); - boolean startFound = false; - while (childIter.hasNext()) { - TreeNode node = childIter.next(); - if (node == startNode) { - startFound = true; - } - - if (startFound && node != endNode && node.getState()) { - selectAllChildren(node, true); - } else if (startFound && node != endNode) { - node.setSelected(true); - selectedIds.add(node.key); - } - - if (node == endNode) { - node.setSelected(true); - selectedIds.add(node.key); - break; - } - } - selectionHasChanged = true; - } - - /** - * Returns the first common parent of two nodes - * - * @param node1 - * The first node - * @param node2 - * The second node - * @return The common parent or null - */ - public TreeNode getCommonGrandParent(TreeNode node1, TreeNode node2) { - // If either one does not have a grand parent then return null - if (node1.getParentNode() == null || node2.getParentNode() == null) { - return null; - } - - // If the nodes are parents of each other then return null - if (node1.isGrandParentOf(node2) || node2.isGrandParentOf(node1)) { - return null; - } - - // Get parents of node1 - List<TreeNode> parents1 = new ArrayList<TreeNode>(); - TreeNode parent1 = node1.getParentNode(); - while (parent1 != null) { - parents1.add(parent1); - parent1 = parent1.getParentNode(); - } - - // Get parents of node2 - List<TreeNode> parents2 = new ArrayList<TreeNode>(); - TreeNode parent2 = node2.getParentNode(); - while (parent2 != null) { - parents2.add(parent2); - parent2 = parent2.getParentNode(); - } - - // Search the parents for the first common parent - for (int i = 0; i < parents1.size(); i++) { - parent1 = parents1.get(i); - for (int j = 0; j < parents2.size(); j++) { - parent2 = parents2.get(j); - if (parent1 == parent2) { - return parent1; - } - } - } - - return null; - } - - /** - * Sets the node currently in focus - * - * @param node - * The node to focus or null to remove the focus completely - * @param scrollIntoView - * Scroll the node into view - */ - public void setFocusedNode(TreeNode node, boolean scrollIntoView) { - // Unfocus previously focused node - if (focusedNode != null) { - focusedNode.setFocused(false); - } - - if (node != null) { - node.setFocused(true); - } - - focusedNode = node; - - if (node != null && scrollIntoView) { - /* - * Delay scrolling the focused node into view if we are still - * rendering. #5396 - */ - if (!rendering) { - node.scrollIntoView(); - } else { - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - focusedNode.scrollIntoView(); - } - }); - } - } - } - - /** - * Focuses a node and scrolls it into view - * - * @param node - * The node to focus - */ - public void setFocusedNode(TreeNode node) { - setFocusedNode(node, true); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event - * .dom.client.FocusEvent) - */ - @Override - public void onFocus(FocusEvent event) { - treeHasFocus = true; - // If no node has focus, focus the first item in the tree - if (focusedNode == null && lastSelection == null && selectable) { - setFocusedNode(getFirstRootNode(), false); - } else if (focusedNode != null && selectable) { - setFocusedNode(focusedNode, false); - } else if (lastSelection != null && selectable) { - setFocusedNode(lastSelection, false); - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event - * .dom.client.BlurEvent) - */ - @Override - public void onBlur(BlurEvent event) { - treeHasFocus = false; - if (focusedNode != null) { - focusedNode.setFocused(false); - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.KeyPressHandler#onKeyPress(com.google - * .gwt.event.dom.client.KeyPressEvent) - */ - @Override - public void onKeyPress(KeyPressEvent event) { - NativeEvent nativeEvent = event.getNativeEvent(); - int keyCode = nativeEvent.getKeyCode(); - if (keyCode == 0 && nativeEvent.getCharCode() == ' ') { - // Provide a keyCode for space to be compatible with FireFox - // keypress event - keyCode = CHARCODE_SPACE; - } - if (handleKeyNavigation(keyCode, - event.isControlKeyDown() || event.isMetaKeyDown(), - event.isShiftKeyDown())) { - event.preventDefault(); - event.stopPropagation(); - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt - * .event.dom.client.KeyDownEvent) - */ - @Override - public void onKeyDown(KeyDownEvent event) { - if (handleKeyNavigation(event.getNativeEvent().getKeyCode(), - event.isControlKeyDown() || event.isMetaKeyDown(), - event.isShiftKeyDown())) { - event.preventDefault(); - event.stopPropagation(); - } - } - - /** - * Handles the keyboard navigation - * - * @param keycode - * The keycode of the pressed key - * @param ctrl - * Was ctrl pressed - * @param shift - * Was shift pressed - * @return Returns true if the key was handled, else false - */ - protected boolean handleKeyNavigation(int keycode, boolean ctrl, - boolean shift) { - // Navigate down - if (keycode == getNavigationDownKey()) { - TreeNode node = null; - // If node is open and has children then move in to the children - if (!focusedNode.isLeaf() && focusedNode.getState() - && focusedNode.getChildren().size() > 0) { - node = focusedNode.getChildren().get(0); - } - - // Else move down to the next sibling - else { - node = getNextSibling(focusedNode); - if (node == null) { - // Else jump to the parent and try to select the next - // sibling there - TreeNode current = focusedNode; - while (node == null && current.getParentNode() != null) { - node = getNextSibling(current.getParentNode()); - current = current.getParentNode(); - } - } - } - - if (node != null) { - setFocusedNode(node); - if (selectable) { - if (!ctrl && !shift) { - selectNode(node, true); - } else if (shift && isMultiselect) { - deselectAll(); - selectNodeRange(lastSelection.key, node.key); - } else if (shift) { - selectNode(node, true); - } - } - } - return true; - } - - // Navigate up - if (keycode == getNavigationUpKey()) { - TreeNode prev = getPreviousSibling(focusedNode); - TreeNode node = null; - if (prev != null) { - node = getLastVisibleChildInTree(prev); - } else if (focusedNode.getParentNode() != null) { - node = focusedNode.getParentNode(); - } - if (node != null) { - setFocusedNode(node); - if (selectable) { - if (!ctrl && !shift) { - selectNode(node, true); - } else if (shift && isMultiselect) { - deselectAll(); - selectNodeRange(lastSelection.key, node.key); - } else if (shift) { - selectNode(node, true); - } - } - } - return true; - } - - // Navigate left (close branch) - if (keycode == getNavigationLeftKey()) { - if (!focusedNode.isLeaf() && focusedNode.getState()) { - focusedNode.setState(false, true); - } else if (focusedNode.getParentNode() != null - && (focusedNode.isLeaf() || !focusedNode.getState())) { - - if (ctrl || !selectable) { - setFocusedNode(focusedNode.getParentNode()); - } else if (shift) { - doRelationSelection(focusedNode.getParentNode(), - focusedNode); - setFocusedNode(focusedNode.getParentNode()); - } else { - focusAndSelectNode(focusedNode.getParentNode()); - } - } - return true; - } - - // Navigate right (open branch) - if (keycode == getNavigationRightKey()) { - if (!focusedNode.isLeaf() && !focusedNode.getState()) { - focusedNode.setState(true, true); - } else if (!focusedNode.isLeaf()) { - if (ctrl || !selectable) { - setFocusedNode(focusedNode.getChildren().get(0)); - } else if (shift) { - setSelected(focusedNode, true); - setFocusedNode(focusedNode.getChildren().get(0)); - setSelected(focusedNode, true); - } else { - focusAndSelectNode(focusedNode.getChildren().get(0)); - } - } - return true; - } - - // Selection - if (keycode == getNavigationSelectKey()) { - if (!focusedNode.isSelected()) { - selectNode( - focusedNode, - (!isMultiselect || multiSelectMode == MULTISELECT_MODE_SIMPLE) - && selectable); - } else { - deselectNode(focusedNode); - } - return true; - } - - // Home selection - if (keycode == getNavigationStartKey()) { - TreeNode node = getFirstRootNode(); - if (ctrl || !selectable) { - setFocusedNode(node); - } else if (shift) { - deselectAll(); - selectNodeRange(focusedNode.key, node.key); - } else { - selectNode(node, true); - } - sendSelectionToServer(); - return true; - } - - // End selection - if (keycode == getNavigationEndKey()) { - TreeNode lastNode = getLastRootNode(); - TreeNode node = getLastVisibleChildInTree(lastNode); - if (ctrl || !selectable) { - setFocusedNode(node); - } else if (shift) { - deselectAll(); - selectNodeRange(focusedNode.key, node.key); - } else { - selectNode(node, true); - } - sendSelectionToServer(); - return true; - } - - return false; - } - - private void focusAndSelectNode(TreeNode node) { - /* - * Keyboard navigation doesn't work reliably if the tree is in - * multiselect mode as well as isNullSelectionAllowed = false. It first - * tries to deselect the old focused node, which fails since there must - * be at least one selection. After this the newly focused node is - * selected and we've ended up with two selected nodes even though we - * only navigated with the arrow keys. - * - * Because of this, we first select the next node and later de-select - * the old one. - */ - TreeNode oldFocusedNode = focusedNode; - setFocusedNode(node); - setSelected(focusedNode, true); - setSelected(oldFocusedNode, false); - } - - /** - * Traverses the tree to the bottom most child - * - * @param root - * The root of the tree - * @return The bottom most child - */ - private TreeNode getLastVisibleChildInTree(TreeNode root) { - if (root.isLeaf() || !root.getState() || root.getChildren().size() == 0) { - return root; - } - List<TreeNode> children = root.getChildren(); - return getLastVisibleChildInTree(children.get(children.size() - 1)); - } - - /** - * Gets the next sibling in the tree - * - * @param node - * The node to get the sibling for - * @return The sibling node or null if the node is the last sibling - */ - private TreeNode getNextSibling(TreeNode node) { - TreeNode parent = node.getParentNode(); - List<TreeNode> children; - if (parent == null) { - children = getRootNodes(); - } else { - children = parent.getChildren(); - } - - int idx = children.indexOf(node); - if (idx < children.size() - 1) { - return children.get(idx + 1); - } - - return null; - } - - /** - * Returns the previous sibling in the tree - * - * @param node - * The node to get the sibling for - * @return The sibling node or null if the node is the first sibling - */ - private TreeNode getPreviousSibling(TreeNode node) { - TreeNode parent = node.getParentNode(); - List<TreeNode> children; - if (parent == null) { - children = getRootNodes(); - } else { - children = parent.getChildren(); - } - - int idx = children.indexOf(node); - if (idx > 0) { - return children.get(idx - 1); - } - - return null; - } - - /** - * Add this to the element mouse down event by using element.setPropertyJSO - * ("onselectstart",applyDisableTextSelectionIEHack()); Remove it then again - * when the mouse is depressed in the mouse up event. - * - * @return Returns the JSO preventing text selection - */ - private native JavaScriptObject applyDisableTextSelectionIEHack() - /*-{ - return function(){ return false; }; - }-*/; - - /** - * Get the key that moves the selection head upwards. By default it is the - * up arrow key but by overriding this you can change the key to whatever - * you want. - * - * @return The keycode of the key - */ - protected int getNavigationUpKey() { - return KeyCodes.KEY_UP; - } - - /** - * Get the key that moves the selection head downwards. By default it is the - * down arrow key but by overriding this you can change the key to whatever - * you want. - * - * @return The keycode of the key - */ - protected int getNavigationDownKey() { - return KeyCodes.KEY_DOWN; - } - - /** - * Get the key that scrolls to the left in the table. By default it is the - * left arrow key but by overriding this you can change the key to whatever - * you want. - * - * @return The keycode of the key - */ - protected int getNavigationLeftKey() { - return KeyCodes.KEY_LEFT; - } - - /** - * Get the key that scroll to the right on the table. By default it is the - * right arrow key but by overriding this you can change the key to whatever - * you want. - * - * @return The keycode of the key - */ - protected int getNavigationRightKey() { - return KeyCodes.KEY_RIGHT; - } - - /** - * Get the key that selects an item in the table. By default it is the space - * bar key but by overriding this you can change the key to whatever you - * want. - * - * @return - */ - protected int getNavigationSelectKey() { - return CHARCODE_SPACE; - } - - /** - * Get the key the moves the selection one page up in the table. By default - * this is the Page Up key but by overriding this you can change the key to - * whatever you want. - * - * @return - */ - protected int getNavigationPageUpKey() { - return KeyCodes.KEY_PAGEUP; - } - - /** - * Get the key the moves the selection one page down in the table. By - * default this is the Page Down key but by overriding this you can change - * the key to whatever you want. - * - * @return - */ - protected int getNavigationPageDownKey() { - return KeyCodes.KEY_PAGEDOWN; - } - - /** - * Get the key the moves the selection to the beginning of the table. By - * default this is the Home key but by overriding this you can change the - * key to whatever you want. - * - * @return - */ - protected int getNavigationStartKey() { - return KeyCodes.KEY_HOME; - } - - /** - * Get the key the moves the selection to the end of the table. By default - * this is the End key but by overriding this you can change the key to - * whatever you want. - * - * @return - */ - protected int getNavigationEndKey() { - return KeyCodes.KEY_END; - } - - private final String SUBPART_NODE_PREFIX = "n"; - private final String EXPAND_IDENTIFIER = "expand"; - - /* - * In webkit, focus may have been requested for this component but not yet - * gained. Use this to trac if tree has gained the focus on webkit. See - * FocusImplSafari and #6373 - */ - private boolean treeHasFocus; - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.SubPartAware#getSubPartElement(java - * .lang.String) - */ - @Override - public Element getSubPartElement(String subPart) { - if ("fe".equals(subPart)) { - if (BrowserInfo.get().isOpera() && focusedNode != null) { - return focusedNode.getElement(); - } - return getFocusElement(); - } - - if (subPart.startsWith(SUBPART_NODE_PREFIX + "[")) { - boolean expandCollapse = false; - - // Node - String[] nodes = subPart.split("/"); - TreeNode treeNode = null; - try { - for (String node : nodes) { - if (node.startsWith(SUBPART_NODE_PREFIX)) { - - // skip SUBPART_NODE_PREFIX"[" - node = node.substring(SUBPART_NODE_PREFIX.length() + 1); - // skip "]" - node = node.substring(0, node.length() - 1); - int position = Integer.parseInt(node); - if (treeNode == null) { - treeNode = getRootNodes().get(position); - } else { - treeNode = treeNode.getChildren().get(position); - } - } else if (node.startsWith(EXPAND_IDENTIFIER)) { - expandCollapse = true; - } - } - - if (expandCollapse) { - return treeNode.getElement(); - } else { - return treeNode.nodeCaptionSpan; - } - } catch (Exception e) { - // Invalid locator string or node could not be found - return null; - } - } - return null; - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.SubPartAware#getSubPartName(com.google - * .gwt.user.client.Element) - */ - @Override - public String getSubPartName(Element subElement) { - // Supported identifiers: - // - // n[index]/n[index]/n[index]{/expand} - // - // Ends with "/expand" if the target is expand/collapse indicator, - // otherwise ends with the node - - boolean isExpandCollapse = false; - - if (!getElement().isOrHasChild(subElement)) { - return null; - } - - if (subElement == getFocusElement()) { - return "fe"; - } - - TreeNode treeNode = Util.findWidget(subElement, TreeNode.class); - if (treeNode == null) { - // Did not click on a node, let somebody else take care of the - // locator string - return null; - } - - if (subElement == treeNode.getElement()) { - // Targets expand/collapse arrow - isExpandCollapse = true; - } - - ArrayList<Integer> positions = new ArrayList<Integer>(); - while (treeNode.getParentNode() != null) { - positions.add(0, - treeNode.getParentNode().getChildren().indexOf(treeNode)); - treeNode = treeNode.getParentNode(); - } - positions.add(0, getRootNodes().indexOf(treeNode)); - - String locator = ""; - for (Integer i : positions) { - locator += SUBPART_NODE_PREFIX + "[" + i + "]/"; - } - - locator = locator.substring(0, locator.length() - 1); - if (isExpandCollapse) { - locator += "/" + EXPAND_IDENTIFIER; - } - return locator; - } - - @Override - public Action[] getActions() { - if (bodyActionKeys == null) { - return new Action[] {}; - } - final Action[] actions = new Action[bodyActionKeys.length]; - for (int i = 0; i < actions.length; i++) { - final String actionKey = bodyActionKeys[i]; - final TreeAction a = new TreeAction(this, null, actionKey); - a.setCaption(getActionCaption(actionKey)); - a.setIconUrl(getActionIcon(actionKey)); - actions[i] = a; - } - return actions; - } - - @Override - public ApplicationConnection getClient() { - return client; - } - - @Override - public String getPaintableId() { - return paintableId; - } - - private void handleBodyContextMenu(ContextMenuEvent event) { - if (!readonly && !disabled) { - if (bodyActionKeys != null) { - int left = event.getNativeEvent().getClientX(); - int top = event.getNativeEvent().getClientY(); - top += Window.getScrollTop(); - left += Window.getScrollLeft(); - client.getContextMenu().showAt(this, left, top); - } - event.stopPropagation(); - event.preventDefault(); - } - } - - public void registerAction(String key, String caption, String iconUrl) { - actionMap.put(key + "_c", caption); - if (iconUrl != null) { - actionMap.put(key + "_i", iconUrl); - } else { - actionMap.remove(key + "_i"); - } - - } - - public void registerNode(TreeNode treeNode) { - keyToNode.put(treeNode.key, treeNode); - } - - public void clearNodeToKeyMap() { - keyToNode.clear(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/treetable/TreeTableConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/treetable/TreeTableConnector.java deleted file mode 100644 index 21f78c2356..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/treetable/TreeTableConnector.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.treetable; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.treetable.TreeTableConstants; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.FocusableScrollPanel; -import com.vaadin.terminal.gwt.client.ui.table.TableConnector; -import com.vaadin.terminal.gwt.client.ui.table.VScrollTable.VScrollTableBody.VScrollTableRow; -import com.vaadin.terminal.gwt.client.ui.treetable.VTreeTable.PendingNavigationEvent; -import com.vaadin.ui.TreeTable; - -@Connect(TreeTable.class) -public class TreeTableConnector extends TableConnector { - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - FocusableScrollPanel widget = null; - int scrollPosition = 0; - if (getWidget().collapseRequest) { - widget = (FocusableScrollPanel) getWidget().getWidget(1); - scrollPosition = widget.getScrollPosition(); - } - getWidget().animationsEnabled = uidl.getBooleanAttribute("animate"); - getWidget().colIndexOfHierarchy = uidl - .hasAttribute(TreeTableConstants.ATTRIBUTE_HIERARCHY_COLUMN_INDEX) ? uidl - .getIntAttribute(TreeTableConstants.ATTRIBUTE_HIERARCHY_COLUMN_INDEX) - : 0; - int oldTotalRows = getWidget().getTotalRows(); - super.updateFromUIDL(uidl, client); - if (getWidget().collapseRequest) { - if (getWidget().collapsedRowKey != null - && getWidget().scrollBody != null) { - VScrollTableRow row = getWidget().getRenderedRowByKey( - getWidget().collapsedRowKey); - if (row != null) { - getWidget().setRowFocus(row); - getWidget().focus(); - } - } - - int scrollPosition2 = widget.getScrollPosition(); - if (scrollPosition != scrollPosition2) { - widget.setScrollPosition(scrollPosition); - } - - // check which rows are needed from the server and initiate a - // deferred fetch - getWidget().onScroll(null); - } - // Recalculate table size if collapse request, or if page length is zero - // (not sent by server) and row count changes (#7908). - if (getWidget().collapseRequest - || (!uidl.hasAttribute("pagelength") && getWidget() - .getTotalRows() != oldTotalRows)) { - /* - * Ensure that possibly removed/added scrollbars are considered. - * Triggers row calculations, removes cached rows etc. Basically - * cleans up state. Be careful if touching this, you will break - * pageLength=0 if you remove this. - */ - getWidget().triggerLazyColumnAdjustment(true); - - getWidget().collapseRequest = false; - } - if (uidl.hasAttribute("focusedRow")) { - String key = uidl.getStringAttribute("focusedRow"); - getWidget().setRowFocus(getWidget().getRenderedRowByKey(key)); - getWidget().focusParentResponsePending = false; - } else if (uidl.hasAttribute("clearFocusPending")) { - // Special case to detect a response to a focusParent request that - // does not return any focusedRow because the selected node has no - // parent - getWidget().focusParentResponsePending = false; - } - - while (!getWidget().collapseRequest - && !getWidget().focusParentResponsePending - && !getWidget().pendingNavigationEvents.isEmpty()) { - // Keep replaying any queued events as long as we don't have any - // potential content changes pending - PendingNavigationEvent event = getWidget().pendingNavigationEvents - .removeFirst(); - getWidget() - .handleNavigation(event.keycode, event.ctrl, event.shift); - } - } - - @Override - public VTreeTable getWidget() { - return (VTreeTable) super.getWidget(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java b/client/src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java deleted file mode 100644 index 909acdf85f..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java +++ /dev/null @@ -1,865 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.treetable; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -import com.google.gwt.animation.client.Animation; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.ImageElement; -import com.google.gwt.dom.client.SpanElement; -import com.google.gwt.dom.client.Style.Display; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.dom.client.Style.Visibility; -import com.google.gwt.dom.client.TableCellElement; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.terminal.gwt.client.ComputedStyle; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.table.VScrollTable; -import com.vaadin.terminal.gwt.client.ui.treetable.VTreeTable.VTreeTableScrollBody.VTreeTableRow; - -public class VTreeTable extends VScrollTable { - - static class PendingNavigationEvent { - final int keycode; - final boolean ctrl; - final boolean shift; - - public PendingNavigationEvent(int keycode, boolean ctrl, boolean shift) { - this.keycode = keycode; - this.ctrl = ctrl; - this.shift = shift; - } - - @Override - public String toString() { - String string = "Keyboard event: " + keycode; - if (ctrl) { - string += " + ctrl"; - } - if (shift) { - string += " + shift"; - } - return string; - } - } - - boolean collapseRequest; - private boolean selectionPending; - int colIndexOfHierarchy; - String collapsedRowKey; - VTreeTableScrollBody scrollBody; - boolean animationsEnabled; - LinkedList<PendingNavigationEvent> pendingNavigationEvents = new LinkedList<VTreeTable.PendingNavigationEvent>(); - boolean focusParentResponsePending; - - @Override - protected VScrollTableBody createScrollBody() { - scrollBody = new VTreeTableScrollBody(); - return scrollBody; - } - - /* - * Overridden to allow animation of expands and collapses of nodes. - */ - @Override - protected void addAndRemoveRows(UIDL partialRowAdditions) { - if (partialRowAdditions == null) { - return; - } - - if (animationsEnabled) { - if (partialRowAdditions.hasAttribute("hide")) { - scrollBody.unlinkRowsAnimatedAndUpdateCacheWhenFinished( - partialRowAdditions.getIntAttribute("firstprowix"), - partialRowAdditions.getIntAttribute("numprows")); - } else { - scrollBody.insertRowsAnimated(partialRowAdditions, - partialRowAdditions.getIntAttribute("firstprowix"), - partialRowAdditions.getIntAttribute("numprows")); - discardRowsOutsideCacheWindow(); - } - } else { - super.addAndRemoveRows(partialRowAdditions); - } - } - - class VTreeTableScrollBody extends VScrollTable.VScrollTableBody { - private int indentWidth = -1; - - VTreeTableScrollBody() { - super(); - } - - @Override - protected VScrollTableRow createRow(UIDL uidl, char[] aligns2) { - if (uidl.hasAttribute("gen_html")) { - // This is a generated row. - return new VTreeTableGeneratedRow(uidl, aligns2); - } - return new VTreeTableRow(uidl, aligns2); - } - - class VTreeTableRow extends - VScrollTable.VScrollTableBody.VScrollTableRow { - - private boolean isTreeCellAdded = false; - private SpanElement treeSpacer; - private boolean open; - private int depth; - private boolean canHaveChildren; - protected Widget widgetInHierarchyColumn; - - public VTreeTableRow(UIDL uidl, char[] aligns2) { - super(uidl, aligns2); - } - - @Override - public void addCell(UIDL rowUidl, String text, char align, - String style, boolean textIsHTML, boolean isSorted, - String description) { - super.addCell(rowUidl, text, align, style, textIsHTML, - isSorted, description); - - addTreeSpacer(rowUidl); - } - - protected boolean addTreeSpacer(UIDL rowUidl) { - if (cellShowsTreeHierarchy(getElement().getChildCount() - 1)) { - Element container = (Element) getElement().getLastChild() - .getFirstChild(); - - if (rowUidl.hasAttribute("icon")) { - // icons are in first content cell in TreeTable - ImageElement icon = Document.get().createImageElement(); - icon.setClassName("v-icon"); - icon.setAlt("icon"); - icon.setSrc(client.translateVaadinUri(rowUidl - .getStringAttribute("icon"))); - container.insertFirst(icon); - } - - String classname = "v-treetable-treespacer"; - if (rowUidl.getBooleanAttribute("ca")) { - canHaveChildren = true; - open = rowUidl.getBooleanAttribute("open"); - classname += open ? " v-treetable-node-open" - : " v-treetable-node-closed"; - } - - treeSpacer = Document.get().createSpanElement(); - - treeSpacer.setClassName(classname); - container.insertFirst(treeSpacer); - depth = rowUidl.hasAttribute("depth") ? rowUidl - .getIntAttribute("depth") : 0; - setIndent(); - isTreeCellAdded = true; - return true; - } - return false; - } - - private boolean cellShowsTreeHierarchy(int curColIndex) { - if (isTreeCellAdded) { - return false; - } - return curColIndex == getHierarchyColumnIndex(); - } - - @Override - public void onBrowserEvent(Event event) { - if (event.getEventTarget().cast() == treeSpacer - && treeSpacer.getClassName().contains("node")) { - if (event.getTypeInt() == Event.ONMOUSEUP) { - sendToggleCollapsedUpdate(getKey()); - } - return; - } - super.onBrowserEvent(event); - } - - @Override - public void addCell(UIDL rowUidl, Widget w, char align, - String style, boolean isSorted) { - super.addCell(rowUidl, w, align, style, isSorted); - if (addTreeSpacer(rowUidl)) { - widgetInHierarchyColumn = w; - } - - } - - private void setIndent() { - if (getIndentWidth() > 0) { - treeSpacer.getParentElement().getStyle() - .setPaddingLeft(getIndent(), Unit.PX); - treeSpacer.getStyle().setWidth(getIndent(), Unit.PX); - } - } - - @Override - protected void onAttach() { - super.onAttach(); - if (getIndentWidth() < 0) { - detectIndent(this); - // If we detect indent here then the size of the hierarchy - // column is still wrong as it has been set when the indent - // was not known. - int w = getCellWidthFromDom(getHierarchyColumnIndex()); - if (w >= 0) { - setColWidth(getHierarchyColumnIndex(), w); - } - } - } - - private int getCellWidthFromDom(int cellIndex) { - final Element cell = DOM.getChild(getElement(), cellIndex); - String w = cell.getStyle().getProperty("width"); - if (w == null || "".equals(w) || !w.endsWith("px")) { - return -1; - } else { - return Integer.parseInt(w.substring(0, w.length() - 2)); - } - } - - private int getHierarchyAndIconWidth() { - int consumedSpace = treeSpacer.getOffsetWidth(); - if (treeSpacer.getParentElement().getChildCount() > 2) { - // icon next to tree spacer - consumedSpace += ((com.google.gwt.dom.client.Element) treeSpacer - .getNextSibling()).getOffsetWidth(); - } - return consumedSpace; - } - - @Override - protected void setCellWidth(int cellIx, int width) { - if (cellIx == getHierarchyColumnIndex()) { - // take indentation padding into account if this is the - // hierarchy column - int indent = getIndent(); - if (indent != -1) { - width = Math.max(width - getIndent(), 0); - } - } - super.setCellWidth(cellIx, width); - } - - private int getHierarchyColumnIndex() { - return colIndexOfHierarchy + (showRowHeaders ? 1 : 0); - } - - private int getIndent() { - return (depth + 1) * getIndentWidth(); - } - } - - protected class VTreeTableGeneratedRow extends VTreeTableRow { - private boolean spanColumns; - private boolean htmlContentAllowed; - - public VTreeTableGeneratedRow(UIDL uidl, char[] aligns) { - super(uidl, aligns); - addStyleName("v-table-generated-row"); - } - - public boolean isSpanColumns() { - return spanColumns; - } - - @Override - protected void initCellWidths() { - if (spanColumns) { - setSpannedColumnWidthAfterDOMFullyInited(); - } else { - super.initCellWidths(); - } - } - - private void setSpannedColumnWidthAfterDOMFullyInited() { - // Defer setting width on spanned columns to make sure that - // they are added to the DOM before trying to calculate - // widths. - Scheduler.get().scheduleDeferred(new ScheduledCommand() { - - @Override - public void execute() { - if (showRowHeaders) { - setCellWidth(0, tHead.getHeaderCell(0).getWidth()); - calcAndSetSpanWidthOnCell(1); - } else { - calcAndSetSpanWidthOnCell(0); - } - } - }); - } - - @Override - protected boolean isRenderHtmlInCells() { - return htmlContentAllowed; - } - - @Override - protected void addCellsFromUIDL(UIDL uidl, char[] aligns, int col, - int visibleColumnIndex) { - htmlContentAllowed = uidl.getBooleanAttribute("gen_html"); - spanColumns = uidl.getBooleanAttribute("gen_span"); - - final Iterator<?> cells = uidl.getChildIterator(); - if (spanColumns) { - int colCount = uidl.getChildCount(); - if (cells.hasNext()) { - final Object cell = cells.next(); - if (cell instanceof String) { - addSpannedCell(uidl, cell.toString(), aligns[0], - "", htmlContentAllowed, false, null, - colCount); - } else { - addSpannedCell(uidl, (Widget) cell, aligns[0], "", - false, colCount); - } - } - } else { - super.addCellsFromUIDL(uidl, aligns, col, - visibleColumnIndex); - } - } - - private void addSpannedCell(UIDL rowUidl, Widget w, char align, - String style, boolean sorted, int colCount) { - TableCellElement td = DOM.createTD().cast(); - td.setColSpan(colCount); - initCellWithWidget(w, align, style, sorted, td); - td.getStyle().setHeight(getRowHeight(), Unit.PX); - if (addTreeSpacer(rowUidl)) { - widgetInHierarchyColumn = w; - } - } - - private void addSpannedCell(UIDL rowUidl, String text, char align, - String style, boolean textIsHTML, boolean sorted, - String description, int colCount) { - // String only content is optimized by not using Label widget - final TableCellElement td = DOM.createTD().cast(); - td.setColSpan(colCount); - initCellWithText(text, align, style, textIsHTML, sorted, - description, td); - td.getStyle().setHeight(getRowHeight(), Unit.PX); - addTreeSpacer(rowUidl); - } - - @Override - protected void setCellWidth(int cellIx, int width) { - if (isSpanColumns()) { - if (showRowHeaders) { - if (cellIx == 0) { - super.setCellWidth(0, width); - } else { - // We need to recalculate the spanning TDs width for - // every cellIx in order to support column resizing. - calcAndSetSpanWidthOnCell(1); - } - } else { - // Same as above. - calcAndSetSpanWidthOnCell(0); - } - } else { - super.setCellWidth(cellIx, width); - } - } - - private void calcAndSetSpanWidthOnCell(final int cellIx) { - int spanWidth = 0; - for (int ix = (showRowHeaders ? 1 : 0); ix < tHead - .getVisibleCellCount(); ix++) { - spanWidth += tHead.getHeaderCell(ix).getOffsetWidth(); - } - Util.setWidthExcludingPaddingAndBorder((Element) getElement() - .getChild(cellIx), spanWidth, 13, false); - } - } - - private int getIndentWidth() { - return indentWidth; - } - - private void detectIndent(VTreeTableRow vTreeTableRow) { - indentWidth = vTreeTableRow.treeSpacer.getOffsetWidth(); - if (indentWidth == 0) { - indentWidth = -1; - return; - } - Iterator<Widget> iterator = iterator(); - while (iterator.hasNext()) { - VTreeTableRow next = (VTreeTableRow) iterator.next(); - next.setIndent(); - } - } - - protected void unlinkRowsAnimatedAndUpdateCacheWhenFinished( - final int firstIndex, final int rows) { - List<VScrollTableRow> rowsToDelete = new ArrayList<VScrollTableRow>(); - for (int ix = firstIndex; ix < firstIndex + rows; ix++) { - VScrollTableRow row = getRowByRowIndex(ix); - if (row != null) { - rowsToDelete.add(row); - } - } - if (!rowsToDelete.isEmpty()) { - // #8810 Only animate if there's something to animate - RowCollapseAnimation anim = new RowCollapseAnimation( - rowsToDelete) { - @Override - protected void onComplete() { - super.onComplete(); - // Actually unlink the rows and update the cache after - // the - // animation is done. - unlinkAndReindexRows(firstIndex, rows); - discardRowsOutsideCacheWindow(); - ensureCacheFilled(); - } - }; - anim.run(150); - } - } - - protected List<VScrollTableRow> insertRowsAnimated(UIDL rowData, - int firstIndex, int rows) { - List<VScrollTableRow> insertedRows = insertAndReindexRows(rowData, - firstIndex, rows); - if (!insertedRows.isEmpty()) { - // Only animate if there's something to animate (#8810) - RowExpandAnimation anim = new RowExpandAnimation(insertedRows); - anim.run(150); - } - return insertedRows; - } - - /** - * Prepares the table for animation by copying the background colors of - * all TR elements to their respective TD elements if the TD element is - * transparent. This is needed, since if TDs have transparent - * backgrounds, the rows sliding behind them are visible. - */ - private class AnimationPreparator { - private final int lastItemIx; - - public AnimationPreparator(int lastItemIx) { - this.lastItemIx = lastItemIx; - } - - public void prepareTableForAnimation() { - int ix = lastItemIx; - VScrollTableRow row = null; - while ((row = getRowByRowIndex(ix)) != null) { - copyTRBackgroundsToTDs(row); - --ix; - } - } - - private void copyTRBackgroundsToTDs(VScrollTableRow row) { - Element tr = row.getElement(); - ComputedStyle cs = new ComputedStyle(tr); - String backgroundAttachment = cs - .getProperty("backgroundAttachment"); - String backgroundClip = cs.getProperty("backgroundClip"); - String backgroundColor = cs.getProperty("backgroundColor"); - String backgroundImage = cs.getProperty("backgroundImage"); - String backgroundOrigin = cs.getProperty("backgroundOrigin"); - for (int ix = 0; ix < tr.getChildCount(); ix++) { - Element td = tr.getChild(ix).cast(); - if (!elementHasBackground(td)) { - td.getStyle().setProperty("backgroundAttachment", - backgroundAttachment); - td.getStyle().setProperty("backgroundClip", - backgroundClip); - td.getStyle().setProperty("backgroundColor", - backgroundColor); - td.getStyle().setProperty("backgroundImage", - backgroundImage); - td.getStyle().setProperty("backgroundOrigin", - backgroundOrigin); - } - } - } - - private boolean elementHasBackground(Element element) { - ComputedStyle cs = new ComputedStyle(element); - String clr = cs.getProperty("backgroundColor"); - String img = cs.getProperty("backgroundImage"); - return !("rgba(0, 0, 0, 0)".equals(clr.trim()) - || "transparent".equals(clr.trim()) || img == null); - } - - public void restoreTableAfterAnimation() { - int ix = lastItemIx; - VScrollTableRow row = null; - while ((row = getRowByRowIndex(ix)) != null) { - restoreStyleForTDsInRow(row); - - --ix; - } - } - - private void restoreStyleForTDsInRow(VScrollTableRow row) { - Element tr = row.getElement(); - for (int ix = 0; ix < tr.getChildCount(); ix++) { - Element td = tr.getChild(ix).cast(); - td.getStyle().clearProperty("backgroundAttachment"); - td.getStyle().clearProperty("backgroundClip"); - td.getStyle().clearProperty("backgroundColor"); - td.getStyle().clearProperty("backgroundImage"); - td.getStyle().clearProperty("backgroundOrigin"); - } - } - } - - /** - * Animates row expansion using the GWT animation framework. - * - * The idea is as follows: - * - * 1. Insert all rows normally - * - * 2. Insert a newly created DIV containing a new TABLE element below - * the DIV containing the actual scroll table body. - * - * 3. Clone the rows that were inserted in step 1 and attach the clones - * to the new TABLE element created in step 2. - * - * 4. The new DIV from step 2 is absolutely positioned so that the last - * inserted row is just behind the row that was expanded. - * - * 5. Hide the contents of the originally inserted rows by setting the - * DIV.v-table-cell-wrapper to display:none;. - * - * 6. Set the height of the originally inserted rows to 0. - * - * 7. The animation loop slides the DIV from step 2 downwards, while at - * the same pace growing the height of each of the inserted rows from 0 - * to full height. The first inserted row grows from 0 to full and after - * this the second row grows from 0 to full, etc until all rows are full - * height. - * - * 8. Remove the DIV from step 2 - * - * 9. Restore display:block; to the DIV.v-table-cell-wrapper elements. - * - * 10. DONE - */ - private class RowExpandAnimation extends Animation { - - private final List<VScrollTableRow> rows; - private Element cloneDiv; - private Element cloneTable; - private AnimationPreparator preparator; - - /** - * @param rows - * List of rows to animate. Must not be empty. - */ - public RowExpandAnimation(List<VScrollTableRow> rows) { - this.rows = rows; - buildAndInsertAnimatingDiv(); - preparator = new AnimationPreparator(rows.get(0).getIndex() - 1); - preparator.prepareTableForAnimation(); - for (VScrollTableRow row : rows) { - cloneAndAppendRow(row); - row.addStyleName("v-table-row-animating"); - setCellWrapperDivsToDisplayNone(row); - row.setHeight(getInitialHeight()); - } - } - - protected String getInitialHeight() { - return "0px"; - } - - private void cloneAndAppendRow(VScrollTableRow row) { - Element clonedTR = null; - clonedTR = row.getElement().cloneNode(true).cast(); - clonedTR.getStyle().setVisibility(Visibility.VISIBLE); - cloneTable.appendChild(clonedTR); - } - - protected double getBaseOffset() { - return rows.get(0).getAbsoluteTop() - - rows.get(0).getParent().getAbsoluteTop() - - rows.size() * getRowHeight(); - } - - private void buildAndInsertAnimatingDiv() { - cloneDiv = DOM.createDiv(); - cloneDiv.addClassName("v-treetable-animation-clone-wrapper"); - cloneTable = DOM.createTable(); - cloneTable.addClassName("v-treetable-animation-clone"); - cloneDiv.appendChild(cloneTable); - insertAnimatingDiv(); - } - - private void insertAnimatingDiv() { - Element tableBody = getElement().cast(); - Element tableBodyParent = tableBody.getParentElement().cast(); - tableBodyParent.insertAfter(cloneDiv, tableBody); - } - - @Override - protected void onUpdate(double progress) { - animateDiv(progress); - animateRowHeights(progress); - } - - private void animateDiv(double progress) { - double offset = calculateDivOffset(progress, getRowHeight()); - - cloneDiv.getStyle().setTop(getBaseOffset() + offset, Unit.PX); - } - - private void animateRowHeights(double progress) { - double rh = getRowHeight(); - double vlh = calculateHeightOfAllVisibleLines(progress, rh); - int ix = 0; - - while (ix < rows.size()) { - double height = vlh < rh ? vlh : rh; - rows.get(ix).setHeight(height + "px"); - vlh -= height; - ix++; - } - } - - protected double calculateHeightOfAllVisibleLines(double progress, - double rh) { - return rows.size() * rh * progress; - } - - protected double calculateDivOffset(double progress, double rh) { - return progress * rows.size() * rh; - } - - @Override - protected void onComplete() { - preparator.restoreTableAfterAnimation(); - for (VScrollTableRow row : rows) { - resetCellWrapperDivsDisplayProperty(row); - row.removeStyleName("v-table-row-animating"); - } - Element tableBodyParent = (Element) getElement() - .getParentElement(); - tableBodyParent.removeChild(cloneDiv); - } - - private void setCellWrapperDivsToDisplayNone(VScrollTableRow row) { - Element tr = row.getElement(); - for (int ix = 0; ix < tr.getChildCount(); ix++) { - getWrapperDiv(tr, ix).getStyle().setDisplay(Display.NONE); - } - } - - private Element getWrapperDiv(Element tr, int tdIx) { - Element td = tr.getChild(tdIx).cast(); - return td.getChild(0).cast(); - } - - private void resetCellWrapperDivsDisplayProperty(VScrollTableRow row) { - Element tr = row.getElement(); - for (int ix = 0; ix < tr.getChildCount(); ix++) { - getWrapperDiv(tr, ix).getStyle().clearProperty("display"); - } - } - - } - - /** - * This is the inverse of the RowExpandAnimation and is implemented by - * extending it and overriding the calculation of offsets and heights. - */ - private class RowCollapseAnimation extends RowExpandAnimation { - - private final List<VScrollTableRow> rows; - - /** - * @param rows - * List of rows to animate. Must not be empty. - */ - public RowCollapseAnimation(List<VScrollTableRow> rows) { - super(rows); - this.rows = rows; - } - - @Override - protected String getInitialHeight() { - return getRowHeight() + "px"; - } - - @Override - protected double getBaseOffset() { - return getRowHeight(); - } - - @Override - protected double calculateHeightOfAllVisibleLines(double progress, - double rh) { - return rows.size() * rh * (1 - progress); - } - - @Override - protected double calculateDivOffset(double progress, double rh) { - return -super.calculateDivOffset(progress, rh); - } - } - } - - /** - * Icons rendered into first actual column in TreeTable, not to row header - * cell - */ - @Override - protected String buildCaptionHtmlSnippet(UIDL uidl) { - if (uidl.getTag().equals("column")) { - return super.buildCaptionHtmlSnippet(uidl); - } else { - String s = uidl.getStringAttribute("caption"); - return s; - } - } - - @Override - protected boolean handleNavigation(int keycode, boolean ctrl, boolean shift) { - if (collapseRequest || focusParentResponsePending) { - // Enqueue the event if there might be pending content changes from - // the server - if (pendingNavigationEvents.size() < 10) { - // Only keep 10 keyboard events in the queue - PendingNavigationEvent pendingNavigationEvent = new PendingNavigationEvent( - keycode, ctrl, shift); - pendingNavigationEvents.add(pendingNavigationEvent); - } - return true; - } - - VTreeTableRow focusedRow = (VTreeTableRow) getFocusedRow(); - if (focusedRow != null) { - if (focusedRow.canHaveChildren - && ((keycode == KeyCodes.KEY_RIGHT && !focusedRow.open) || (keycode == KeyCodes.KEY_LEFT && focusedRow.open))) { - if (!ctrl) { - client.updateVariable(paintableId, "selectCollapsed", true, - false); - } - sendSelectedRows(false); - sendToggleCollapsedUpdate(focusedRow.getKey()); - return true; - } else if (keycode == KeyCodes.KEY_RIGHT && focusedRow.open) { - // already expanded, move selection down if next is on a deeper - // level (is-a-child) - VTreeTableScrollBody body = (VTreeTableScrollBody) focusedRow - .getParent(); - Iterator<Widget> iterator = body.iterator(); - VTreeTableRow next = null; - while (iterator.hasNext()) { - next = (VTreeTableRow) iterator.next(); - if (next == focusedRow) { - next = (VTreeTableRow) iterator.next(); - break; - } - } - if (next != null) { - if (next.depth > focusedRow.depth) { - selectionPending = true; - return super.handleNavigation(getNavigationDownKey(), - ctrl, shift); - } - } else { - // Note, a minor change here for a bit false behavior if - // cache rows is disabled + last visible row + no childs for - // the node - selectionPending = true; - return super.handleNavigation(getNavigationDownKey(), ctrl, - shift); - } - } else if (keycode == KeyCodes.KEY_LEFT) { - // already collapsed move selection up to parent node - // do on the server side as the parent is not necessary - // rendered on the client, could check if parent is visible if - // a performance issue arises - - client.updateVariable(paintableId, "focusParent", - focusedRow.getKey(), true); - - // Set flag that we should enqueue navigation events until we - // get a response to this request - focusParentResponsePending = true; - - return true; - } - } - return super.handleNavigation(keycode, ctrl, shift); - } - - private void sendToggleCollapsedUpdate(String rowKey) { - collapsedRowKey = rowKey; - collapseRequest = true; - client.updateVariable(paintableId, "toggleCollapsed", rowKey, true); - } - - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - if (event.getTypeInt() == Event.ONKEYUP && selectionPending) { - sendSelectedRows(); - } - } - - @Override - protected void sendSelectedRows(boolean immediately) { - super.sendSelectedRows(immediately); - selectionPending = false; - } - - @Override - protected void reOrderColumn(String columnKey, int newIndex) { - super.reOrderColumn(columnKey, newIndex); - // current impl not intelligent enough to survive without visiting the - // server to redraw content - client.sendPendingVariableChanges(); - } - - @Override - public void setStyleName(String style) { - super.setStyleName(style + " v-treetable"); - } - - @Override - protected void updateTotalRows(UIDL uidl) { - // Make sure that initializedAndAttached & al are not reset when the - // totalrows are updated on expand/collapse requests. - int newTotalRows = uidl.getIntAttribute("totalrows"); - setTotalRows(newTotalRows); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/twincolselect/TwinColSelectConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/twincolselect/TwinColSelectConnector.java deleted file mode 100644 index c4a5437149..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/twincolselect/TwinColSelectConnector.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.twincolselect; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.DirectionalManagedLayout; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.optiongroup.OptionGroupBaseConnector; -import com.vaadin.ui.TwinColSelect; - -@Connect(TwinColSelect.class) -public class TwinColSelectConnector extends OptionGroupBaseConnector implements - DirectionalManagedLayout { - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - // Captions are updated before super call to ensure the widths are set - // correctly - if (isRealUpdate(uidl)) { - getWidget().updateCaptions(uidl); - getLayoutManager().setNeedsHorizontalLayout(this); - } - - super.updateFromUIDL(uidl, client); - } - - @Override - protected void init() { - super.init(); - getLayoutManager().registerDependency(this, - getWidget().captionWrapper.getElement()); - } - - @Override - public void onUnregister() { - getLayoutManager().unregisterDependency(this, - getWidget().captionWrapper.getElement()); - } - - @Override - public VTwinColSelect getWidget() { - return (VTwinColSelect) super.getWidget(); - } - - @Override - public void layoutVertically() { - if (isUndefinedHeight()) { - getWidget().clearInternalHeights(); - } else { - getWidget().setInternalHeights(); - } - } - - @Override - public void layoutHorizontally() { - if (isUndefinedWidth()) { - getWidget().clearInternalWidths(); - } else { - getWidget().setInternalWidths(); - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/twincolselect/VTwinColSelect.java b/client/src/com/vaadin/terminal/gwt/client/ui/twincolselect/VTwinColSelect.java deleted file mode 100644 index fef44eb502..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/twincolselect/VTwinColSelect.java +++ /dev/null @@ -1,621 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.twincolselect; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import com.google.gwt.dom.client.Style.Overflow; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.DoubleClickEvent; -import com.google.gwt.event.dom.client.DoubleClickHandler; -import com.google.gwt.event.dom.client.HasDoubleClickHandlers; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.MouseDownEvent; -import com.google.gwt.event.dom.client.MouseDownHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.ListBox; -import com.google.gwt.user.client.ui.Panel; -import com.vaadin.shared.ui.twincolselect.TwinColSelectConstants; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.SubPartAware; -import com.vaadin.terminal.gwt.client.ui.button.VButton; -import com.vaadin.terminal.gwt.client.ui.optiongroup.VOptionGroupBase; - -public class VTwinColSelect extends VOptionGroupBase implements KeyDownHandler, - MouseDownHandler, DoubleClickHandler, SubPartAware { - - private static final String CLASSNAME = "v-select-twincol"; - - private static final int VISIBLE_COUNT = 10; - - private static final int DEFAULT_COLUMN_COUNT = 10; - - private final DoubleClickListBox options; - - private final DoubleClickListBox selections; - - FlowPanel captionWrapper; - - private HTML optionsCaption = null; - - private HTML selectionsCaption = null; - - private final VButton add; - - private final VButton remove; - - private final FlowPanel buttons; - - private final Panel panel; - - /** - * A ListBox which catches double clicks - * - */ - public class DoubleClickListBox extends ListBox implements - HasDoubleClickHandlers { - public DoubleClickListBox(boolean isMultipleSelect) { - super(isMultipleSelect); - } - - public DoubleClickListBox() { - super(); - } - - @Override - public HandlerRegistration addDoubleClickHandler( - DoubleClickHandler handler) { - return addDomHandler(handler, DoubleClickEvent.getType()); - } - } - - public VTwinColSelect() { - super(CLASSNAME); - - captionWrapper = new FlowPanel(); - - options = new DoubleClickListBox(); - options.addClickHandler(this); - options.addDoubleClickHandler(this); - options.setVisibleItemCount(VISIBLE_COUNT); - options.setStyleName(CLASSNAME + "-options"); - - selections = new DoubleClickListBox(); - selections.addClickHandler(this); - selections.addDoubleClickHandler(this); - selections.setVisibleItemCount(VISIBLE_COUNT); - selections.setStyleName(CLASSNAME + "-selections"); - - buttons = new FlowPanel(); - buttons.setStyleName(CLASSNAME + "-buttons"); - add = new VButton(); - add.setText(">>"); - add.addClickHandler(this); - remove = new VButton(); - remove.setText("<<"); - remove.addClickHandler(this); - - panel = ((Panel) optionsContainer); - - panel.add(captionWrapper); - captionWrapper.getElement().getStyle().setOverflow(Overflow.HIDDEN); - // Hide until there actually is a caption to prevent IE from rendering - // extra empty space - captionWrapper.setVisible(false); - - panel.add(options); - buttons.add(add); - final HTML br = new HTML("<span/>"); - br.setStyleName(CLASSNAME + "-deco"); - buttons.add(br); - buttons.add(remove); - panel.add(buttons); - panel.add(selections); - - options.addKeyDownHandler(this); - options.addMouseDownHandler(this); - - selections.addMouseDownHandler(this); - selections.addKeyDownHandler(this); - } - - public HTML getOptionsCaption() { - if (optionsCaption == null) { - optionsCaption = new HTML(); - optionsCaption.setStyleName(CLASSNAME + "-caption-left"); - optionsCaption.getElement().getStyle() - .setFloat(com.google.gwt.dom.client.Style.Float.LEFT); - captionWrapper.add(optionsCaption); - } - - return optionsCaption; - } - - public HTML getSelectionsCaption() { - if (selectionsCaption == null) { - selectionsCaption = new HTML(); - selectionsCaption.setStyleName(CLASSNAME + "-caption-right"); - selectionsCaption.getElement().getStyle() - .setFloat(com.google.gwt.dom.client.Style.Float.RIGHT); - captionWrapper.add(selectionsCaption); - } - - return selectionsCaption; - } - - protected void updateCaptions(UIDL uidl) { - String leftCaption = (uidl - .hasAttribute(TwinColSelectConstants.ATTRIBUTE_LEFT_CAPTION) ? uidl - .getStringAttribute(TwinColSelectConstants.ATTRIBUTE_LEFT_CAPTION) - : null); - String rightCaption = (uidl - .hasAttribute(TwinColSelectConstants.ATTRIBUTE_RIGHT_CAPTION) ? uidl - .getStringAttribute(TwinColSelectConstants.ATTRIBUTE_RIGHT_CAPTION) - : null); - - boolean hasCaptions = (leftCaption != null || rightCaption != null); - - if (leftCaption == null) { - removeOptionsCaption(); - } else { - getOptionsCaption().setText(leftCaption); - - } - - if (rightCaption == null) { - removeSelectionsCaption(); - } else { - getSelectionsCaption().setText(rightCaption); - } - - captionWrapper.setVisible(hasCaptions); - } - - private void removeOptionsCaption() { - if (optionsCaption == null) { - return; - } - - if (optionsCaption.getParent() != null) { - captionWrapper.remove(optionsCaption); - } - - optionsCaption = null; - } - - private void removeSelectionsCaption() { - if (selectionsCaption == null) { - return; - } - - if (selectionsCaption.getParent() != null) { - captionWrapper.remove(selectionsCaption); - } - - selectionsCaption = null; - } - - @Override - protected void buildOptions(UIDL uidl) { - final boolean enabled = !isDisabled() && !isReadonly(); - options.setMultipleSelect(isMultiselect()); - selections.setMultipleSelect(isMultiselect()); - options.setEnabled(enabled); - selections.setEnabled(enabled); - add.setEnabled(enabled); - remove.setEnabled(enabled); - options.clear(); - selections.clear(); - for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) { - final UIDL optionUidl = (UIDL) i.next(); - if (optionUidl.hasAttribute("selected")) { - selections.addItem(optionUidl.getStringAttribute("caption"), - optionUidl.getStringAttribute("key")); - } else { - options.addItem(optionUidl.getStringAttribute("caption"), - optionUidl.getStringAttribute("key")); - } - } - - if (getRows() > 0) { - options.setVisibleItemCount(getRows()); - selections.setVisibleItemCount(getRows()); - - } - - } - - @Override - protected String[] getSelectedItems() { - final ArrayList<String> selectedItemKeys = new ArrayList<String>(); - for (int i = 0; i < selections.getItemCount(); i++) { - selectedItemKeys.add(selections.getValue(i)); - } - return selectedItemKeys.toArray(new String[selectedItemKeys.size()]); - } - - private boolean[] getSelectionBitmap(ListBox listBox) { - final boolean[] selectedIndexes = new boolean[listBox.getItemCount()]; - for (int i = 0; i < listBox.getItemCount(); i++) { - if (listBox.isItemSelected(i)) { - selectedIndexes[i] = true; - } else { - selectedIndexes[i] = false; - } - } - return selectedIndexes; - } - - private void addItem() { - Set<String> movedItems = moveSelectedItems(options, selections); - selectedKeys.addAll(movedItems); - - client.updateVariable(paintableId, "selected", - selectedKeys.toArray(new String[selectedKeys.size()]), - isImmediate()); - } - - private void removeItem() { - Set<String> movedItems = moveSelectedItems(selections, options); - selectedKeys.removeAll(movedItems); - - client.updateVariable(paintableId, "selected", - selectedKeys.toArray(new String[selectedKeys.size()]), - isImmediate()); - } - - private Set<String> moveSelectedItems(ListBox source, ListBox target) { - final boolean[] sel = getSelectionBitmap(source); - final Set<String> movedItems = new HashSet<String>(); - int lastSelected = 0; - for (int i = 0; i < sel.length; i++) { - if (sel[i]) { - final int optionIndex = i - - (sel.length - source.getItemCount()); - movedItems.add(source.getValue(optionIndex)); - - // Move selection to another column - final String text = source.getItemText(optionIndex); - final String value = source.getValue(optionIndex); - target.addItem(text, value); - target.setItemSelected(target.getItemCount() - 1, true); - source.removeItem(optionIndex); - - if (source.getItemCount() > 0) { - lastSelected = optionIndex > 0 ? optionIndex - 1 : 0; - } - } - } - - if (source.getItemCount() > 0) { - source.setSelectedIndex(lastSelected); - } - - // If no items are left move the focus to the selections - if (source.getItemCount() == 0) { - target.setFocus(true); - } else { - source.setFocus(true); - } - - return movedItems; - } - - @Override - public void onClick(ClickEvent event) { - super.onClick(event); - if (event.getSource() == add) { - addItem(); - - } else if (event.getSource() == remove) { - removeItem(); - - } else if (event.getSource() == options) { - // unselect all in other list, to avoid mistakes (i.e wrong button) - final int c = selections.getItemCount(); - for (int i = 0; i < c; i++) { - selections.setItemSelected(i, false); - } - } else if (event.getSource() == selections) { - // unselect all in other list, to avoid mistakes (i.e wrong button) - final int c = options.getItemCount(); - for (int i = 0; i < c; i++) { - options.setItemSelected(i, false); - } - } - } - - void clearInternalHeights() { - selections.setHeight(""); - options.setHeight(""); - } - - void setInternalHeights() { - int captionHeight = Util.getRequiredHeight(captionWrapper); - int totalHeight = getOffsetHeight(); - - String selectHeight = (totalHeight - captionHeight) + "px"; - - selections.setHeight(selectHeight); - options.setHeight(selectHeight); - - } - - void clearInternalWidths() { - int cols = -1; - if (getColumns() > 0) { - cols = getColumns(); - } else { - cols = DEFAULT_COLUMN_COUNT; - } - - if (cols >= 0) { - String colWidth = cols + "em"; - String containerWidth = (2 * cols + 4) + "em"; - // Caption wrapper width == optionsSelect + buttons + - // selectionsSelect - String captionWrapperWidth = (2 * cols + 4 - 0.5) + "em"; - - options.setWidth(colWidth); - if (optionsCaption != null) { - optionsCaption.setWidth(colWidth); - } - selections.setWidth(colWidth); - if (selectionsCaption != null) { - selectionsCaption.setWidth(colWidth); - } - buttons.setWidth("3.5em"); - optionsContainer.setWidth(containerWidth); - captionWrapper.setWidth(captionWrapperWidth); - } - } - - void setInternalWidths() { - DOM.setStyleAttribute(getElement(), "position", "relative"); - int bordersAndPaddings = Util.measureHorizontalPaddingAndBorder( - buttons.getElement(), 0); - - int buttonWidth = Util.getRequiredWidth(buttons); - int totalWidth = getOffsetWidth(); - - int spaceForSelect = (totalWidth - buttonWidth - bordersAndPaddings) / 2; - - options.setWidth(spaceForSelect + "px"); - if (optionsCaption != null) { - optionsCaption.setWidth(spaceForSelect + "px"); - } - - selections.setWidth(spaceForSelect + "px"); - if (selectionsCaption != null) { - selectionsCaption.setWidth(spaceForSelect + "px"); - } - captionWrapper.setWidth("100%"); - } - - @Override - protected void setTabIndex(int tabIndex) { - options.setTabIndex(tabIndex); - selections.setTabIndex(tabIndex); - add.setTabIndex(tabIndex); - remove.setTabIndex(tabIndex); - } - - @Override - public void focus() { - options.setFocus(true); - } - - /** - * Get the key that selects an item in the table. By default it is the Enter - * key but by overriding this you can change the key to whatever you want. - * - * @return - */ - protected int getNavigationSelectKey() { - return KeyCodes.KEY_ENTER; - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt - * .event.dom.client.KeyDownEvent) - */ - @Override - public void onKeyDown(KeyDownEvent event) { - int keycode = event.getNativeKeyCode(); - - // Catch tab and move between select:s - if (keycode == KeyCodes.KEY_TAB && event.getSource() == options) { - // Prevent default behavior - event.preventDefault(); - - // Remove current selections - for (int i = 0; i < options.getItemCount(); i++) { - options.setItemSelected(i, false); - } - - // Focus selections - selections.setFocus(true); - } - - if (keycode == KeyCodes.KEY_TAB && event.isShiftKeyDown() - && event.getSource() == selections) { - // Prevent default behavior - event.preventDefault(); - - // Remove current selections - for (int i = 0; i < selections.getItemCount(); i++) { - selections.setItemSelected(i, false); - } - - // Focus options - options.setFocus(true); - } - - if (keycode == getNavigationSelectKey()) { - // Prevent default behavior - event.preventDefault(); - - // Decide which select the selection was made in - if (event.getSource() == options) { - // Prevents the selection to become a single selection when - // using Enter key - // as the selection key (default) - options.setFocus(false); - - addItem(); - - } else if (event.getSource() == selections) { - // Prevents the selection to become a single selection when - // using Enter key - // as the selection key (default) - selections.setFocus(false); - - removeItem(); - } - } - - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.MouseDownHandler#onMouseDown(com.google - * .gwt.event.dom.client.MouseDownEvent) - */ - @Override - public void onMouseDown(MouseDownEvent event) { - // Ensure that items are deselected when selecting - // from a different source. See #3699 for details. - if (event.getSource() == options) { - for (int i = 0; i < selections.getItemCount(); i++) { - selections.setItemSelected(i, false); - } - } else if (event.getSource() == selections) { - for (int i = 0; i < options.getItemCount(); i++) { - options.setItemSelected(i, false); - } - } - - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.DoubleClickHandler#onDoubleClick(com. - * google.gwt.event.dom.client.DoubleClickEvent) - */ - @Override - public void onDoubleClick(DoubleClickEvent event) { - if (event.getSource() == options) { - addItem(); - options.setSelectedIndex(-1); - options.setFocus(false); - } else if (event.getSource() == selections) { - removeItem(); - selections.setSelectedIndex(-1); - selections.setFocus(false); - } - - } - - private static final String SUBPART_OPTION_SELECT = "leftSelect"; - private static final String SUBPART_OPTION_SELECT_ITEM = SUBPART_OPTION_SELECT - + "-item"; - private static final String SUBPART_SELECTION_SELECT = "rightSelect"; - private static final String SUBPART_SELECTION_SELECT_ITEM = SUBPART_SELECTION_SELECT - + "-item"; - private static final String SUBPART_LEFT_CAPTION = "leftCaption"; - private static final String SUBPART_RIGHT_CAPTION = "rightCaption"; - private static final String SUBPART_ADD_BUTTON = "add"; - private static final String SUBPART_REMOVE_BUTTON = "remove"; - - @Override - public Element getSubPartElement(String subPart) { - if (SUBPART_OPTION_SELECT.equals(subPart)) { - return options.getElement(); - } else if (subPart.startsWith(SUBPART_OPTION_SELECT_ITEM)) { - String idx = subPart.substring(SUBPART_OPTION_SELECT_ITEM.length()); - return (Element) options.getElement().getChild( - Integer.parseInt(idx)); - } else if (SUBPART_SELECTION_SELECT.equals(subPart)) { - return selections.getElement(); - } else if (subPart.startsWith(SUBPART_SELECTION_SELECT_ITEM)) { - String idx = subPart.substring(SUBPART_SELECTION_SELECT_ITEM - .length()); - return (Element) selections.getElement().getChild( - Integer.parseInt(idx)); - } else if (optionsCaption != null - && SUBPART_LEFT_CAPTION.equals(subPart)) { - return optionsCaption.getElement(); - } else if (selectionsCaption != null - && SUBPART_RIGHT_CAPTION.equals(subPart)) { - return selectionsCaption.getElement(); - } else if (SUBPART_ADD_BUTTON.equals(subPart)) { - return add.getElement(); - } else if (SUBPART_REMOVE_BUTTON.equals(subPart)) { - return remove.getElement(); - } - - return null; - } - - @Override - public String getSubPartName(Element subElement) { - if (optionsCaption != null - && optionsCaption.getElement().isOrHasChild(subElement)) { - return SUBPART_LEFT_CAPTION; - } else if (selectionsCaption != null - && selectionsCaption.getElement().isOrHasChild(subElement)) { - return SUBPART_RIGHT_CAPTION; - } else if (options.getElement().isOrHasChild(subElement)) { - if (options.getElement() == subElement) { - return SUBPART_OPTION_SELECT; - } else { - int idx = Util.getChildElementIndex(subElement); - return SUBPART_OPTION_SELECT_ITEM + idx; - } - } else if (selections.getElement().isOrHasChild(subElement)) { - if (selections.getElement() == subElement) { - return SUBPART_SELECTION_SELECT; - } else { - int idx = Util.getChildElementIndex(subElement); - return SUBPART_SELECTION_SELECT_ITEM + idx; - } - } else if (add.getElement().isOrHasChild(subElement)) { - return SUBPART_ADD_BUTTON; - } else if (remove.getElement().isOrHasChild(subElement)) { - return SUBPART_REMOVE_BUTTON; - } - - return null; - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/upload/UploadConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/upload/UploadConnector.java deleted file mode 100644 index 83be123eb9..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/upload/UploadConnector.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.upload; - -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; -import com.vaadin.ui.Upload; - -@Connect(value = Upload.class, loadStyle = LoadStyle.LAZY) -public class UploadConnector extends AbstractComponentConnector implements - Paintable { - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (!isRealUpdate(uidl)) { - return; - } - if (uidl.hasAttribute("notStarted")) { - getWidget().t.schedule(400); - return; - } - if (uidl.hasAttribute("forceSubmit")) { - getWidget().submit(); - return; - } - getWidget().setImmediate(getState().isImmediate()); - getWidget().client = client; - getWidget().paintableId = uidl.getId(); - getWidget().nextUploadId = uidl.getIntAttribute("nextid"); - final String action = client.translateVaadinUri(uidl - .getStringVariable("action")); - getWidget().element.setAction(action); - if (uidl.hasAttribute("buttoncaption")) { - getWidget().submitButton.setText(uidl - .getStringAttribute("buttoncaption")); - getWidget().submitButton.setVisible(true); - } else { - getWidget().submitButton.setVisible(false); - } - getWidget().fu.setName(getWidget().paintableId + "_file"); - - if (!isEnabled() || isReadOnly()) { - getWidget().disableUpload(); - } else if (!uidl.getBooleanAttribute("state")) { - // Enable the button only if an upload is not in progress - getWidget().enableUpload(); - getWidget().ensureTargetFrame(); - } - } - - @Override - public VUpload getWidget() { - return (VUpload) super.getWidget(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/upload/UploadIFrameOnloadStrategy.java b/client/src/com/vaadin/terminal/gwt/client/ui/upload/UploadIFrameOnloadStrategy.java deleted file mode 100644 index e81b4909ba..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/upload/UploadIFrameOnloadStrategy.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.upload; - -public class UploadIFrameOnloadStrategy { - - native void hookEvents(com.google.gwt.dom.client.Element iframe, - VUpload upload) - /*-{ - iframe.onload = $entry(function() { - upload.@com.vaadin.terminal.gwt.client.ui.upload.VUpload::onSubmitComplete()(); - }); - }-*/; - - /** - * @param iframe - * the iframe whose onLoad event is to be cleaned - */ - native void unHookEvents(com.google.gwt.dom.client.Element iframe) - /*-{ - iframe.onload = null; - }-*/; - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/upload/UploadIFrameOnloadStrategyIE.java b/client/src/com/vaadin/terminal/gwt/client/ui/upload/UploadIFrameOnloadStrategyIE.java deleted file mode 100644 index 0f885261e3..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/upload/UploadIFrameOnloadStrategyIE.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.upload; - -import com.google.gwt.dom.client.Element; - -/** - * IE does not have onload, detect onload via readystatechange - * - */ -public class UploadIFrameOnloadStrategyIE extends UploadIFrameOnloadStrategy { - @Override - native void hookEvents(Element iframe, VUpload upload) - /*-{ - iframe.onreadystatechange = $entry(function() { - if (iframe.readyState == 'complete') { - upload.@com.vaadin.terminal.gwt.client.ui.upload.VUpload::onSubmitComplete()(); - } - }); - }-*/; - - @Override - native void unHookEvents(Element iframe) - /*-{ - iframe.onreadystatechange = null; - }-*/; - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/upload/VUpload.java b/client/src/com/vaadin/terminal/gwt/client/ui/upload/VUpload.java deleted file mode 100644 index 759236ea7f..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/upload/VUpload.java +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.upload; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.dom.client.DivElement; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.FormElement; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.ui.FileUpload; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.FormPanel; -import com.google.gwt.user.client.ui.Hidden; -import com.google.gwt.user.client.ui.Panel; -import com.google.gwt.user.client.ui.SimplePanel; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.VConsole; -import com.vaadin.terminal.gwt.client.ui.button.VButton; - -/** - * - * Note, we are not using GWT FormPanel as we want to listen submitcomplete - * events even though the upload component is already detached. - * - */ -public class VUpload extends SimplePanel { - - private final class MyFileUpload extends FileUpload { - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - if (event.getTypeInt() == Event.ONCHANGE) { - if (immediate && fu.getFilename() != null - && !"".equals(fu.getFilename())) { - submit(); - } - } else if (BrowserInfo.get().isIE() - && event.getTypeInt() == Event.ONFOCUS) { - // IE and user has clicked on hidden textarea part of upload - // field. Manually open file selector, other browsers do it by - // default. - fireNativeClick(fu.getElement()); - // also remove focus to enable hack if user presses cancel - // button - fireNativeBlur(fu.getElement()); - } - } - } - - public static final String CLASSNAME = "v-upload"; - - /** - * FileUpload component that opens native OS dialog to select file. - */ - FileUpload fu = new MyFileUpload(); - - Panel panel = new FlowPanel(); - - UploadIFrameOnloadStrategy onloadstrategy = GWT - .create(UploadIFrameOnloadStrategy.class); - - ApplicationConnection client; - - protected String paintableId; - - /** - * Button that initiates uploading - */ - protected final VButton submitButton; - - /** - * When expecting big files, programmer may initiate some UI changes when - * uploading the file starts. Bit after submitting file we'll visit the - * server to check possible changes. - */ - protected Timer t; - - /** - * some browsers tries to send form twice if submit is called in button - * click handler, some don't submit at all without it, so we need to track - * if form is already being submitted - */ - private boolean submitted = false; - - private boolean enabled = true; - - private boolean immediate; - - private Hidden maxfilesize = new Hidden(); - - protected FormElement element; - - private com.google.gwt.dom.client.Element synthesizedFrame; - - protected int nextUploadId; - - public VUpload() { - super(com.google.gwt.dom.client.Document.get().createFormElement()); - - element = getElement().cast(); - setEncoding(getElement(), FormPanel.ENCODING_MULTIPART); - element.setMethod(FormPanel.METHOD_POST); - - setWidget(panel); - panel.add(maxfilesize); - panel.add(fu); - submitButton = new VButton(); - submitButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - if (immediate) { - // fire click on upload (eg. focused button and hit space) - fireNativeClick(fu.getElement()); - } else { - submit(); - } - } - }); - panel.add(submitButton); - - setStyleName(CLASSNAME); - } - - private static native void setEncoding(Element form, String encoding) - /*-{ - form.enctype = encoding; - }-*/; - - protected void setImmediate(boolean booleanAttribute) { - if (immediate != booleanAttribute) { - immediate = booleanAttribute; - if (immediate) { - fu.sinkEvents(Event.ONCHANGE); - fu.sinkEvents(Event.ONFOCUS); - } - } - setStyleName(getElement(), CLASSNAME + "-immediate", immediate); - } - - private static native void fireNativeClick(Element element) - /*-{ - element.click(); - }-*/; - - private static native void fireNativeBlur(Element element) - /*-{ - element.blur(); - }-*/; - - protected void disableUpload() { - submitButton.setEnabled(false); - if (!submitted) { - // Cannot disable the fileupload while submitting or the file won't - // be submitted at all - fu.getElement().setPropertyBoolean("disabled", true); - } - enabled = false; - } - - protected void enableUpload() { - submitButton.setEnabled(true); - fu.getElement().setPropertyBoolean("disabled", false); - enabled = true; - if (submitted) { - /* - * An old request is still in progress (most likely cancelled), - * ditching that target frame to make it possible to send a new - * file. A new target frame is created later." - */ - cleanTargetFrame(); - submitted = false; - } - } - - /** - * Re-creates file input field and populates panel. This is needed as we - * want to clear existing values from our current file input field. - */ - private void rebuildPanel() { - panel.remove(submitButton); - panel.remove(fu); - fu = new MyFileUpload(); - fu.setName(paintableId + "_file"); - fu.getElement().setPropertyBoolean("disabled", !enabled); - panel.add(fu); - panel.add(submitButton); - if (immediate) { - fu.sinkEvents(Event.ONCHANGE); - } - } - - /** - * Called by JSNI (hooked via {@link #onloadstrategy}) - */ - private void onSubmitComplete() { - /* Needs to be run dereferred to avoid various browser issues. */ - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - if (submitted) { - if (client != null) { - if (t != null) { - t.cancel(); - } - VConsole.log("VUpload:Submit complete"); - client.sendPendingVariableChanges(); - } - - rebuildPanel(); - - submitted = false; - enableUpload(); - if (!isAttached()) { - /* - * Upload is complete when upload is already abandoned. - */ - cleanTargetFrame(); - } - } - } - }); - } - - protected void submit() { - if (fu.getFilename().length() == 0 || submitted || !enabled) { - VConsole.log("Submit cancelled (disabled, no file or already submitted)"); - return; - } - // flush possibly pending variable changes, so they will be handled - // before upload - client.sendPendingVariableChanges(); - - element.submit(); - submitted = true; - VConsole.log("Submitted form"); - - disableUpload(); - - /* - * Visit server a moment after upload has started to see possible - * changes from UploadStarted event. Will be cleared on complete. - */ - t = new Timer() { - @Override - public void run() { - VConsole.log("Visiting server to see if upload started event changed UI."); - client.updateVariable(paintableId, "pollForStart", - nextUploadId, true); - } - }; - t.schedule(800); - } - - @Override - protected void onAttach() { - super.onAttach(); - if (client != null) { - ensureTargetFrame(); - } - } - - protected void ensureTargetFrame() { - if (synthesizedFrame == null) { - // Attach a hidden IFrame to the form. This is the target iframe to - // which the form will be submitted. We have to create the iframe - // using innerHTML, because setting an iframe's 'name' property - // dynamically doesn't work on most browsers. - DivElement dummy = Document.get().createDivElement(); - dummy.setInnerHTML("<iframe src=\"javascript:''\" name='" - + getFrameName() - + "' style='position:absolute;width:0;height:0;border:0'>"); - synthesizedFrame = dummy.getFirstChildElement(); - Document.get().getBody().appendChild(synthesizedFrame); - element.setTarget(getFrameName()); - onloadstrategy.hookEvents(synthesizedFrame, this); - } - } - - private String getFrameName() { - return paintableId + "_TGT_FRAME"; - } - - @Override - protected void onDetach() { - super.onDetach(); - if (!submitted) { - cleanTargetFrame(); - } - } - - private void cleanTargetFrame() { - if (synthesizedFrame != null) { - Document.get().getBody().removeChild(synthesizedFrame); - onloadstrategy.unHookEvents(synthesizedFrame); - synthesizedFrame = null; - } - } -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/video/VVideo.java b/client/src/com/vaadin/terminal/gwt/client/ui/video/VVideo.java deleted file mode 100644 index 5f8d1ee574..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/video/VVideo.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.video; - -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.dom.client.VideoElement; -import com.google.gwt.user.client.Element; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.VMediaBase; - -public class VVideo extends VMediaBase { - - private static String CLASSNAME = "v-video"; - - private VideoElement video; - - public VVideo() { - video = Document.get().createVideoElement(); - setMediaElement(video); - setStyleName(CLASSNAME); - - updateDimensionsWhenMetadataLoaded(getElement()); - } - - /** - * Registers a listener that updates the dimensions of the widget when the - * video metadata has been loaded. - * - * @param el - */ - private native void updateDimensionsWhenMetadataLoaded(Element el) - /*-{ - var self = this; - el.addEventListener('loadedmetadata', $entry(function(e) { - self.@com.vaadin.terminal.gwt.client.ui.video.VVideo::updateElementDynamicSize(II)(el.videoWidth, el.videoHeight); - }), false); - - }-*/; - - /** - * Updates the dimensions of the widget. - * - * @param w - * @param h - */ - private void updateElementDynamicSize(int w, int h) { - video.getStyle().setWidth(w, Unit.PX); - video.getStyle().setHeight(h, Unit.PX); - Util.notifyParentOfSizeChange(this, true); - } - - public void setPoster(String poster) { - video.setPoster(poster); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/video/VideoConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/video/VideoConnector.java deleted file mode 100644 index 2b228d14ea..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/video/VideoConnector.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.video; - -import com.vaadin.shared.communication.URLReference; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.video.VideoState; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; -import com.vaadin.terminal.gwt.client.ui.MediaBaseConnector; -import com.vaadin.ui.Video; - -@Connect(Video.class) -public class VideoConnector extends MediaBaseConnector { - - @Override - public VideoState getState() { - return (VideoState) super.getState(); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - URLReference poster = getState().getPoster(); - if (poster != null) { - getWidget().setPoster(poster.getURL()); - } else { - getWidget().setPoster(null); - } - } - - @Override - public VVideo getWidget() { - return (VVideo) super.getWidget(); - } - - @Override - protected String getDefaultAltHtml() { - return "Your browser does not support the <code>video</code> element."; - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java b/client/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java deleted file mode 100644 index 1660eee246..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java +++ /dev/null @@ -1,932 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.terminal.gwt.client.ui.window; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.ScrollEvent; -import com.google.gwt.event.dom.client.ScrollHandler; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.HasWidgets; -import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.EventId; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.Console; -import com.vaadin.terminal.gwt.client.Focusable; -import com.vaadin.terminal.gwt.client.LayoutManager; -import com.vaadin.terminal.gwt.client.Util; -import com.vaadin.terminal.gwt.client.ui.FocusableScrollPanel; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner; -import com.vaadin.terminal.gwt.client.ui.VLazyExecutor; -import com.vaadin.terminal.gwt.client.ui.VOverlay; -import com.vaadin.terminal.gwt.client.ui.notification.VNotification; - -/** - * "Sub window" component. - * - * @author Vaadin Ltd - */ -public class VWindow extends VOverlay implements ShortcutActionHandlerOwner, - ScrollHandler, KeyDownHandler, FocusHandler, BlurHandler, Focusable { - - /** - * Minimum allowed height of a window. This refers to the content area, not - * the outer borders. - */ - private static final int MIN_CONTENT_AREA_HEIGHT = 100; - - /** - * Minimum allowed width of a window. This refers to the content area, not - * the outer borders. - */ - private static final int MIN_CONTENT_AREA_WIDTH = 150; - - private static ArrayList<VWindow> windowOrder = new ArrayList<VWindow>(); - - private static boolean orderingDefered; - - public static final String CLASSNAME = "v-window"; - - private static final int STACKING_OFFSET_PIXELS = 15; - - public static final int Z_INDEX = 10000; - - ComponentConnector layout; - - Element contents; - - Element header; - - Element footer; - - private Element resizeBox; - - final FocusableScrollPanel contentPanel = new FocusableScrollPanel(); - - private boolean dragging; - - private int startX; - - private int startY; - - private int origX; - - private int origY; - - private boolean resizing; - - private int origW; - - private int origH; - - Element closeBox; - - protected ApplicationConnection client; - - String id; - - ShortcutActionHandler shortcutHandler; - - /** Last known positionx read from UIDL or updated to application connection */ - private int uidlPositionX = -1; - - /** Last known positiony read from UIDL or updated to application connection */ - private int uidlPositionY = -1; - - boolean vaadinModality = false; - - boolean resizable = true; - - private boolean draggable = true; - - boolean resizeLazy = false; - - private Element modalityCurtain; - private Element draggingCurtain; - private Element resizingCurtain; - - private Element headerText; - - private boolean closable = true; - - // If centered (via UIDL), the window should stay in the centered -mode - // until a position is received from the server, or the user moves or - // resizes the window. - boolean centered = false; - - boolean immediate; - - private Element wrapper; - - boolean visibilityChangesDisabled; - - int bringToFrontSequence = -1; - - private VLazyExecutor delayedContentsSizeUpdater = new VLazyExecutor(200, - new ScheduledCommand() { - - @Override - public void execute() { - updateContentsSize(); - } - }); - - public VWindow() { - super(false, false, true); // no autohide, not modal, shadow - // Different style of shadow for windows - setShadowStyle("window"); - - constructDOM(); - contentPanel.addScrollHandler(this); - contentPanel.addKeyDownHandler(this); - contentPanel.addFocusHandler(this); - contentPanel.addBlurHandler(this); - } - - public void bringToFront() { - int curIndex = windowOrder.indexOf(this); - if (curIndex + 1 < windowOrder.size()) { - windowOrder.remove(this); - windowOrder.add(this); - for (; curIndex < windowOrder.size(); curIndex++) { - windowOrder.get(curIndex).setWindowOrder(curIndex); - } - } - } - - /** - * Returns true if this window is the topmost VWindow - * - * @return - */ - private boolean isActive() { - return equals(getTopmostWindow()); - } - - private static VWindow getTopmostWindow() { - return windowOrder.get(windowOrder.size() - 1); - } - - void setWindowOrderAndPosition() { - // This cannot be done in the constructor as the widgets are created in - // a different order than on they should appear on screen - if (windowOrder.contains(this)) { - // Already set - return; - } - final int order = windowOrder.size(); - setWindowOrder(order); - windowOrder.add(this); - setPopupPosition(order * STACKING_OFFSET_PIXELS, order - * STACKING_OFFSET_PIXELS); - - } - - private void setWindowOrder(int order) { - setZIndex(order + Z_INDEX); - } - - @Override - protected void setZIndex(int zIndex) { - super.setZIndex(zIndex); - if (vaadinModality) { - DOM.setStyleAttribute(getModalityCurtain(), "zIndex", "" + zIndex); - } - } - - protected Element getModalityCurtain() { - if (modalityCurtain == null) { - modalityCurtain = DOM.createDiv(); - modalityCurtain.setClassName(CLASSNAME + "-modalitycurtain"); - } - return modalityCurtain; - } - - protected void constructDOM() { - setStyleName(CLASSNAME); - - header = DOM.createDiv(); - DOM.setElementProperty(header, "className", CLASSNAME + "-outerheader"); - headerText = DOM.createDiv(); - DOM.setElementProperty(headerText, "className", CLASSNAME + "-header"); - contents = DOM.createDiv(); - DOM.setElementProperty(contents, "className", CLASSNAME + "-contents"); - footer = DOM.createDiv(); - DOM.setElementProperty(footer, "className", CLASSNAME + "-footer"); - resizeBox = DOM.createDiv(); - DOM.setElementProperty(resizeBox, "className", CLASSNAME + "-resizebox"); - closeBox = DOM.createDiv(); - DOM.setElementProperty(closeBox, "className", CLASSNAME + "-closebox"); - DOM.appendChild(footer, resizeBox); - - wrapper = DOM.createDiv(); - DOM.setElementProperty(wrapper, "className", CLASSNAME + "-wrap"); - - DOM.appendChild(wrapper, header); - DOM.appendChild(wrapper, closeBox); - DOM.appendChild(header, headerText); - DOM.appendChild(wrapper, contents); - DOM.appendChild(wrapper, footer); - DOM.appendChild(super.getContainerElement(), wrapper); - - sinkEvents(Event.MOUSEEVENTS | Event.TOUCHEVENTS | Event.ONCLICK - | Event.ONLOSECAPTURE); - - setWidget(contentPanel); - - } - - /** - * Calling this method will defer ordering algorithm, to order windows based - * on servers bringToFront and modality instructions. Non changed windows - * will be left intact. - */ - static void deferOrdering() { - if (!orderingDefered) { - orderingDefered = true; - Scheduler.get().scheduleFinally(new Command() { - - @Override - public void execute() { - doServerSideOrdering(); - VNotification.bringNotificationsToFront(); - } - }); - } - } - - private static void doServerSideOrdering() { - orderingDefered = false; - VWindow[] array = windowOrder.toArray(new VWindow[windowOrder.size()]); - Arrays.sort(array, new Comparator<VWindow>() { - - @Override - public int compare(VWindow o1, VWindow o2) { - /* - * Order by modality, then by bringtofront sequence. - */ - - if (o1.vaadinModality && !o2.vaadinModality) { - return 1; - } else if (!o1.vaadinModality && o2.vaadinModality) { - return -1; - } else if (o1.bringToFrontSequence > o2.bringToFrontSequence) { - return 1; - } else if (o1.bringToFrontSequence < o2.bringToFrontSequence) { - return -1; - } else { - return 0; - } - } - }); - for (int i = 0; i < array.length; i++) { - VWindow w = array[i]; - if (w.bringToFrontSequence != -1 || w.vaadinModality) { - w.bringToFront(); - w.bringToFrontSequence = -1; - } - } - } - - @Override - public void setVisible(boolean visible) { - /* - * Visibility with VWindow works differently than with other Paintables - * in Vaadin. Invisible VWindows are not attached to DOM at all. Flag is - * used to avoid visibility call from - * ApplicationConnection.updateComponent(); - */ - if (!visibilityChangesDisabled) { - super.setVisible(visible); - } - } - - void setDraggable(boolean draggable) { - if (this.draggable == draggable) { - return; - } - - this.draggable = draggable; - - setCursorProperties(); - } - - private void setCursorProperties() { - if (!draggable) { - header.getStyle().setProperty("cursor", "default"); - footer.getStyle().setProperty("cursor", "default"); - } else { - header.getStyle().setProperty("cursor", ""); - footer.getStyle().setProperty("cursor", ""); - } - } - - /** - * Sets the closable state of the window. Additionally hides/shows the close - * button according to the new state. - * - * @param closable - * true if the window can be closed by the user - */ - protected void setClosable(boolean closable) { - if (this.closable == closable) { - return; - } - - this.closable = closable; - if (closable) { - DOM.setStyleAttribute(closeBox, "display", ""); - } else { - DOM.setStyleAttribute(closeBox, "display", "none"); - } - - } - - /** - * Returns the closable state of the sub window. If the sub window is - * closable a decoration (typically an X) is shown to the user. By clicking - * on the X the user can close the window. - * - * @return true if the sub window is closable - */ - protected boolean isClosable() { - return closable; - } - - @Override - public void show() { - if (!windowOrder.contains(this)) { - // This is needed if the window is hidden and then shown again. - // Otherwise this VWindow is added to windowOrder in the - // constructor. - windowOrder.add(this); - } - - if (vaadinModality) { - showModalityCurtain(); - } - super.show(); - } - - @Override - public void hide() { - if (vaadinModality) { - hideModalityCurtain(); - } - super.hide(); - - // Remove window from windowOrder to avoid references being left - // hanging. - windowOrder.remove(this); - } - - void setVaadinModality(boolean modality) { - vaadinModality = modality; - if (vaadinModality) { - if (isAttached()) { - showModalityCurtain(); - } - deferOrdering(); - } else { - if (modalityCurtain != null) { - if (isAttached()) { - hideModalityCurtain(); - } - modalityCurtain = null; - } - } - } - - private void showModalityCurtain() { - DOM.setStyleAttribute(getModalityCurtain(), "zIndex", - "" + (windowOrder.indexOf(this) + Z_INDEX)); - if (isShowing()) { - RootPanel.getBodyElement().insertBefore(getModalityCurtain(), - getElement()); - } else { - DOM.appendChild(RootPanel.getBodyElement(), getModalityCurtain()); - } - } - - private void hideModalityCurtain() { - DOM.removeChild(RootPanel.getBodyElement(), modalityCurtain); - } - - /* - * Shows an empty div on top of all other content; used when moving, so that - * iframes (etc) do not steal event. - */ - private void showDraggingCurtain() { - DOM.appendChild(RootPanel.getBodyElement(), getDraggingCurtain()); - } - - private void hideDraggingCurtain() { - if (draggingCurtain != null) { - DOM.removeChild(RootPanel.getBodyElement(), draggingCurtain); - } - } - - /* - * Shows an empty div on top of all other content; used when resizing, so - * that iframes (etc) do not steal event. - */ - private void showResizingCurtain() { - DOM.appendChild(RootPanel.getBodyElement(), getResizingCurtain()); - } - - private void hideResizingCurtain() { - if (resizingCurtain != null) { - DOM.removeChild(RootPanel.getBodyElement(), resizingCurtain); - } - } - - private Element getDraggingCurtain() { - if (draggingCurtain == null) { - draggingCurtain = createCurtain(); - draggingCurtain.setClassName(CLASSNAME + "-draggingCurtain"); - } - - return draggingCurtain; - } - - private Element getResizingCurtain() { - if (resizingCurtain == null) { - resizingCurtain = createCurtain(); - resizingCurtain.setClassName(CLASSNAME + "-resizingCurtain"); - } - - return resizingCurtain; - } - - private Element createCurtain() { - Element curtain = DOM.createDiv(); - - DOM.setStyleAttribute(curtain, "position", "absolute"); - DOM.setStyleAttribute(curtain, "top", "0px"); - DOM.setStyleAttribute(curtain, "left", "0px"); - DOM.setStyleAttribute(curtain, "width", "100%"); - DOM.setStyleAttribute(curtain, "height", "100%"); - DOM.setStyleAttribute(curtain, "zIndex", "" + VOverlay.Z_INDEX); - - return curtain; - } - - void setResizable(boolean resizability) { - resizable = resizability; - if (resizability) { - DOM.setElementProperty(footer, "className", CLASSNAME + "-footer"); - DOM.setElementProperty(resizeBox, "className", CLASSNAME - + "-resizebox"); - } else { - DOM.setElementProperty(footer, "className", CLASSNAME + "-footer " - + CLASSNAME + "-footer-noresize"); - DOM.setElementProperty(resizeBox, "className", CLASSNAME - + "-resizebox " + CLASSNAME + "-resizebox-disabled"); - } - } - - @Override - public void setPopupPosition(int left, int top) { - if (top < 0) { - // ensure window is not moved out of browser window from top of the - // screen - top = 0; - } - super.setPopupPosition(left, top); - if (left != uidlPositionX && client != null) { - client.updateVariable(id, "positionx", left, false); - uidlPositionX = left; - } - if (top != uidlPositionY && client != null) { - client.updateVariable(id, "positiony", top, false); - uidlPositionY = top; - } - } - - public void setCaption(String c) { - setCaption(c, null); - } - - public void setCaption(String c, String icon) { - String html = Util.escapeHTML(c); - if (icon != null) { - icon = client.translateVaadinUri(icon); - html = "<img src=\"" + Util.escapeAttribute(icon) - + "\" class=\"v-icon\" />" + html; - } - DOM.setInnerHTML(headerText, html); - } - - @Override - protected Element getContainerElement() { - // in GWT 1.5 this method is used in PopupPanel constructor - if (contents == null) { - return super.getContainerElement(); - } - return contents; - } - - @Override - public void onBrowserEvent(final Event event) { - boolean bubble = true; - - final int type = event.getTypeInt(); - - final Element target = DOM.eventGetTarget(event); - - if (resizing || resizeBox == target) { - onResizeEvent(event); - bubble = false; - } else if (isClosable() && target == closeBox) { - if (type == Event.ONCLICK) { - onCloseClick(); - } - bubble = false; - } else if (dragging || !contents.isOrHasChild(target)) { - onDragEvent(event); - bubble = false; - } else if (type == Event.ONCLICK) { - // clicked inside window, ensure to be on top - if (!isActive()) { - bringToFront(); - } - } - - /* - * If clicking on other than the content, move focus to the window. - * After that this windows e.g. gets all keyboard shortcuts. - */ - if (type == Event.ONMOUSEDOWN - && !contentPanel.getElement().isOrHasChild(target) - && target != closeBox) { - contentPanel.focus(); - } - - if (!bubble) { - event.stopPropagation(); - } else { - // Super.onBrowserEvent takes care of Handlers added by the - // ClickEventHandler - super.onBrowserEvent(event); - } - } - - private void onCloseClick() { - client.updateVariable(id, "close", true, true); - } - - private void onResizeEvent(Event event) { - if (resizable && Util.isTouchEventOrLeftMouseButton(event)) { - switch (event.getTypeInt()) { - case Event.ONMOUSEDOWN: - case Event.ONTOUCHSTART: - if (!isActive()) { - bringToFront(); - } - showResizingCurtain(); - if (BrowserInfo.get().isIE()) { - DOM.setStyleAttribute(resizeBox, "visibility", "hidden"); - } - resizing = true; - startX = Util.getTouchOrMouseClientX(event); - startY = Util.getTouchOrMouseClientY(event); - origW = getElement().getOffsetWidth(); - origH = getElement().getOffsetHeight(); - DOM.setCapture(getElement()); - event.preventDefault(); - break; - case Event.ONMOUSEUP: - case Event.ONTOUCHEND: - setSize(event, true); - case Event.ONTOUCHCANCEL: - DOM.releaseCapture(getElement()); - case Event.ONLOSECAPTURE: - hideResizingCurtain(); - if (BrowserInfo.get().isIE()) { - DOM.setStyleAttribute(resizeBox, "visibility", ""); - } - resizing = false; - break; - case Event.ONMOUSEMOVE: - case Event.ONTOUCHMOVE: - if (resizing) { - centered = false; - setSize(event, false); - event.preventDefault(); - } - break; - default: - event.preventDefault(); - break; - } - } - } - - /** - * TODO check if we need to support this with touch based devices. - * - * Checks if the cursor was inside the browser content area when the event - * happened. - * - * @param event - * The event to be checked - * @return true, if the cursor is inside the browser content area - * - * false, otherwise - */ - private boolean cursorInsideBrowserContentArea(Event event) { - if (event.getClientX() < 0 || event.getClientY() < 0) { - // Outside to the left or above - return false; - } - - if (event.getClientX() > Window.getClientWidth() - || event.getClientY() > Window.getClientHeight()) { - // Outside to the right or below - return false; - } - - return true; - } - - private void setSize(Event event, boolean updateVariables) { - if (!cursorInsideBrowserContentArea(event)) { - // Only drag while cursor is inside the browser client area - return; - } - - int w = Util.getTouchOrMouseClientX(event) - startX + origW; - int minWidth = getMinWidth(); - if (w < minWidth) { - w = minWidth; - } - - int h = Util.getTouchOrMouseClientY(event) - startY + origH; - int minHeight = getMinHeight(); - if (h < minHeight) { - h = minHeight; - } - - setWidth(w + "px"); - setHeight(h + "px"); - - if (updateVariables) { - // sending width back always as pixels, no need for unit - client.updateVariable(id, "width", w, false); - client.updateVariable(id, "height", h, immediate); - } - - if (updateVariables || !resizeLazy) { - // Resize has finished or is not lazy - updateContentsSize(); - } else { - // Lazy resize - wait for a while before re-rendering contents - delayedContentsSizeUpdater.trigger(); - } - } - - private void updateContentsSize() { - // Update child widget dimensions - if (client != null) { - client.handleComponentRelativeSize(layout.getWidget()); - client.runDescendentsLayout((HasWidgets) layout.getWidget()); - } - - LayoutManager layoutManager = LayoutManager.get(client); - layoutManager.setNeedsMeasure(ConnectorMap.get(client).getConnector( - this)); - layoutManager.layoutNow(); - } - - @Override - public void setWidth(String width) { - // Override PopupPanel which sets the width to the contents - getElement().getStyle().setProperty("width", width); - // Update v-has-width in case undefined window is resized - setStyleName("v-has-width", width != null && width.length() > 0); - } - - @Override - public void setHeight(String height) { - // Override PopupPanel which sets the height to the contents - getElement().getStyle().setProperty("height", height); - // Update v-has-height in case undefined window is resized - setStyleName("v-has-height", height != null && height.length() > 0); - } - - private void onDragEvent(Event event) { - if (!Util.isTouchEventOrLeftMouseButton(event)) { - return; - } - - switch (DOM.eventGetType(event)) { - case Event.ONTOUCHSTART: - if (event.getTouches().length() > 1) { - return; - } - case Event.ONMOUSEDOWN: - if (!isActive()) { - bringToFront(); - } - beginMovingWindow(event); - break; - case Event.ONMOUSEUP: - case Event.ONTOUCHEND: - case Event.ONTOUCHCANCEL: - case Event.ONLOSECAPTURE: - stopMovingWindow(); - break; - case Event.ONMOUSEMOVE: - case Event.ONTOUCHMOVE: - moveWindow(event); - break; - default: - break; - } - } - - private void moveWindow(Event event) { - if (dragging) { - centered = false; - if (cursorInsideBrowserContentArea(event)) { - // Only drag while cursor is inside the browser client area - final int x = Util.getTouchOrMouseClientX(event) - startX - + origX; - final int y = Util.getTouchOrMouseClientY(event) - startY - + origY; - setPopupPosition(x, y); - } - DOM.eventPreventDefault(event); - } - } - - private void beginMovingWindow(Event event) { - if (draggable) { - showDraggingCurtain(); - dragging = true; - startX = Util.getTouchOrMouseClientX(event); - startY = Util.getTouchOrMouseClientY(event); - origX = DOM.getAbsoluteLeft(getElement()); - origY = DOM.getAbsoluteTop(getElement()); - DOM.setCapture(getElement()); - DOM.eventPreventDefault(event); - } - } - - private void stopMovingWindow() { - dragging = false; - hideDraggingCurtain(); - DOM.releaseCapture(getElement()); - } - - @Override - public boolean onEventPreview(Event event) { - if (dragging) { - onDragEvent(event); - return false; - } else if (resizing) { - onResizeEvent(event); - return false; - } - - // TODO This is probably completely unnecessary as the modality curtain - // prevents events from reaching other windows and any security check - // must be done on the server side and not here. - // The code here is also run many times as each VWindow has an event - // preview but we cannot check only the current VWindow here (e.g. - // if(isTopMost) {...}) because PopupPanel will cause all events that - // are not cancelled here and target this window to be consume():d - // meaning the event won't be sent to the rest of the preview handlers. - - if (getTopmostWindow().vaadinModality) { - // Topmost window is modal. Cancel the event if it targets something - // outside that window (except debug console...) - if (DOM.getCaptureElement() != null) { - // Allow events when capture is set - return true; - } - - final Element target = event.getEventTarget().cast(); - if (!DOM.isOrHasChild(getTopmostWindow().getElement(), target)) { - // not within the modal window, but let's see if it's in the - // debug window - Widget w = Util.findWidget(target, null); - while (w != null) { - if (w instanceof Console) { - return true; // allow debug-window clicks - } else if (ConnectorMap.get(client).isConnector(w)) { - return false; - } - w = w.getParent(); - } - return false; - } - } - return true; - } - - @Override - public void addStyleDependentName(String styleSuffix) { - // VWindow's getStyleElement() does not return the same element as - // getElement(), so we need to override this. - setStyleName(getElement(), getStylePrimaryName() + "-" + styleSuffix, - true); - } - - @Override - public ShortcutActionHandler getShortcutActionHandler() { - return shortcutHandler; - } - - @Override - public void onScroll(ScrollEvent event) { - client.updateVariable(id, "scrollTop", - contentPanel.getScrollPosition(), false); - client.updateVariable(id, "scrollLeft", - contentPanel.getHorizontalScrollPosition(), false); - - } - - @Override - public void onKeyDown(KeyDownEvent event) { - if (shortcutHandler != null) { - shortcutHandler - .handleKeyboardEvent(Event.as(event.getNativeEvent())); - return; - } - } - - @Override - public void onBlur(BlurEvent event) { - if (client.hasEventListeners(this, EventId.BLUR)) { - client.updateVariable(id, EventId.BLUR, "", true); - } - } - - @Override - public void onFocus(FocusEvent event) { - if (client.hasEventListeners(this, EventId.FOCUS)) { - client.updateVariable(id, EventId.FOCUS, "", true); - } - } - - @Override - public void focus() { - contentPanel.focus(); - } - - public int getMinHeight() { - return MIN_CONTENT_AREA_HEIGHT + getDecorationHeight(); - } - - private int getDecorationHeight() { - LayoutManager lm = layout.getLayoutManager(); - int headerHeight = lm.getOuterHeight(header); - int footerHeight = lm.getOuterHeight(footer); - return headerHeight + footerHeight; - } - - public int getMinWidth() { - return MIN_CONTENT_AREA_WIDTH + getDecorationWidth(); - } - - private int getDecorationWidth() { - LayoutManager layoutManager = layout.getLayoutManager(); - return layoutManager.getOuterWidth(getElement()) - - contentPanel.getElement().getOffsetWidth(); - } - -} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java deleted file mode 100644 index 3ee266b944..0000000000 --- a/client/src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.client.ui.window; - -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Position; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.window.WindowServerRpc; -import com.vaadin.shared.ui.window.WindowState; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; -import com.vaadin.terminal.gwt.client.ComponentConnector; -import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; -import com.vaadin.terminal.gwt.client.LayoutManager; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; -import com.vaadin.terminal.gwt.client.communication.RpcProxy; -import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector; -import com.vaadin.terminal.gwt.client.ui.ClickEventHandler; -import com.vaadin.terminal.gwt.client.ui.PostLayoutListener; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler; -import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutActionListener; -import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout; -import com.vaadin.terminal.gwt.client.ui.layout.MayScrollChildren; - -@Connect(value = com.vaadin.ui.Window.class) -public class WindowConnector extends AbstractComponentContainerConnector -implements Paintable, BeforeShortcutActionListener, -SimpleManagedLayout, PostLayoutListener, MayScrollChildren { - - private ClickEventHandler clickEventHandler = new ClickEventHandler(this) { - @Override - protected void fireClick(NativeEvent event, - MouseEventDetails mouseDetails) { - rpc.click(mouseDetails); - } - }; - - private WindowServerRpc rpc; - - boolean minWidthChecked = false; - - @Override - public boolean delegateCaptionHandling() { - return false; - }; - - @Override - protected void init() { - super.init(); - rpc = RpcProxy.create(WindowServerRpc.class, this); - - getLayoutManager().registerDependency(this, - getWidget().contentPanel.getElement()); - getLayoutManager().registerDependency(this, getWidget().header); - getLayoutManager().registerDependency(this, getWidget().footer); - } - - @Override - public void onUnregister() { - LayoutManager lm = getLayoutManager(); - VWindow window = getWidget(); - lm.unregisterDependency(this, window.contentPanel.getElement()); - lm.unregisterDependency(this, window.header); - lm.unregisterDependency(this, window.footer); - } - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - getWidget().id = getConnectorId(); - getWidget().client = client; - - // Workaround needed for Testing Tools (GWT generates window DOM - // slightly different in different browsers). - DOM.setElementProperty(getWidget().closeBox, "id", getConnectorId() - + "_window_close"); - - if (isRealUpdate(uidl)) { - if (getState().isModal() != getWidget().vaadinModality) { - getWidget().setVaadinModality(!getWidget().vaadinModality); - } - if (!getWidget().isAttached()) { - getWidget().setVisible(false); // hide until - // possible centering - getWidget().show(); - } - if (getState().isResizable() != getWidget().resizable) { - getWidget().setResizable(getState().isResizable()); - } - getWidget().resizeLazy = getState().isResizeLazy(); - - getWidget().setDraggable(getState().isDraggable()); - - // Caption must be set before required header size is measured. If - // the caption attribute is missing the caption should be cleared. - String iconURL = null; - if (getState().getIcon() != null) { - iconURL = getState().getIcon().getURL(); - } - getWidget().setCaption(getState().getCaption(), iconURL); - } - - getWidget().visibilityChangesDisabled = true; - if (!isRealUpdate(uidl)) { - return; - } - getWidget().visibilityChangesDisabled = false; - - clickEventHandler.handleEventHandlerRegistration(); - - getWidget().immediate = getState().isImmediate(); - - getWidget().setClosable(!isReadOnly()); - - // Initialize the position form UIDL - int positionx = getState().getPositionX(); - int positiony = getState().getPositionY(); - if (positionx >= 0 || positiony >= 0) { - if (positionx < 0) { - positionx = 0; - } - if (positiony < 0) { - positiony = 0; - } - getWidget().setPopupPosition(positionx, positiony); - } - - int childIndex = 0; - - // we may have actions - for (int i = 0; i < uidl.getChildCount(); i++) { - UIDL childUidl = uidl.getChildUIDL(i); - if (childUidl.getTag().equals("actions")) { - if (getWidget().shortcutHandler == null) { - getWidget().shortcutHandler = new ShortcutActionHandler( - getConnectorId(), client); - } - getWidget().shortcutHandler.updateActionMap(childUidl); - } - - } - - // setting scrollposition must happen after children is rendered - getWidget().contentPanel.setScrollPosition(getState().getScrollTop()); - getWidget().contentPanel.setHorizontalScrollPosition(getState() - .getScrollLeft()); - - // Center this window on screen if requested - // This had to be here because we might not know the content size before - // everything is painted into the window - - // centered is this is unset on move/resize - getWidget().centered = getState().isCentered(); - getWidget().setVisible(true); - - // ensure window is not larger than browser window - if (getWidget().getOffsetWidth() > Window.getClientWidth()) { - getWidget().setWidth(Window.getClientWidth() + "px"); - } - if (getWidget().getOffsetHeight() > Window.getClientHeight()) { - getWidget().setHeight(Window.getClientHeight() + "px"); - } - - if (uidl.hasAttribute("bringToFront")) { - /* - * Focus as a side-effect. Will be overridden by - * ApplicationConnection if another component was focused by the - * server side. - */ - getWidget().contentPanel.focus(); - getWidget().bringToFrontSequence = uidl - .getIntAttribute("bringToFront"); - VWindow.deferOrdering(); - } - } - - @Override - public void updateCaption(ComponentConnector component) { - // NOP, window has own caption, layout caption not rendered - } - - @Override - public void onBeforeShortcutAction(Event e) { - // NOP, nothing to update just avoid workaround ( causes excess - // blur/focus ) - } - - @Override - public VWindow getWidget() { - return (VWindow) super.getWidget(); - } - - @Override - public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { - super.onConnectorHierarchyChange(event); - - // We always have 1 child, unless the child is hidden - Widget newChildWidget = null; - ComponentConnector newChild = null; - if (getChildComponents().size() == 1) { - newChild = getChildComponents().get(0); - newChildWidget = newChild.getWidget(); - } - - getWidget().layout = newChild; - getWidget().contentPanel.setWidget(newChildWidget); - } - - @Override - public void layout() { - LayoutManager lm = getLayoutManager(); - VWindow window = getWidget(); - ComponentConnector layout = window.layout; - Element contentElement = window.contentPanel.getElement(); - - if (!minWidthChecked) { - boolean needsMinWidth = !isUndefinedWidth() - || layout.isRelativeWidth(); - int minWidth = window.getMinWidth(); - if (needsMinWidth && lm.getInnerWidth(contentElement) < minWidth) { - minWidthChecked = true; - // Use minimum width if less than a certain size - window.setWidth(minWidth + "px"); - } - minWidthChecked = true; - } - - boolean needsMinHeight = !isUndefinedHeight() - || layout.isRelativeHeight(); - int minHeight = window.getMinHeight(); - if (needsMinHeight && lm.getInnerHeight(contentElement) < minHeight) { - // Use minimum height if less than a certain size - window.setHeight(minHeight + "px"); - } - - Style contentStyle = window.contents.getStyle(); - - int headerHeight = lm.getOuterHeight(window.header); - contentStyle.setPaddingTop(headerHeight, Unit.PX); - contentStyle.setMarginTop(-headerHeight, Unit.PX); - - int footerHeight = lm.getOuterHeight(window.footer); - contentStyle.setPaddingBottom(footerHeight, Unit.PX); - contentStyle.setMarginBottom(-footerHeight, Unit.PX); - - /* - * Must set absolute position if the child has relative height and - * there's a chance of horizontal scrolling as some browsers will - * otherwise not take the scrollbar into account when calculating the - * height. - */ - Element layoutElement = layout.getWidget().getElement(); - Style childStyle = layoutElement.getStyle(); - if (layout.isRelativeHeight() && !BrowserInfo.get().isIE9()) { - childStyle.setPosition(Position.ABSOLUTE); - - Style wrapperStyle = contentElement.getStyle(); - if (window.getElement().getStyle().getWidth().length() == 0 - && !layout.isRelativeWidth()) { - /* - * Need to lock width to make undefined width work even with - * absolute positioning - */ - int contentWidth = lm.getOuterWidth(layoutElement); - wrapperStyle.setWidth(contentWidth, Unit.PX); - } else { - wrapperStyle.clearWidth(); - } - } else { - childStyle.clearPosition(); - } - } - - @Override - public void postLayout() { - minWidthChecked = false; - VWindow window = getWidget(); - if (window.centered) { - window.center(); - } - window.positionOrSizeUpdated(); - } - - @Override - public WindowState getState() { - return (WindowState) super.getState(); - } - - /** - * Gives the WindowConnector an order number. As a side effect, moves the - * window according to its order number so the windows are stacked. This - * method should be called for each window in the order they should appear. - */ - public void setWindowOrderAndPosition() { - getWidget().setWindowOrderAndPosition(); - } -} diff --git a/client/src/com/vaadin/terminal/gwt/public/ie6pngfix/blank.gif b/client/src/com/vaadin/terminal/gwt/public/ie6pngfix/blank.gif Binary files differdeleted file mode 100644 index 3776af0784..0000000000 --- a/client/src/com/vaadin/terminal/gwt/public/ie6pngfix/blank.gif +++ /dev/null |