summaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/com')
-rw-r--r--src/com/vaadin/Application.java14
-rw-r--r--src/com/vaadin/annotations/LoadScripts.java8
-rw-r--r--src/com/vaadin/data/util/MethodProperty.java9
-rw-r--r--src/com/vaadin/data/util/MethodPropertyDescriptor.java12
-rw-r--r--src/com/vaadin/data/util/sqlcontainer/SQLContainer.java129
-rw-r--r--src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPool.java5
-rw-r--r--src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java29
-rw-r--r--src/com/vaadin/event/ListenerMethod.java16
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/AcceptAll.java2
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/And.java1
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/ClientCriterion.java29
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/ContainsDataFlavor.java2
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/Not.java2
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/Or.java2
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/ServerSideCriterion.java2
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/SourceIs.java14
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/SourceIsTarget.java2
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/TargetDetailIs.java2
-rw-r--r--src/com/vaadin/navigator/Navigator.java25
-rw-r--r--src/com/vaadin/terminal/AbstractClientConnector.java61
-rw-r--r--src/com/vaadin/terminal/AbstractExtension.java57
-rw-r--r--src/com/vaadin/terminal/AbstractJavaScriptExtension.java158
-rw-r--r--src/com/vaadin/terminal/AbstractJavascriptExtension.java20
-rw-r--r--src/com/vaadin/terminal/ClassResource.java8
-rw-r--r--src/com/vaadin/terminal/Extension.java18
-rw-r--r--src/com/vaadin/terminal/JavaScriptCallbackHelper.java115
-rw-r--r--src/com/vaadin/terminal/JavascriptRpcHelper.java61
-rw-r--r--src/com/vaadin/terminal/Page.java630
-rw-r--r--src/com/vaadin/terminal/UserError.java10
-rw-r--r--src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java25
-rw-r--r--src/com/vaadin/terminal/gwt/client/ApplicationConnection.java38
-rw-r--r--src/com/vaadin/terminal/gwt/client/BrowserInfo.java20
-rw-r--r--src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java372
-rw-r--r--src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java32
-rw-r--r--src/com/vaadin/terminal/gwt/client/JavaScriptExtensionState.java36
-rw-r--r--src/com/vaadin/terminal/gwt/client/JavascriptConnectorHelper.java205
-rw-r--r--src/com/vaadin/terminal/gwt/client/JavascriptExtension.java33
-rw-r--r--src/com/vaadin/terminal/gwt/client/Util.java16
-rw-r--r--src/com/vaadin/terminal/gwt/client/WidgetSet.java6
-rw-r--r--src/com/vaadin/terminal/gwt/client/communication/HasJavaScriptConnectorHelper.java11
-rw-r--r--src/com/vaadin/terminal/gwt/client/communication/HasJavascriptConnectorHelper.java11
-rw-r--r--src/com/vaadin/terminal/gwt/client/communication/RpcManager.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/extensions/AbstractExtensionConnector.java27
-rw-r--r--src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/ExecuteJavaScriptRpc.java11
-rw-r--r--src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerConnector.java119
-rw-r--r--src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerState.java (renamed from src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavascriptManagerState.java)2
-rw-r--r--src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavascriptManagerConnector.java78
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/AbstractClickEventHandler.java104
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java15
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java5
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java42
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentState.java37
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/JavaScriptWidget.java (renamed from src/com/vaadin/terminal/gwt/client/ui/JavascriptWidget.java)6
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/JavascriptComponentConnector.java60
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java111
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java19
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/button/VButton.java42
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java37
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/AcceptCriterion.java33
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java21
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptAll.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VAnd.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VContainsDataFlavor.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VDragSourceIs.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VIsOverId.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VItemIdIs.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VLazyInitItemIdentifiers.java14
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VNot.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VOr.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VServerAccept.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VSourceIsTarget.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VTargetDetailIs.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VTargetInSubtree.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java3
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java10
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/form/VForm.java5
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java7
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java19
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java33
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/root/PageClientRpc.java13
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java15
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java223
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java17
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java7
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelState.java36
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java207
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java242
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java15
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java40
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java44
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java4
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java35
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java74
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java72
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java9
-rw-r--r--src/com/vaadin/terminal/gwt/server/ClientConnector.java60
-rw-r--r--src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java13
-rw-r--r--src/com/vaadin/terminal/gwt/server/DragAndDropService.java23
-rw-r--r--src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java36
-rw-r--r--src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java30
-rw-r--r--src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java17
-rw-r--r--src/com/vaadin/terminal/gwt/server/WebBrowser.java50
-rw-r--r--src/com/vaadin/terminal/gwt/widgetsetutils/AcceptCriteriaFactoryGenerator.java38
-rw-r--r--src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java252
-rw-r--r--src/com/vaadin/tools/WidgetsetCompiler.java11
-rw-r--r--src/com/vaadin/ui/AbstractJavaScriptComponent.java161
-rw-r--r--src/com/vaadin/ui/AbstractJavascriptComponent.java19
-rw-r--r--src/com/vaadin/ui/AbstractSelect.java5
-rw-r--r--src/com/vaadin/ui/AbstractSplitPanel.java128
-rw-r--r--src/com/vaadin/ui/Button.java2
-rw-r--r--src/com/vaadin/ui/HelloWorldExtension.java2
-rw-r--r--src/com/vaadin/ui/JavaScript.java146
-rw-r--r--src/com/vaadin/ui/JavaScriptCallback.java41
-rw-r--r--src/com/vaadin/ui/JavascriptCallback.java14
-rw-r--r--src/com/vaadin/ui/JavascriptManager.java58
-rw-r--r--src/com/vaadin/ui/Link.java7
-rw-r--r--src/com/vaadin/ui/Notification.java115
-rw-r--r--src/com/vaadin/ui/Root.java1065
-rw-r--r--src/com/vaadin/ui/TabSheet.java88
-rw-r--r--src/com/vaadin/ui/Table.java164
-rw-r--r--src/com/vaadin/ui/Tree.java5
-rw-r--r--src/com/vaadin/ui/TreeTable.java12
-rw-r--r--src/com/vaadin/ui/UniqueSerializable.java30
-rw-r--r--src/com/vaadin/ui/Window.java39
-rw-r--r--src/com/vaadin/ui/themes/ChameleonTheme.java2
127 files changed, 4459 insertions, 2354 deletions
diff --git a/src/com/vaadin/Application.java b/src/com/vaadin/Application.java
index 4da1d52c00..dbf71408a9 100644
--- a/src/com/vaadin/Application.java
+++ b/src/com/vaadin/Application.java
@@ -194,6 +194,7 @@ public class Application implements Terminal.ErrorListener, Serializable {
* @see #getWindow(String)
* @see Application#getRoot(WrappedRequest)
*/
+
@Override
public Root.LegacyWindow getRoot(WrappedRequest request) {
String pathInfo = request.getRequestPathInfo();
@@ -246,6 +247,7 @@ public class Application implements Terminal.ErrorListener, Serializable {
* <p>
* {@inheritDoc}
*/
+
@Override
public String getThemeForRoot(Root root) {
return theme;
@@ -1066,12 +1068,14 @@ public class Application implements Terminal.ErrorListener, Serializable {
* the change event.
* @see com.vaadin.terminal.Terminal.ErrorListener#terminalError(com.vaadin.terminal.Terminal.ErrorEvent)
*/
+
public void terminalError(Terminal.ErrorEvent event) {
final Throwable t = event.getThrowable();
if (t instanceof SocketException) {
// Most likely client browser closed socket
- logger.info("SocketException in CommunicationManager."
- + " Most likely client (browser) closed socket.");
+ getLogger().info(
+ "SocketException in CommunicationManager."
+ + " Most likely client (browser) closed socket.");
return;
}
@@ -1090,7 +1094,7 @@ public class Application implements Terminal.ErrorListener, Serializable {
}
// also print the error on console
- logger.log(Level.SEVERE, "Terminal error:", t);
+ getLogger().log(Level.SEVERE, "Terminal error:", t);
}
/**
@@ -2416,4 +2420,8 @@ public class Application implements Terminal.ErrorListener, Serializable {
}
}
+
+ private static final Logger getLogger() {
+ return Logger.getLogger(Application.class.getName());
+ }
}
diff --git a/src/com/vaadin/annotations/LoadScripts.java b/src/com/vaadin/annotations/LoadScripts.java
index f2b72407f7..84ac2d2fb7 100644
--- a/src/com/vaadin/annotations/LoadScripts.java
+++ b/src/com/vaadin/annotations/LoadScripts.java
@@ -8,8 +8,16 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+/**
+ * Temporary hack used for ensuring external javascript libraries are included.
+ * To add a javascript, add this annotation to your Root class.
+ *
+ * @deprecated Will be removed in favor of a more robust solution before version
+ * 7.0.0
+ */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
+@Deprecated
public @interface LoadScripts {
public String[] value();
diff --git a/src/com/vaadin/data/util/MethodProperty.java b/src/com/vaadin/data/util/MethodProperty.java
index 4fc5531320..7df45e04ab 100644
--- a/src/com/vaadin/data/util/MethodProperty.java
+++ b/src/com/vaadin/data/util/MethodProperty.java
@@ -48,8 +48,6 @@ import com.vaadin.util.SerializerHelper;
@SuppressWarnings("serial")
public class MethodProperty<T> extends AbstractProperty<T> {
- private static final Logger logger = Logger.getLogger(MethodProperty.class
- .getName());
/**
* The object that includes the property the MethodProperty is bound to.
*/
@@ -130,9 +128,9 @@ public class MethodProperty<T> extends AbstractProperty<T> {
getMethod = null;
}
} catch (SecurityException e) {
- logger.log(Level.SEVERE, "Internal deserialization error", e);
+ getLogger().log(Level.SEVERE, "Internal deserialization error", e);
} catch (NoSuchMethodException e) {
- logger.log(Level.SEVERE, "Internal deserialization error", e);
+ getLogger().log(Level.SEVERE, "Internal deserialization error", e);
}
};
@@ -777,4 +775,7 @@ public class MethodProperty<T> extends AbstractProperty<T> {
super.fireValueChange();
}
+ private static final Logger getLogger() {
+ return Logger.getLogger(MethodProperty.class.getName());
+ }
}
diff --git a/src/com/vaadin/data/util/MethodPropertyDescriptor.java b/src/com/vaadin/data/util/MethodPropertyDescriptor.java
index 10faa7a0f3..5fdb982b9e 100644
--- a/src/com/vaadin/data/util/MethodPropertyDescriptor.java
+++ b/src/com/vaadin/data/util/MethodPropertyDescriptor.java
@@ -23,9 +23,6 @@ import com.vaadin.util.SerializerHelper;
public class MethodPropertyDescriptor<BT> implements
VaadinPropertyDescriptor<BT> {
- private static final Logger logger = Logger
- .getLogger(MethodPropertyDescriptor.class.getName());
-
private final String name;
private Class<?> propertyType;
private transient Method readMethod;
@@ -109,9 +106,9 @@ public class MethodPropertyDescriptor<BT> implements
readMethod = null;
}
} catch (SecurityException e) {
- logger.log(Level.SEVERE, "Internal deserialization error", e);
+ getLogger().log(Level.SEVERE, "Internal deserialization error", e);
} catch (NoSuchMethodException e) {
- logger.log(Level.SEVERE, "Internal deserialization error", e);
+ getLogger().log(Level.SEVERE, "Internal deserialization error", e);
}
};
@@ -128,4 +125,7 @@ public class MethodPropertyDescriptor<BT> implements
writeMethod);
}
-}
+ private static final Logger getLogger() {
+ return Logger.getLogger(MethodPropertyDescriptor.class.getName());
+ }
+} \ No newline at end of file
diff --git a/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java b/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java
index 3bf33defd5..e9b5b4fea3 100644
--- a/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java
+++ b/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java
@@ -36,9 +36,6 @@ import com.vaadin.data.util.sqlcontainer.query.generator.OracleGenerator;
public class SQLContainer implements Container, Container.Filterable,
Container.Indexed, Container.Sortable, Container.ItemSetChangeNotifier {
- private static final Logger logger = Logger.getLogger(SQLContainer.class
- .getName());
-
/** Query delegate */
private QueryDelegate delegate;
/** Auto commit mode, default = false */
@@ -132,6 +129,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* {@inheritDoc}
*/
+
public Object addItem() throws UnsupportedOperationException {
Object emptyKey[] = new Object[delegate.getPrimaryKeyColumns().size()];
RowId itemId = new TemporaryRowId(emptyKey);
@@ -162,15 +160,15 @@ public class SQLContainer implements Container, Container.Filterable,
if (notificationsEnabled) {
CacheFlushNotifier.notifyOfCacheFlush(this);
}
- logger.log(Level.FINER, "Row added to DB...");
+ getLogger().log(Level.FINER, "Row added to DB...");
return itemId;
} catch (SQLException e) {
- logger.log(Level.WARNING,
+ getLogger().log(Level.WARNING,
"Failed to add row to DB. Rolling back.", e);
try {
delegate.rollback();
} catch (SQLException ee) {
- logger.log(Level.SEVERE,
+ getLogger().log(Level.SEVERE,
"Failed to roll back row addition", e);
}
return null;
@@ -187,6 +185,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#containsId(java.lang.Object)
*/
+
public boolean containsId(Object itemId) {
if (itemId == null) {
return false;
@@ -215,7 +214,7 @@ public class SQLContainer implements Container, Container.Filterable,
return delegate.containsRowWithKey(((RowId) itemId).getId());
} catch (Exception e) {
/* Query failed, just return false. */
- logger.log(Level.WARNING, "containsId query failed", e);
+ getLogger().log(Level.WARNING, "containsId query failed", e);
}
}
return false;
@@ -227,6 +226,7 @@ public class SQLContainer implements Container, Container.Filterable,
* @see com.vaadin.data.Container#getContainerProperty(java.lang.Object,
* java.lang.Object)
*/
+
public Property<?> getContainerProperty(Object itemId, Object propertyId) {
Item item = getItem(itemId);
if (item == null) {
@@ -240,6 +240,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#getContainerPropertyIds()
*/
+
public Collection<?> getContainerPropertyIds() {
return Collections.unmodifiableCollection(propertyIds);
}
@@ -249,6 +250,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#getItem(java.lang.Object)
*/
+
public Item getItem(Object itemId) {
if (!cachedItems.containsKey(itemId)) {
int index = indexOfId(itemId);
@@ -295,6 +297,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* {@inheritDoc}
*/
+
public Collection<?> getItemIds() {
updateCount();
ArrayList<RowId> ids = new ArrayList<RowId>();
@@ -325,17 +328,18 @@ public class SQLContainer implements Container, Container.Filterable,
rs.close();
delegate.commit();
} catch (SQLException e) {
- logger.log(Level.WARNING, "getItemIds() failed, rolling back.", e);
+ getLogger().log(Level.WARNING,
+ "getItemIds() failed, rolling back.", e);
try {
delegate.rollback();
} catch (SQLException e1) {
- logger.log(Level.SEVERE, "Failed to roll back state", e1);
+ getLogger().log(Level.SEVERE, "Failed to roll back state", e1);
}
try {
rs.getStatement().close();
rs.close();
} catch (SQLException e1) {
- logger.log(Level.WARNING, "Closing session failed", e1);
+ getLogger().log(Level.WARNING, "Closing session failed", e1);
}
throw new RuntimeException("Failed to fetch item indexes.", e);
}
@@ -350,6 +354,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#getType(java.lang.Object)
*/
+
public Class<?> getType(Object propertyId) {
if (!propertyIds.contains(propertyId)) {
return null;
@@ -362,6 +367,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#size()
*/
+
public int size() {
updateCount();
return size + sizeOfAddedItems() - removedItems.size();
@@ -372,6 +378,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#removeItem(java.lang.Object)
*/
+
public boolean removeItem(Object itemId)
throws UnsupportedOperationException {
if (!containsId(itemId)) {
@@ -400,29 +407,29 @@ public class SQLContainer implements Container, Container.Filterable,
CacheFlushNotifier.notifyOfCacheFlush(this);
}
if (success) {
- logger.log(Level.FINER, "Row removed from DB...");
+ getLogger().log(Level.FINER, "Row removed from DB...");
}
return success;
} catch (SQLException e) {
- logger.log(Level.WARNING, "Failed to remove row, rolling back",
- e);
+ getLogger().log(Level.WARNING,
+ "Failed to remove row, rolling back", e);
try {
delegate.rollback();
} catch (SQLException ee) {
/* Nothing can be done here */
- logger.log(Level.SEVERE, "Failed to rollback row removal",
- ee);
+ getLogger().log(Level.SEVERE,
+ "Failed to rollback row removal", ee);
}
return false;
} catch (OptimisticLockException e) {
- logger.log(Level.WARNING, "Failed to remove row, rolling back",
- e);
+ getLogger().log(Level.WARNING,
+ "Failed to remove row, rolling back", e);
try {
delegate.rollback();
} catch (SQLException ee) {
/* Nothing can be done here */
- logger.log(Level.SEVERE, "Failed to rollback row removal",
- ee);
+ getLogger().log(Level.SEVERE,
+ "Failed to rollback row removal", ee);
}
throw e;
}
@@ -439,6 +446,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#removeAllItems()
*/
+
public boolean removeAllItems() throws UnsupportedOperationException {
if (autoCommit) {
/* Remove and commit instantly. */
@@ -452,7 +460,7 @@ public class SQLContainer implements Container, Container.Filterable,
}
if (success) {
delegate.commit();
- logger.log(Level.FINER, "All rows removed from DB...");
+ getLogger().log(Level.FINER, "All rows removed from DB...");
refresh();
if (notificationsEnabled) {
CacheFlushNotifier.notifyOfCacheFlush(this);
@@ -462,23 +470,23 @@ public class SQLContainer implements Container, Container.Filterable,
}
return success;
} catch (SQLException e) {
- logger.log(Level.WARNING,
+ getLogger().log(Level.WARNING,
"removeAllItems() failed, rolling back", e);
try {
delegate.rollback();
} catch (SQLException ee) {
/* Nothing can be done here */
- logger.log(Level.SEVERE, "Failed to roll back", ee);
+ getLogger().log(Level.SEVERE, "Failed to roll back", ee);
}
return false;
} catch (OptimisticLockException e) {
- logger.log(Level.WARNING,
+ getLogger().log(Level.WARNING,
"removeAllItems() failed, rolling back", e);
try {
delegate.rollback();
} catch (SQLException ee) {
/* Nothing can be done here */
- logger.log(Level.SEVERE, "Failed to roll back", ee);
+ getLogger().log(Level.SEVERE, "Failed to roll back", ee);
}
throw e;
}
@@ -499,6 +507,7 @@ public class SQLContainer implements Container, Container.Filterable,
/**
* {@inheritDoc}
*/
+
public void addContainerFilter(Filter filter)
throws UnsupportedFilterException {
// filter.setCaseSensitive(!ignoreCase);
@@ -510,6 +519,7 @@ public class SQLContainer implements Container, Container.Filterable,
/**
* {@inheritDoc}
*/
+
public void removeContainerFilter(Filter filter) {
filters.remove(filter);
}
@@ -549,6 +559,7 @@ public class SQLContainer implements Container, Container.Filterable,
/**
* {@inheritDoc}
*/
+
public void removeAllContainerFilters() {
filters.clear();
refresh();
@@ -563,6 +574,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Indexed#indexOfId(java.lang.Object)
*/
+
public int indexOfId(Object itemId) {
// First check if the id is in the added items
for (int ix = 0; ix < addedItems.size(); ix++) {
@@ -609,6 +621,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Indexed#getIdByIndex(int)
*/
+
public Object getIdByIndex(int index) {
if (index < 0 || index > size() - 1) {
return null;
@@ -635,6 +648,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Ordered#nextItemId(java.lang.Object)
*/
+
public Object nextItemId(Object itemId) {
return getIdByIndex(indexOfId(itemId) + 1);
}
@@ -644,6 +658,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Ordered#prevItemId(java.lang.Object)
*/
+
public Object prevItemId(Object itemId) {
return getIdByIndex(indexOfId(itemId) - 1);
}
@@ -653,6 +668,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Ordered#firstItemId()
*/
+
public Object firstItemId() {
updateCount();
if (size == 0) {
@@ -680,6 +696,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Ordered#lastItemId()
*/
+
public Object lastItemId() {
if (addedItems.isEmpty()) {
int lastIx = size() - 1;
@@ -705,6 +722,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Ordered#isFirstId(java.lang.Object)
*/
+
public boolean isFirstId(Object itemId) {
return firstItemId().equals(itemId);
}
@@ -714,6 +732,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Ordered#isLastId(java.lang.Object)
*/
+
public boolean isLastId(Object itemId) {
return lastItemId().equals(itemId);
}
@@ -728,6 +747,7 @@ public class SQLContainer implements Container, Container.Filterable,
* @see com.vaadin.data.Container.Sortable#sort(java.lang.Object[],
* boolean[])
*/
+
public void sort(Object[] propertyId, boolean[] ascending) {
sorters.clear();
if (propertyId == null || propertyId.length == 0) {
@@ -743,7 +763,7 @@ public class SQLContainer implements Container, Container.Filterable,
try {
asc = ascending[i];
} catch (Exception e) {
- logger.log(Level.WARNING, "", e);
+ getLogger().log(Level.WARNING, "", e);
}
sorters.add(new OrderBy((String) propertyId[i], asc));
}
@@ -756,6 +776,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Sortable#getSortableContainerPropertyIds()
*/
+
public Collection<?> getSortableContainerPropertyIds() {
return getContainerPropertyIds();
}
@@ -872,7 +893,8 @@ public class SQLContainer implements Container, Container.Filterable,
*/
public void commit() throws UnsupportedOperationException, SQLException {
try {
- logger.log(Level.FINER, "Commiting changes through delegate...");
+ getLogger().log(Level.FINER,
+ "Commiting changes through delegate...");
delegate.beginTransaction();
/* Perform buffered deletions */
for (RowItem item : removedItems.values()) {
@@ -926,7 +948,7 @@ public class SQLContainer implements Container, Container.Filterable,
* @throws SQLException
*/
public void rollback() throws UnsupportedOperationException, SQLException {
- logger.log(Level.FINE, "Rolling back changes...");
+ getLogger().log(Level.FINE, "Rolling back changes...");
removedItems.clear();
addedItems.clear();
modifiedItems.clear();
@@ -956,15 +978,15 @@ public class SQLContainer implements Container, Container.Filterable,
if (notificationsEnabled) {
CacheFlushNotifier.notifyOfCacheFlush(this);
}
- logger.log(Level.FINER, "Row updated to DB...");
+ getLogger().log(Level.FINER, "Row updated to DB...");
} catch (SQLException e) {
- logger.log(Level.WARNING,
+ getLogger().log(Level.WARNING,
"itemChangeNotification failed, rolling back...", e);
try {
delegate.rollback();
} catch (SQLException ee) {
/* Nothing can be done here */
- logger.log(Level.SEVERE, "Rollback failed", e);
+ getLogger().log(Level.SEVERE, "Rollback failed", e);
}
throw new RuntimeException(e);
}
@@ -1009,13 +1031,13 @@ public class SQLContainer implements Container, Container.Filterable,
try {
delegate.setFilters(filters);
} catch (UnsupportedOperationException e) {
- logger.log(Level.FINE,
+ getLogger().log(Level.FINE,
"The query delegate doesn't support filtering", e);
}
try {
delegate.setOrderBy(sorters);
} catch (UnsupportedOperationException e) {
- logger.log(Level.FINE,
+ getLogger().log(Level.FINE,
"The query delegate doesn't support filtering", e);
}
int newSize = delegate.getCount();
@@ -1025,7 +1047,8 @@ public class SQLContainer implements Container, Container.Filterable,
}
sizeUpdated = new Date();
sizeDirty = false;
- logger.log(Level.FINER, "Updated row count. New count is: " + size);
+ getLogger().log(Level.FINER,
+ "Updated row count. New count is: " + size);
} catch (SQLException e) {
throw new RuntimeException("Failed to update item set size.", e);
}
@@ -1069,7 +1092,7 @@ public class SQLContainer implements Container, Container.Filterable,
try {
type = Class.forName(rsmd.getColumnClassName(i));
} catch (Exception e) {
- logger.log(Level.WARNING, "Class not found", e);
+ getLogger().log(Level.WARNING, "Class not found", e);
/* On failure revert to Object and hope for the best. */
type = Object.class;
}
@@ -1095,14 +1118,14 @@ public class SQLContainer implements Container, Container.Filterable,
rs.getStatement().close();
rs.close();
delegate.commit();
- logger.log(Level.FINER, "Property IDs fetched.");
+ getLogger().log(Level.FINER, "Property IDs fetched.");
} catch (SQLException e) {
- logger.log(Level.WARNING,
+ getLogger().log(Level.WARNING,
"Failed to fetch property ids, rolling back", e);
try {
delegate.rollback();
} catch (SQLException e1) {
- logger.log(Level.SEVERE, "Failed to roll back", e1);
+ getLogger().log(Level.SEVERE, "Failed to roll back", e1);
}
try {
if (rs != null) {
@@ -1112,7 +1135,7 @@ public class SQLContainer implements Container, Container.Filterable,
rs.close();
}
} catch (SQLException e1) {
- logger.log(Level.WARNING, "Failed to close session", e1);
+ getLogger().log(Level.WARNING, "Failed to close session", e1);
}
throw e;
}
@@ -1135,7 +1158,7 @@ public class SQLContainer implements Container, Container.Filterable,
} catch (UnsupportedOperationException e) {
/* The query delegate doesn't support sorting. */
/* No need to do anything. */
- logger.log(Level.FINE,
+ getLogger().log(Level.FINE,
"The query delegate doesn't support sorting", e);
}
delegate.beginTransaction();
@@ -1217,14 +1240,17 @@ public class SQLContainer implements Container, Container.Filterable,
rs.getStatement().close();
rs.close();
delegate.commit();
- logger.log(Level.FINER, "Fetched " + pageLength * CACHE_RATIO
- + " rows starting from " + currentOffset);
+ getLogger().log(
+ Level.FINER,
+ "Fetched " + pageLength * CACHE_RATIO
+ + " rows starting from " + currentOffset);
} catch (SQLException e) {
- logger.log(Level.WARNING, "Failed to fetch rows, rolling back", e);
+ getLogger().log(Level.WARNING,
+ "Failed to fetch rows, rolling back", e);
try {
delegate.rollback();
} catch (SQLException e1) {
- logger.log(Level.SEVERE, "Failed to roll back", e1);
+ getLogger().log(Level.SEVERE, "Failed to roll back", e1);
}
try {
if (rs != null) {
@@ -1234,7 +1260,7 @@ public class SQLContainer implements Container, Container.Filterable,
}
}
} catch (SQLException e1) {
- logger.log(Level.WARNING, "Failed to close session", e1);
+ getLogger().log(Level.WARNING, "Failed to close session", e1);
}
throw new RuntimeException("Failed to fetch page.", e);
}
@@ -1324,6 +1350,7 @@ public class SQLContainer implements Container, Container.Filterable,
* @see com.vaadin.data.Container#addContainerProperty(java.lang.Object,
* java.lang.Class, java.lang.Object)
*/
+
public boolean addContainerProperty(Object propertyId, Class<?> type,
Object defaultValue) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
@@ -1334,6 +1361,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#removeContainerProperty(java.lang.Object)
*/
+
public boolean removeContainerProperty(Object propertyId)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
@@ -1344,6 +1372,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#addItem(java.lang.Object)
*/
+
public Item addItem(Object itemId) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@@ -1354,6 +1383,7 @@ public class SQLContainer implements Container, Container.Filterable,
* @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object,
* java.lang.Object)
*/
+
public Item addItemAfter(Object previousItemId, Object newItemId)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
@@ -1364,6 +1394,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Indexed#addItemAt(int, java.lang.Object)
*/
+
public Item addItemAt(int index, Object newItemId)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
@@ -1374,6 +1405,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Indexed#addItemAt(int)
*/
+
public Object addItemAt(int index) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@@ -1383,6 +1415,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object)
*/
+
public Object addItemAfter(Object previousItemId)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
@@ -1399,6 +1432,7 @@ public class SQLContainer implements Container, Container.Filterable,
* com.vaadin.data.Container.ItemSetChangeNotifier#addListener(com.vaadin
* .data.Container.ItemSetChangeListener)
*/
+
public void addListener(Container.ItemSetChangeListener listener) {
if (itemSetChangeListeners == null) {
itemSetChangeListeners = new LinkedList<Container.ItemSetChangeListener>();
@@ -1413,6 +1447,7 @@ public class SQLContainer implements Container, Container.Filterable,
* com.vaadin.data.Container.ItemSetChangeNotifier#removeListener(com.vaadin
* .data.Container.ItemSetChangeListener)
*/
+
public void removeListener(Container.ItemSetChangeListener listener) {
if (itemSetChangeListeners != null) {
itemSetChangeListeners.remove(listener);
@@ -1577,7 +1612,8 @@ public class SQLContainer implements Container, Container.Filterable,
r.getReferencedColumn()));
return true;
} catch (Exception e) {
- logger.log(Level.WARNING, "Setting referenced item failed.", e);
+ getLogger()
+ .log(Level.WARNING, "Setting referenced item failed.", e);
return false;
}
}
@@ -1640,4 +1676,7 @@ public class SQLContainer implements Container, Container.Filterable,
}
}
+ private static final Logger getLogger() {
+ return Logger.getLogger(SQLContainer.class.getName());
+ }
}
diff --git a/src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPool.java b/src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPool.java
index 9e4bb772f5..40d0d0426f 100644
--- a/src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPool.java
+++ b/src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPool.java
@@ -13,8 +13,6 @@ import javax.naming.NamingException;
import javax.sql.DataSource;
public class J2EEConnectionPool implements JDBCConnectionPool {
- private static final Logger logger = Logger
- .getLogger(J2EEConnectionPool.class.getName());
private String dataSourceJndiName;
@@ -58,7 +56,8 @@ public class J2EEConnectionPool implements JDBCConnectionPool {
try {
conn.close();
} catch (SQLException e) {
- logger.log(Level.FINE, "Could not release SQL connection", e);
+ Logger.getLogger(J2EEConnectionPool.class.getName()).log(
+ Level.FINE, "Could not release SQL connection", e);
}
}
}
diff --git a/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java b/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java
index 7e546309f6..22ca30cc32 100644
--- a/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java
+++ b/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java
@@ -38,9 +38,6 @@ import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper;
public class TableQuery implements QueryDelegate,
QueryDelegate.RowIdChangeNotifier {
- private static final Logger logger = Logger.getLogger(TableQuery.class
- .getName());
-
/** Table name, primary key column name(s) and version column name */
private String tableName;
private List<String> primaryKeyColumns;
@@ -115,7 +112,7 @@ public class TableQuery implements QueryDelegate,
* @see com.vaadin.addon.sqlcontainer.query.QueryDelegate#getCount()
*/
public int getCount() throws SQLException {
- logger.log(Level.FINE, "Fetching count...");
+ getLogger().log(Level.FINE, "Fetching count...");
StatementHelper sh = sqlGenerator.generateSelectQuery(tableName,
filters, null, 0, 0, "COUNT(*)");
boolean shouldCloseTransaction = false;
@@ -228,7 +225,7 @@ public class TableQuery implements QueryDelegate,
PreparedStatement pstmt = activeConnection.prepareStatement(
sh.getQueryString(), primaryKeyColumns.toArray(new String[0]));
sh.setParameterValuesToStatement(pstmt);
- logger.log(Level.FINE, "DB -> " + sh.getQueryString());
+ getLogger().log(Level.FINE, "DB -> " + sh.getQueryString());
int result = pstmt.executeUpdate();
if (result > 0) {
/*
@@ -293,7 +290,7 @@ public class TableQuery implements QueryDelegate,
throw new IllegalStateException();
}
- logger.log(Level.FINE, "DB -> begin transaction");
+ getLogger().log(Level.FINE, "DB -> begin transaction");
activeConnection = connectionPool.reserveConnection();
activeConnection.setAutoCommit(false);
transactionOpen = true;
@@ -306,7 +303,7 @@ public class TableQuery implements QueryDelegate,
*/
public void commit() throws UnsupportedOperationException, SQLException {
if (transactionOpen && activeConnection != null) {
- logger.log(Level.FINE, "DB -> commit");
+ getLogger().log(Level.FINE, "DB -> commit");
activeConnection.commit();
connectionPool.releaseConnection(activeConnection);
} else {
@@ -334,7 +331,7 @@ public class TableQuery implements QueryDelegate,
*/
public void rollback() throws UnsupportedOperationException, SQLException {
if (transactionOpen && activeConnection != null) {
- logger.log(Level.FINE, "DB -> rollback");
+ getLogger().log(Level.FINE, "DB -> rollback");
activeConnection.rollback();
connectionPool.releaseConnection(activeConnection);
} else {
@@ -389,7 +386,7 @@ public class TableQuery implements QueryDelegate,
}
PreparedStatement pstmt = c.prepareStatement(sh.getQueryString());
sh.setParameterValuesToStatement(pstmt);
- logger.log(Level.FINE, "DB -> " + sh.getQueryString());
+ getLogger().log(Level.FINE, "DB -> " + sh.getQueryString());
return pstmt.executeQuery();
}
@@ -415,7 +412,7 @@ public class TableQuery implements QueryDelegate,
}
pstmt = c.prepareStatement(sh.getQueryString());
sh.setParameterValuesToStatement(pstmt);
- logger.log(Level.FINE, "DB -> " + sh.getQueryString());
+ getLogger().log(Level.FINE, "DB -> " + sh.getQueryString());
int retval = pstmt.executeUpdate();
return retval;
} finally {
@@ -458,7 +455,7 @@ public class TableQuery implements QueryDelegate,
pstmt = c.prepareStatement(sh.getQueryString(),
primaryKeyColumns.toArray(new String[0]));
sh.setParameterValuesToStatement(pstmt);
- logger.log(Level.FINE, "DB -> " + sh.getQueryString());
+ getLogger().log(Level.FINE, "DB -> " + sh.getQueryString());
int result = pstmt.executeUpdate();
genKeys = pstmt.getGeneratedKeys();
RowId newId = getNewRowId(row, genKeys);
@@ -571,7 +568,7 @@ public class TableQuery implements QueryDelegate,
}
return new RowId(newRowId.toArray());
} catch (Exception e) {
- logger.log(Level.FINE,
+ getLogger().log(Level.FINE,
"Failed to fetch key values on insert: " + e.getMessage());
return null;
}
@@ -586,8 +583,8 @@ public class TableQuery implements QueryDelegate,
*/
public boolean removeRow(RowItem row) throws UnsupportedOperationException,
SQLException {
- logger.log(Level.FINE, "Removing row with id: "
- + row.getId().getId()[0].toString());
+ getLogger().log(Level.FINE,
+ "Removing row with id: " + row.getId().getId()[0].toString());
if (executeUpdate(sqlGenerator.generateDeleteQuery(getTableName(),
primaryKeyColumns, versionColumn, row)) == 1) {
return true;
@@ -695,4 +692,8 @@ public class TableQuery implements QueryDelegate,
rowIdChangeListeners.remove(listener);
}
}
+
+ private static final Logger getLogger() {
+ return Logger.getLogger(TableQuery.class.getName());
+ }
}
diff --git a/src/com/vaadin/event/ListenerMethod.java b/src/com/vaadin/event/ListenerMethod.java
index 1f1305fa69..f7dc8a7f13 100644
--- a/src/com/vaadin/event/ListenerMethod.java
+++ b/src/com/vaadin/event/ListenerMethod.java
@@ -43,9 +43,6 @@ import java.util.logging.Logger;
@SuppressWarnings("serial")
public class ListenerMethod implements EventListener, Serializable {
- private static final Logger logger = Logger.getLogger(ListenerMethod.class
- .getName());
-
/**
* Type of the event that should trigger this listener. Also the subclasses
* of this class are accepted to trigger the listener.
@@ -84,9 +81,10 @@ public class ListenerMethod implements EventListener, Serializable {
out.writeObject(name);
out.writeObject(paramTypes);
} catch (NotSerializableException e) {
- logger.warning("Error in serialization of the application: Class "
- + target.getClass().getName()
- + " must implement serialization.");
+ getLogger().warning(
+ "Error in serialization of the application: Class "
+ + target.getClass().getName()
+ + " must implement serialization.");
throw e;
}
@@ -103,7 +101,7 @@ public class ListenerMethod implements EventListener, Serializable {
// inner classes
method = findHighestMethod(target.getClass(), name, paramTypes);
} catch (SecurityException e) {
- logger.log(Level.SEVERE, "Internal deserialization error", e);
+ getLogger().log(Level.SEVERE, "Internal deserialization error", e);
}
};
@@ -658,4 +656,8 @@ public class ListenerMethod implements EventListener, Serializable {
return target;
}
+ private static final Logger getLogger() {
+ return Logger.getLogger(ListenerMethod.class.getName());
+ }
+
}
diff --git a/src/com/vaadin/event/dd/acceptcriteria/AcceptAll.java b/src/com/vaadin/event/dd/acceptcriteria/AcceptAll.java
index 87193e8b3e..52ffab9263 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/AcceptAll.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/AcceptAll.java
@@ -7,7 +7,6 @@
package com.vaadin.event.dd.acceptcriteria;
import com.vaadin.event.dd.DragAndDropEvent;
-import com.vaadin.terminal.gwt.client.ui.dd.VAcceptAll;
/**
* Criterion that accepts all drops anywhere on the component.
@@ -18,7 +17,6 @@ import com.vaadin.terminal.gwt.client.ui.dd.VAcceptAll;
* @since 6.3
*
*/
-@ClientCriterion(VAcceptAll.class)
public final class AcceptAll extends ClientSideCriterion {
private static final long serialVersionUID = 7406683402153141461L;
diff --git a/src/com/vaadin/event/dd/acceptcriteria/And.java b/src/com/vaadin/event/dd/acceptcriteria/And.java
index 89c8cb377b..a0340a9cdb 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/And.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/And.java
@@ -19,7 +19,6 @@ import com.vaadin.terminal.PaintTarget;
* @since 6.3
*
*/
-@ClientCriterion(com.vaadin.terminal.gwt.client.ui.dd.VAnd.class)
public class And extends ClientSideCriterion {
private static final long serialVersionUID = -5242574480825471748L;
diff --git a/src/com/vaadin/event/dd/acceptcriteria/ClientCriterion.java b/src/com/vaadin/event/dd/acceptcriteria/ClientCriterion.java
deleted file mode 100644
index 8b64106be7..0000000000
--- a/src/com/vaadin/event/dd/acceptcriteria/ClientCriterion.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.event.dd.acceptcriteria;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import com.vaadin.terminal.gwt.client.ui.dd.VAcceptCriterion;
-
-/**
- * An annotation type used to point the client side counterpart for server side
- * a {@link AcceptCriterion} class.
- * <p>
- * Annotations are used at GWT compilation phase, so remember to rebuild your
- * widgetset if you do changes for {@link ClientCriterion} mappings.
- *
- * @since 6.3
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface ClientCriterion {
- /**
- * @return the client side counterpart for the annotated criterion
- */
- Class<? extends VAcceptCriterion> value();
-}
diff --git a/src/com/vaadin/event/dd/acceptcriteria/ContainsDataFlavor.java b/src/com/vaadin/event/dd/acceptcriteria/ContainsDataFlavor.java
index 298a50a1d5..7eb04d9647 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/ContainsDataFlavor.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/ContainsDataFlavor.java
@@ -10,7 +10,6 @@ import com.vaadin.event.Transferable;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
-import com.vaadin.terminal.gwt.client.ui.dd.VContainsDataFlavor;
/**
* A Criterion that checks whether {@link Transferable} contains given data
@@ -19,7 +18,6 @@ import com.vaadin.terminal.gwt.client.ui.dd.VContainsDataFlavor;
*
* @since 6.3
*/
-@ClientCriterion(VContainsDataFlavor.class)
public class ContainsDataFlavor extends ClientSideCriterion {
private String dataFlavorId;
diff --git a/src/com/vaadin/event/dd/acceptcriteria/Not.java b/src/com/vaadin/event/dd/acceptcriteria/Not.java
index 774dcc642e..85ff7e9bc9 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/Not.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/Not.java
@@ -9,7 +9,6 @@ package com.vaadin.event.dd.acceptcriteria;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
-import com.vaadin.terminal.gwt.client.ui.dd.VNot;
/**
* Criterion that wraps another criterion and inverts its return value.
@@ -17,7 +16,6 @@ import com.vaadin.terminal.gwt.client.ui.dd.VNot;
* @since 6.3
*
*/
-@ClientCriterion(VNot.class)
public class Not extends ClientSideCriterion {
private static final long serialVersionUID = 1131422338558613244L;
diff --git a/src/com/vaadin/event/dd/acceptcriteria/Or.java b/src/com/vaadin/event/dd/acceptcriteria/Or.java
index 2e7cdf45a3..077e9114d8 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/Or.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/Or.java
@@ -9,7 +9,6 @@ package com.vaadin.event.dd.acceptcriteria;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
-import com.vaadin.terminal.gwt.client.ui.dd.VOr;
/**
* A compound criterion that accepts the drag if any of its criterion accepts
@@ -20,7 +19,6 @@ import com.vaadin.terminal.gwt.client.ui.dd.VOr;
* @since 6.3
*
*/
-@ClientCriterion(VOr.class)
public class Or extends ClientSideCriterion {
private static final long serialVersionUID = 1L;
private AcceptCriterion criteria[];
diff --git a/src/com/vaadin/event/dd/acceptcriteria/ServerSideCriterion.java b/src/com/vaadin/event/dd/acceptcriteria/ServerSideCriterion.java
index b3f4702c51..77840bc94f 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/ServerSideCriterion.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/ServerSideCriterion.java
@@ -8,7 +8,6 @@ import java.io.Serializable;
import com.vaadin.event.Transferable;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
-import com.vaadin.terminal.gwt.client.ui.dd.VServerAccept;
/**
* Parent class for criteria which are verified on the server side during a drag
@@ -27,7 +26,6 @@ import com.vaadin.terminal.gwt.client.ui.dd.VServerAccept;
*
* @since 6.3
*/
-@ClientCriterion(VServerAccept.class)
public abstract class ServerSideCriterion implements Serializable,
AcceptCriterion {
diff --git a/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java b/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java
index 0d29e9a327..d7c47dc915 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java
@@ -13,7 +13,6 @@ import com.vaadin.event.TransferableImpl;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
-import com.vaadin.terminal.gwt.client.ui.dd.VDragSourceIs;
import com.vaadin.ui.Component;
/**
@@ -23,10 +22,7 @@ import com.vaadin.ui.Component;
* @since 6.3
*/
@SuppressWarnings("serial")
-@ClientCriterion(VDragSourceIs.class)
public class SourceIs extends ClientSideCriterion {
- private static final Logger logger = Logger.getLogger(SourceIs.class
- .getName());
private Component[] components;
@@ -43,11 +39,11 @@ public class SourceIs extends ClientSideCriterion {
if (c.getApplication() != null) {
target.addAttribute("component" + paintedComponents++, c);
} else {
- logger.log(
- Level.WARNING,
- "SourceIs component {0} at index {1} is not attached to the component hierachy and will thus be ignored",
- new Object[] { c.getClass().getName(),
- Integer.valueOf(i) });
+ Logger.getLogger(SourceIs.class.getName())
+ .log(Level.WARNING,
+ "SourceIs component {0} at index {1} is not attached to the component hierachy and will thus be ignored",
+ new Object[] { c.getClass().getName(),
+ Integer.valueOf(i) });
}
}
target.addAttribute("c", paintedComponents);
diff --git a/src/com/vaadin/event/dd/acceptcriteria/SourceIsTarget.java b/src/com/vaadin/event/dd/acceptcriteria/SourceIsTarget.java
index 8303809140..454159b3da 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/SourceIsTarget.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/SourceIsTarget.java
@@ -10,7 +10,6 @@ import com.vaadin.event.Transferable;
import com.vaadin.event.TransferableImpl;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropTarget;
-import com.vaadin.terminal.gwt.client.ui.dd.VSourceIsTarget;
import com.vaadin.ui.Component;
import com.vaadin.ui.Table;
import com.vaadin.ui.Tree;
@@ -26,7 +25,6 @@ import com.vaadin.ui.Tree;
* @since 6.3
*
*/
-@ClientCriterion(VSourceIsTarget.class)
public class SourceIsTarget extends ClientSideCriterion {
private static final long serialVersionUID = -451399314705532584L;
diff --git a/src/com/vaadin/event/dd/acceptcriteria/TargetDetailIs.java b/src/com/vaadin/event/dd/acceptcriteria/TargetDetailIs.java
index 25371938d2..641fddc3ea 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/TargetDetailIs.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/TargetDetailIs.java
@@ -10,7 +10,6 @@ import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.TargetDetails;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
-import com.vaadin.terminal.gwt.client.ui.dd.VTargetDetailIs;
/**
* Criterion for checking if drop target details contains the specific property
@@ -21,7 +20,6 @@ import com.vaadin.terminal.gwt.client.ui.dd.VTargetDetailIs;
* TODO add support for other basic data types that we support in UIDL.
*
*/
-@ClientCriterion(VTargetDetailIs.class)
public class TargetDetailIs extends ClientSideCriterion {
private static final long serialVersionUID = 763165450054331246L;
diff --git a/src/com/vaadin/navigator/Navigator.java b/src/com/vaadin/navigator/Navigator.java
index 9d9acf9ed3..387f1d4eae 100644
--- a/src/com/vaadin/navigator/Navigator.java
+++ b/src/com/vaadin/navigator/Navigator.java
@@ -10,12 +10,13 @@ import java.util.LinkedList;
import java.util.List;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
+import com.vaadin.terminal.Page;
+import com.vaadin.terminal.Page.FragmentChangedEvent;
+import com.vaadin.terminal.Page.FragmentChangedListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.Root;
-import com.vaadin.ui.Root.FragmentChangedEvent;
-import com.vaadin.ui.Root.FragmentChangedListener;
/**
* Navigator utility that allows switching of views in a part of an application.
@@ -67,7 +68,7 @@ public class Navigator implements Serializable {
*/
public static class UriFragmentManager implements FragmentManager,
FragmentChangedListener {
- private final Root root;
+ private final Page page;
private final Navigator navigator;
/**
@@ -80,20 +81,20 @@ public class Navigator implements Serializable {
* {@link Navigator} to notify of fragment changes (using
* {@link Navigator#navigateTo(String)}
*/
- public UriFragmentManager(Root root, Navigator navigator) {
- this.root = root;
+ public UriFragmentManager(Page page, Navigator navigator) {
+ this.page = page;
this.navigator = navigator;
- root.addListener(this);
+ page.addListener(this);
}
public String getFragment() {
- return root.getFragment();
+ return page.getFragment();
}
public void setFragment(String fragment) {
// TODO ", false" ???
- root.setFragment(fragment);
+ page.setFragment(fragment);
}
public void fragmentChanged(FragmentChangedEvent event) {
@@ -276,9 +277,9 @@ public class Navigator implements Serializable {
* @param display
* where to display the views
*/
- public Navigator(Root root, ViewDisplay display) {
+ public Navigator(Page page, ViewDisplay display) {
this.display = display;
- fragmentManager = new UriFragmentManager(root, this);
+ fragmentManager = new UriFragmentManager(page, this);
}
/**
@@ -289,9 +290,9 @@ public class Navigator implements Serializable {
* @param root
* whose URI fragments are used
*/
- public Navigator(Root root) {
+ public Navigator(Page page) {
display = new SimpleViewDisplay();
- fragmentManager = new UriFragmentManager(root, this);
+ fragmentManager = new UriFragmentManager(page, this);
}
/**
diff --git a/src/com/vaadin/terminal/AbstractClientConnector.java b/src/com/vaadin/terminal/AbstractClientConnector.java
index a2bf4a0be8..6a87f58c71 100644
--- a/src/com/vaadin/terminal/AbstractClientConnector.java
+++ b/src/com/vaadin/terminal/AbstractClientConnector.java
@@ -31,7 +31,12 @@ import com.vaadin.ui.HasComponents;
import com.vaadin.ui.Root;
/**
- *
+ * An abstract base class for ClientConnector implementations. This class
+ * provides all the basic functionality required for connectors.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
*/
public abstract class AbstractClientConnector implements ClientConnector {
/**
@@ -115,6 +120,7 @@ public abstract class AbstractClientConnector implements ClientConnector {
throw new RuntimeException(
"Use registerRpc(T implementation, Class<T> rpcInterfaceType) if the Rpc implementation implements more than one interface");
}
+ @SuppressWarnings("unchecked")
Class<T> type = (Class<T>) interfaces[0];
registerRpc(implementation, type);
}
@@ -210,7 +216,7 @@ public abstract class AbstractClientConnector implements ClientConnector {
public Iterator<ClientConnector> iterator() {
CombinedIterator<ClientConnector> iterator = new CombinedIterator<ClientConnector>();
- iterator.addIterator(connector.getExtensionIterator());
+ iterator.addIterator(connector.getExtensions().iterator());
if (connector instanceof HasComponents) {
HasComponents hasComponents = (HasComponents) connector;
@@ -371,35 +377,42 @@ public abstract class AbstractClientConnector implements ClientConnector {
}
}
+ /**
+ * Get an Iterable for iterating over all child connectors, including both
+ * extensions and child components.
+ *
+ * @param connector
+ * the connector to get children for
+ * @return an Iterable giving all child connectors.
+ */
public static Iterable<ClientConnector> getAllChildrenIterable(
final ClientConnector connector) {
return new AllChildrenIterable(connector);
}
- public Iterator<Extension> getExtensionIterator() {
- return Collections.unmodifiableList(extensions).iterator();
+ public Collection<Extension> getExtensions() {
+ return Collections.unmodifiableCollection(extensions);
}
+ /**
+ * Add an extension to this connector. This method is protected to allow
+ * extensions to select which targets they can extend.
+ *
+ * @param extension
+ * the extension to add
+ */
protected void addExtension(Extension extension) {
- addExtensionAtIndex(extension, extensions.size());
- }
-
- protected void addExtensionAtIndex(Extension extension, int index) {
ClientConnector previousParent = extension.getParent();
if (previousParent == this) {
- int oldIndex = extensions.indexOf(extension);
- if (oldIndex < index) {
- index--;
- }
- extensions.remove(oldIndex);
- extensions.add(index, extension);
- } else {
- if (previousParent != null) {
- previousParent.removeExtension(extension);
- }
- extensions.add(index, extension);
- extension.setParent(this);
+ // Nothing to do, already attached
+ return;
+ } else if (previousParent != null) {
+ throw new IllegalStateException(
+ "Moving an extension from one parent to another is not supported");
}
+
+ extensions.add(extension);
+ extension.setParent(this);
requestRepaint();
}
@@ -447,6 +460,14 @@ public abstract class AbstractClientConnector implements ClientConnector {
}
}
+ /**
+ * {@inheritDoc}
+ *
+ * <p>
+ * The {@link #getApplication()} and {@link #getRoot()} methods might return
+ * <code>null</code> after this method is called.
+ * </p>
+ */
public void detach() {
for (ClientConnector connector : getAllChildrenIterable(this)) {
connector.detach();
diff --git a/src/com/vaadin/terminal/AbstractExtension.java b/src/com/vaadin/terminal/AbstractExtension.java
index 353db85a18..33a60e39ef 100644
--- a/src/com/vaadin/terminal/AbstractExtension.java
+++ b/src/com/vaadin/terminal/AbstractExtension.java
@@ -6,26 +6,69 @@ package com.vaadin.terminal;
import com.vaadin.terminal.gwt.server.ClientConnector;
+/**
+ * An extension is an entity that is attached to a Component or another
+ * Extension and independently communicates between client and server.
+ * <p>
+ * Extensions can use shared state and RPC in the same way as components.
+ * <p>
+ * AbstractExtension adds a mechanism for adding the extension to any Connector
+ * (extend). To let the Extension determine what kind target it can be added to,
+ * the extend method is declared as protected.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
public abstract class AbstractExtension extends AbstractClientConnector
implements Extension {
+ private boolean previouslyAttached = false;
- protected Class<? extends ClientConnector> getAcceptedParentType() {
+ /**
+ * Gets a type that the parent must be an instance of. Override this if the
+ * extension only support certain targets, e.g. if only TextFields can be
+ * extended.
+ *
+ * @return a type that the parent must be an instance of
+ */
+ protected Class<? extends ClientConnector> getSupportedParentType() {
return ClientConnector.class;
}
- protected void attachTo(AbstractClientConnector parent) {
- parent.addExtension(this);
+ /**
+ * Add this extension to the target connector. This method is protected to
+ * allow subclasses to require a more specific type of target.
+ *
+ * @param target
+ * the connector to attach this extension to
+ */
+ protected void extend(AbstractClientConnector target) {
+ target.addExtension(this);
+ }
+
+ /**
+ * Remove this extension from its target. After an extension has been
+ * removed, it can not be attached again.
+ */
+ public void removeFromTarget() {
+ getParent().removeExtension(this);
}
@Override
public void setParent(ClientConnector parent) {
- Class<? extends ClientConnector> acceptedParentType = getAcceptedParentType();
- if (parent == null || acceptedParentType.isInstance(parent)) {
+ if (previouslyAttached && parent != null) {
+ throw new IllegalStateException(
+ "An extension can not be set to extend a new target after getting detached from the previous.");
+ }
+
+ Class<? extends ClientConnector> supportedParentType = getSupportedParentType();
+ if (parent == null || supportedParentType.isInstance(parent)) {
super.setParent(parent);
+ previouslyAttached = true;
} else {
throw new IllegalArgumentException(getClass().getName()
- + " can only be attached to parents of type "
- + acceptedParentType.getName() + " but attach to "
+ + " can only be attached to targets of type "
+ + supportedParentType.getName() + " but attach to "
+ parent.getClass().getName() + " was attempted.");
}
}
diff --git a/src/com/vaadin/terminal/AbstractJavaScriptExtension.java b/src/com/vaadin/terminal/AbstractJavaScriptExtension.java
new file mode 100644
index 0000000000..bdcd948c74
--- /dev/null
+++ b/src/com/vaadin/terminal/AbstractJavaScriptExtension.java
@@ -0,0 +1,158 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal;
+
+import com.vaadin.terminal.gwt.client.JavaScriptExtensionState;
+import com.vaadin.ui.JavaScriptCallback;
+
+/**
+ * Base class for Extensions with all client-side logic implemented using
+ * JavaScript.
+ * <p>
+ * When a new JavaScript extension is initialized in the browser, the framework
+ * will look for a globally defined JavaScript function that will initialize the
+ * extension. The name of the initialization function is formed by replacing .
+ * with _ in the name of the server-side class. If no such function is defined,
+ * each super class is used in turn until a match is found. The framework will
+ * thus first attempt with <code>com_example_MyExtension</code> for the
+ * server-side
+ * <code>com.example.MyExtension extends AbstractJavaScriptExtension</code>
+ * class. If MyExtension instead extends <code>com.example.SuperExtension</code>
+ * , then <code>com_example_SuperExtension</code> will also be attempted if
+ * <code>com_example_MyExtension</code> has not been defined.
+ * <p>
+ *
+ * The initialization function will be called with <code>this</code> pointing to
+ * a connector wrapper object providing integration to Vaadin with the following
+ * functions:
+ * <ul>
+ * <li><code>getConnectorId()</code> - returns a string with the id of the
+ * connector.</li>
+ * <li><code>getParentId([connectorId])</code> - returns a string with the id of
+ * the connector's parent. If <code>connectorId</code> is provided, the id of
+ * the parent of the corresponding connector with the passed id is returned
+ * instead.</li>
+ * <li><code>getWidgetElement([connectorId])</code> - returns the DOM Element
+ * that is the root of a connector's widget. <code>null</code> is returned if
+ * the connector can not be found or if the connector doesn't have a widget. If
+ * <code>connectorId</code> is not provided, the connector id of the current
+ * connector will be used.</li>
+ * <li><code>getState()</code> - returns an object corresponding to the shared
+ * state defined on the server. The scheme for conversion between Java and
+ * JavaScript types is described bellow.</li>
+ * <li><code>registerRpc([name, ] rpcObject)</code> - registers the
+ * <code>rpcObject</code> as a RPC handler. <code>rpcObject</code> should be an
+ * object with field containing functions for all eligible RPC functions. If
+ * <code>name</code> is provided, the RPC handler will only used for RPC calls
+ * for the RPC interface with the same fully qualified Java name. If no
+ * <code>name</code> is provided, the RPC handler will be used for all incoming
+ * RPC invocations where the RPC method name is defined as a function field in
+ * the handler. The scheme for conversion between Java types in the RPC
+ * interface definition and the JavaScript values passed as arguments to the
+ * handler functions is described bellow.</li>
+ * <li><code>getRpcProxy([name])</code> - returns an RPC proxy object. If
+ * <code>name</code> is provided, the proxy object will contain functions for
+ * all methods in the RPC interface with the same fully qualified name, provided
+ * a RPC handler has been registered by the server-side code. If no
+ * <code>name</code> is provided, the returned RPC proxy object will contain
+ * functions for all methods in all RPC interfaces registered for the connector
+ * on the server. If the same method name is present in multiple registered RPC
+ * interfaces, the corresponding function in the RPC proxy object will throw an
+ * exception when called. The scheme for conversion between Java types in the
+ * RPC interface and the JavaScript values that should be passed to the
+ * functions is described bellow.</li>
+ * </ul>
+ * The connector wrapper also supports these special functions:
+ * <ul>
+ * <li><code>onStateChange</code> - If the JavaScript code assigns a function to
+ * the field, that function is called whenever the contents of the shared state
+ * is changed.</li>
+ * <li>Any field name corresponding to a call to
+ * {@link #registerCallback(String, JavaScriptCallback)} on the server will
+ * automatically be present as a function that triggers the registered callback
+ * on the server.</li>
+ * <li>Any field name referred to using
+ * {@link #invokeCallback(String, Object...)} on the server will be called if a
+ * function has been assigned to the field.</li>
+ * </ul>
+ * <p>
+ *
+ * Values in the Shared State and in RPC calls are converted between Java and
+ * JavaScript using the following conventions:
+ * <ul>
+ * <li>Primitive Java numbers (byte, char, int, long, float, double) and their
+ * boxed types (Byte, Character, Integer, Long, Float, Double) are represented
+ * by JavaScript numbers.</li>
+ * <li>The primitive Java boolean and the boxed Boolean are represented by
+ * JavaScript booleans.</li>
+ * <li>Java Strings are represented by JavaScript strings.</li>
+ * <li>List, Set and all arrays in Java are represented by JavaScript arrays.</li>
+ * <li>Map<String, ?> in Java is represented by JavaScript object with fields
+ * corresponding to the map keys.</li>
+ * <li>Any other Java Map is represented by a JavaScript array containing two
+ * arrays, the first contains the keys and the second contains the values in the
+ * same order.</li>
+ * <li>A Java Bean is represented by a JavaScript object with fields
+ * corresponding to the bean's properties.</li>
+ * <li>A Java Connector is represented by a JavaScript string containing the
+ * connector's id.</li>
+ * <li>A pluggable serialization mechanism is provided for types not described
+ * here. Please refer to the documentation for specific types for serialization
+ * information.</li>
+ * </ul>
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public abstract class AbstractJavaScriptExtension extends AbstractExtension {
+ private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper(
+ this);
+
+ @Override
+ protected <T> void registerRpc(T implementation, Class<T> rpcInterfaceType) {
+ super.registerRpc(implementation, rpcInterfaceType);
+ callbackHelper.registerRpc(rpcInterfaceType);
+ }
+
+ /**
+ * Register a {@link JavaScriptCallback} that can be called from the
+ * JavaScript using the provided name. A JavaScript function with the
+ * provided name will be added to the connector wrapper object (initially
+ * available as <code>this</code>). Calling that JavaScript function will
+ * cause the call method in the registered {@link JavaScriptCallback} to be
+ * invoked with the same arguments.
+ *
+ * @param functionName
+ * the name that should be used for client-side callback
+ * @param javaScriptCallback
+ * the callback object that will be invoked when the JavaScript
+ * function is called
+ */
+ protected void registerCallback(String functionName,
+ JavaScriptCallback javaScriptCallback) {
+ callbackHelper.registerCallback(functionName, javaScriptCallback);
+ }
+
+ /**
+ * Invoke a named function that the connector JavaScript has added to the
+ * JavaScript connector wrapper object. The arguments should only contain
+ * data types that can be represented in JavaScript, including primitive
+ * boxing types, arrays, String, List, Set, Map, Connector and JavaBeans.
+ *
+ * @param name
+ * the name of the function
+ * @param arguments
+ * function arguments
+ */
+ protected void invokeCallback(String name, Object... arguments) {
+ callbackHelper.invokeCallback(name, arguments);
+ }
+
+ @Override
+ public JavaScriptExtensionState getState() {
+ return (JavaScriptExtensionState) super.getState();
+ }
+}
diff --git a/src/com/vaadin/terminal/AbstractJavascriptExtension.java b/src/com/vaadin/terminal/AbstractJavascriptExtension.java
deleted file mode 100644
index e741e2af1e..0000000000
--- a/src/com/vaadin/terminal/AbstractJavascriptExtension.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal;
-
-import com.vaadin.ui.JavascriptCallback;
-
-public class AbstractJavascriptExtension extends AbstractExtension {
- private JavascriptRpcHelper rpcHelper = new JavascriptRpcHelper(this);
-
- protected void registerCallback(String functionName,
- JavascriptCallback javascriptCallback) {
- rpcHelper.registerCallback(functionName, javascriptCallback);
- }
-
- protected void invokeCallback(String name, Object... arguments) {
- rpcHelper.invokeCallback(name, arguments);
- }
-}
diff --git a/src/com/vaadin/terminal/ClassResource.java b/src/com/vaadin/terminal/ClassResource.java
index fa196e90d9..e7419576f1 100644
--- a/src/com/vaadin/terminal/ClassResource.java
+++ b/src/com/vaadin/terminal/ClassResource.java
@@ -60,13 +60,7 @@ public class ClassResource implements ApplicationResource, Serializable {
* the application this resource will be added to.
*/
public ClassResource(String resourceName, Application application) {
- associatedClass = application.getClass();
- this.resourceName = resourceName;
- this.application = application;
- if (resourceName == null) {
- throw new NullPointerException();
- }
- application.addResource(this);
+ this(application.getClass(), resourceName, application);
}
/**
diff --git a/src/com/vaadin/terminal/Extension.java b/src/com/vaadin/terminal/Extension.java
index 7769423f0d..ef5bb4cf8d 100644
--- a/src/com/vaadin/terminal/Extension.java
+++ b/src/com/vaadin/terminal/Extension.java
@@ -6,6 +6,22 @@ package com.vaadin.terminal;
import com.vaadin.terminal.gwt.server.ClientConnector;
+/**
+ * An extension is an entity that is attached to a Component or another
+ * Extension and independently communicates between client and server.
+ * <p>
+ * An extension can only be attached once. It is not supported to move an
+ * extension from one target to another.
+ * <p>
+ * Extensions can use shared state and RPC in the same way as components.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
public interface Extension extends ClientConnector {
-
+ /*
+ * Currently just an empty marker interface to distinguish between
+ * extensions and other connectors, e.g. components
+ */
}
diff --git a/src/com/vaadin/terminal/JavaScriptCallbackHelper.java b/src/com/vaadin/terminal/JavaScriptCallbackHelper.java
new file mode 100644
index 0000000000..01db0267d9
--- /dev/null
+++ b/src/com/vaadin/terminal/JavaScriptCallbackHelper.java
@@ -0,0 +1,115 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import com.vaadin.external.json.JSONArray;
+import com.vaadin.external.json.JSONException;
+import com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper;
+import com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper.JavaScriptConnectorState;
+import com.vaadin.tools.ReflectTools;
+import com.vaadin.ui.AbstractJavaScriptComponent;
+import com.vaadin.ui.JavaScript.JavaScriptCallbackRpc;
+import com.vaadin.ui.JavaScriptCallback;
+
+/**
+ * Internal helper class used to implement functionality common to
+ * {@link AbstractJavaScriptComponent} and {@link AbstractJavaScriptExtension}.
+ * Corresponding support in client-side code is in
+ * {@link JavaScriptConnectorHelper}.
+ * <p>
+ * You should most likely no use this class directly.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class JavaScriptCallbackHelper implements Serializable {
+
+ private static final Method CALL_METHOD = ReflectTools.findMethod(
+ JavaScriptCallbackRpc.class, "call", String.class, JSONArray.class);
+ private AbstractClientConnector connector;
+
+ private Map<String, JavaScriptCallback> callbacks = new HashMap<String, JavaScriptCallback>();
+ private JavaScriptCallbackRpc javascriptCallbackRpc;
+
+ public JavaScriptCallbackHelper(AbstractClientConnector connector) {
+ this.connector = connector;
+ }
+
+ public void registerCallback(String functionName,
+ JavaScriptCallback javaScriptCallback) {
+ callbacks.put(functionName, javaScriptCallback);
+ JavaScriptConnectorState state = getConnectorState();
+ if (state.getCallbackNames().add(functionName)) {
+ connector.requestRepaint();
+ }
+ ensureRpc();
+ }
+
+ private JavaScriptConnectorState getConnectorState() {
+ JavaScriptConnectorState state = (JavaScriptConnectorState) connector
+ .getState();
+ return state;
+ }
+
+ private void ensureRpc() {
+ if (javascriptCallbackRpc == null) {
+ javascriptCallbackRpc = new JavaScriptCallbackRpc() {
+ public void call(String name, JSONArray arguments) {
+ JavaScriptCallback callback = callbacks.get(name);
+ try {
+ callback.call(arguments);
+ } catch (JSONException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ };
+ connector.registerRpc(javascriptCallbackRpc);
+ }
+ }
+
+ public void invokeCallback(String name, Object... arguments) {
+ if (callbacks.containsKey(name)) {
+ throw new IllegalStateException(
+ "Can't call callback "
+ + name
+ + " on the client because a callback with the same name is registered on the server.");
+ }
+ JSONArray args = new JSONArray(Arrays.asList(arguments));
+ connector.addMethodInvocationToQueue(
+ JavaScriptCallbackRpc.class.getName(), CALL_METHOD,
+ new Object[] { name, args });
+ connector.requestRepaint();
+ }
+
+ public void registerRpc(Class<?> rpcInterfaceType) {
+ if (rpcInterfaceType == JavaScriptCallbackRpc.class) {
+ // Ignore
+ return;
+ }
+ Map<String, Set<String>> rpcInterfaces = getConnectorState()
+ .getRpcInterfaces();
+ String interfaceName = rpcInterfaceType.getName();
+ if (!rpcInterfaces.containsKey(interfaceName)) {
+ Set<String> methodNames = new HashSet<String>();
+
+ for (Method method : rpcInterfaceType.getMethods()) {
+ methodNames.add(method.getName());
+ }
+
+ rpcInterfaces.put(interfaceName, methodNames);
+ connector.requestRepaint();
+ }
+ }
+
+}
diff --git a/src/com/vaadin/terminal/JavascriptRpcHelper.java b/src/com/vaadin/terminal/JavascriptRpcHelper.java
deleted file mode 100644
index b566462833..0000000000
--- a/src/com/vaadin/terminal/JavascriptRpcHelper.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-import com.vaadin.external.json.JSONArray;
-import com.vaadin.external.json.JSONException;
-import com.vaadin.tools.ReflectTools;
-import com.vaadin.ui.JavascriptCallback;
-import com.vaadin.ui.JavascriptManager.JavascriptCallbackRpc;
-
-public class JavascriptRpcHelper {
-
- private static final Method CALL_METHOD = ReflectTools.findMethod(
- JavascriptCallbackRpc.class, "call", String.class, JSONArray.class);
- private AbstractClientConnector connector;
-
- private Map<String, JavascriptCallback> callbacks = new HashMap<String, JavascriptCallback>();
- private JavascriptCallbackRpc javascriptCallbackRpc;
-
- public JavascriptRpcHelper(AbstractClientConnector connector) {
- this.connector = connector;
- }
-
- public void registerCallback(String functionName,
- JavascriptCallback javascriptCallback) {
- callbacks.put(functionName, javascriptCallback);
- ensureRpc();
- }
-
- private void ensureRpc() {
- if (javascriptCallbackRpc == null) {
- javascriptCallbackRpc = new JavascriptCallbackRpc() {
- public void call(String name, JSONArray arguments) {
- JavascriptCallback callback = callbacks.get(name);
- try {
- callback.call(arguments);
- } catch (JSONException e) {
- throw new IllegalArgumentException(e);
- }
- }
- };
- connector.registerRpc(javascriptCallbackRpc);
- }
- }
-
- public void invokeCallback(String name, Object... arguments) {
- JSONArray args = new JSONArray(Arrays.asList(arguments));
- connector.addMethodInvocationToQueue(
- JavascriptCallbackRpc.class.getName(), CALL_METHOD,
- new Object[] { name, args });
- connector.requestRepaint();
- }
-
-}
diff --git a/src/com/vaadin/terminal/Page.java b/src/com/vaadin/terminal/Page.java
new file mode 100644
index 0000000000..65fa500d27
--- /dev/null
+++ b/src/com/vaadin/terminal/Page.java
@@ -0,0 +1,630 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.EventObject;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.vaadin.event.EventRouter;
+import com.vaadin.terminal.WrappedRequest.BrowserDetails;
+import com.vaadin.terminal.gwt.client.ui.notification.VNotification;
+import com.vaadin.terminal.gwt.client.ui.root.PageClientRpc;
+import com.vaadin.terminal.gwt.client.ui.root.VRoot;
+import com.vaadin.terminal.gwt.server.WebApplicationContext;
+import com.vaadin.terminal.gwt.server.WebBrowser;
+import com.vaadin.tools.ReflectTools;
+import com.vaadin.ui.JavaScript;
+import com.vaadin.ui.Notification;
+import com.vaadin.ui.Root;
+
+public class Page implements Serializable {
+
+ /**
+ * Listener that gets notified when the size of the browser window
+ * containing the root has changed.
+ *
+ * @see Root#addListener(BrowserWindowResizeListener)
+ */
+ public interface BrowserWindowResizeListener extends Serializable {
+ /**
+ * Invoked when the browser window containing a Root has been resized.
+ *
+ * @param event
+ * a browser window resize event
+ */
+ public void browserWindowResized(BrowserWindowResizeEvent event);
+ }
+
+ /**
+ * Event that is fired when a browser window containing a root is resized.
+ */
+ public class BrowserWindowResizeEvent extends EventObject {
+
+ private final int width;
+ private final int height;
+
+ /**
+ * Creates a new event
+ *
+ * @param source
+ * the root for which the browser window has been resized
+ * @param width
+ * the new width of the browser window
+ * @param height
+ * the new height of the browser window
+ */
+ public BrowserWindowResizeEvent(Page source, int width, int height) {
+ super(source);
+ this.width = width;
+ this.height = height;
+ }
+
+ @Override
+ public Page getSource() {
+ return (Page) super.getSource();
+ }
+
+ /**
+ * Gets the new browser window height
+ *
+ * @return an integer with the new pixel height of the browser window
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * Gets the new browser window width
+ *
+ * @return an integer with the new pixel width of the browser window
+ */
+ public int getWidth() {
+ return width;
+ }
+ }
+
+ /**
+ * Private class for storing properties related to opening resources.
+ */
+ private class OpenResource implements Serializable {
+
+ /**
+ * The resource to open
+ */
+ private final Resource resource;
+
+ /**
+ * The name of the target window
+ */
+ private final String name;
+
+ /**
+ * The width of the target window
+ */
+ private final int width;
+
+ /**
+ * The height of the target window
+ */
+ private final int height;
+
+ /**
+ * The border style of the target window
+ */
+ private final int border;
+
+ /**
+ * Creates a new open resource.
+ *
+ * @param resource
+ * The resource to open
+ * @param name
+ * The name of the target window
+ * @param width
+ * The width of the target window
+ * @param height
+ * The height of the target window
+ * @param border
+ * The border style of the target window
+ */
+ private OpenResource(Resource resource, String name, int width,
+ int height, int border) {
+ this.resource = resource;
+ this.name = name;
+ this.width = width;
+ this.height = height;
+ this.border = border;
+ }
+
+ /**
+ * Paints the open request. Should be painted inside the window.
+ *
+ * @param target
+ * the paint target
+ * @throws PaintException
+ * if the paint operation fails
+ */
+ private void paintContent(PaintTarget target) throws PaintException {
+ target.startTag("open");
+ target.addAttribute("src", resource);
+ if (name != null && name.length() > 0) {
+ target.addAttribute("name", name);
+ }
+ if (width >= 0) {
+ target.addAttribute("width", width);
+ }
+ if (height >= 0) {
+ target.addAttribute("height", height);
+ }
+ switch (border) {
+ case BORDER_MINIMAL:
+ target.addAttribute("border", "minimal");
+ break;
+ case BORDER_NONE:
+ target.addAttribute("border", "none");
+ break;
+ }
+
+ target.endTag("open");
+ }
+ }
+
+ private static final Method BROWSWER_RESIZE_METHOD = ReflectTools
+ .findMethod(BrowserWindowResizeListener.class,
+ "browserWindowResized", BrowserWindowResizeEvent.class);
+
+ /**
+ * A border style used for opening resources in a window without a border.
+ */
+ public static final int BORDER_NONE = 0;
+
+ /**
+ * A border style used for opening resources in a window with a minimal
+ * border.
+ */
+ public static final int BORDER_MINIMAL = 1;
+
+ /**
+ * A border style that indicates that the default border style should be
+ * used when opening resources.
+ */
+ public static final int BORDER_DEFAULT = 2;
+
+ /**
+ * Listener that listens changes in URI fragment.
+ */
+ public interface FragmentChangedListener extends Serializable {
+ public void fragmentChanged(FragmentChangedEvent event);
+ }
+
+ private static final Method FRAGMENT_CHANGED_METHOD = ReflectTools
+ .findMethod(Page.FragmentChangedListener.class, "fragmentChanged",
+ FragmentChangedEvent.class);
+
+ /**
+ * Resources to be opened automatically on next repaint. The list is
+ * automatically cleared when it has been sent to the client.
+ */
+ private final LinkedList<OpenResource> openList = new LinkedList<OpenResource>();
+
+ /**
+ * A list of notifications that are waiting to be sent to the client.
+ * Cleared (set to null) when the notifications have been sent.
+ */
+ private List<Notification> notifications;
+
+ /**
+ * Event fired when uri fragment changes.
+ */
+ public class FragmentChangedEvent extends EventObject {
+
+ /**
+ * The new uri fragment
+ */
+ private final String fragment;
+
+ /**
+ * Creates a new instance of UriFragmentReader change event.
+ *
+ * @param source
+ * the Source of the event.
+ */
+ public FragmentChangedEvent(Page source, String fragment) {
+ super(source);
+ this.fragment = fragment;
+ }
+
+ /**
+ * Gets the root in which the fragment has changed.
+ *
+ * @return the root in which the fragment has changed
+ */
+ public Page getPage() {
+ return (Page) getSource();
+ }
+
+ /**
+ * Get the new fragment
+ *
+ * @return the new fragment
+ */
+ public String getFragment() {
+ return fragment;
+ }
+ }
+
+ private EventRouter eventRouter;
+
+ /**
+ * The current URI fragment.
+ */
+ private String fragment;
+
+ private final Root root;
+
+ private int browserWindowWidth = -1;
+ private int browserWindowHeight = -1;
+
+ private JavaScript javaScript;
+
+ public Page(Root root) {
+ this.root = root;
+ }
+
+ private void addListener(Class<?> eventType, Object target, Method method) {
+ if (eventRouter == null) {
+ eventRouter = new EventRouter();
+ }
+ eventRouter.addListener(eventType, target, method);
+ }
+
+ private void removeListener(Class<?> eventType, Object target, Method method) {
+ if (eventRouter != null) {
+ eventRouter.removeListener(eventType, target, method);
+ }
+ }
+
+ public void addListener(Page.FragmentChangedListener listener) {
+ addListener(FragmentChangedEvent.class, listener,
+ FRAGMENT_CHANGED_METHOD);
+ }
+
+ public void removeListener(Page.FragmentChangedListener listener) {
+ removeListener(FragmentChangedEvent.class, listener,
+ FRAGMENT_CHANGED_METHOD);
+ }
+
+ /**
+ * Sets URI fragment. Optionally fires a {@link FragmentChangedEvent}
+ *
+ * @param newFragment
+ * id of the new fragment
+ * @param fireEvent
+ * true to fire event
+ * @see FragmentChangedEvent
+ * @see Page.FragmentChangedListener
+ */
+ public void setFragment(String newFragment, boolean fireEvents) {
+ if (newFragment == null) {
+ throw new NullPointerException("The fragment may not be null");
+ }
+ if (!newFragment.equals(fragment)) {
+ fragment = newFragment;
+ if (fireEvents) {
+ fireEvent(new FragmentChangedEvent(this, newFragment));
+ }
+ root.requestRepaint();
+ }
+ }
+
+ private void fireEvent(EventObject event) {
+ if (eventRouter != null) {
+ eventRouter.fireEvent(event);
+ }
+ }
+
+ /**
+ * Sets URI fragment. This method fires a {@link FragmentChangedEvent}
+ *
+ * @param newFragment
+ * id of the new fragment
+ * @see FragmentChangedEvent
+ * @see Page.FragmentChangedListener
+ */
+ public void setFragment(String newFragment) {
+ setFragment(newFragment, true);
+ }
+
+ /**
+ * Gets currently set URI fragment.
+ * <p>
+ * To listen changes in fragment, hook a
+ * {@link Page.FragmentChangedListener}.
+ *
+ * @return the current fragment in browser uri or null if not known
+ */
+ public String getFragment() {
+ return fragment;
+ }
+
+ public void init(WrappedRequest request) {
+ BrowserDetails browserDetails = request.getBrowserDetails();
+ if (browserDetails != null) {
+ fragment = browserDetails.getUriFragment();
+ }
+ }
+
+ public WebBrowser getWebBrowser() {
+ return ((WebApplicationContext) root.getApplication().getContext())
+ .getBrowser();
+ }
+
+ public void setBrowserWindowSize(Integer width, Integer height) {
+ boolean fireEvent = false;
+
+ if (width != null) {
+ int newWidth = width.intValue();
+ if (newWidth != browserWindowWidth) {
+ browserWindowWidth = newWidth;
+ fireEvent = true;
+ }
+ }
+
+ if (height != null) {
+ int newHeight = height.intValue();
+ if (newHeight != browserWindowHeight) {
+ browserWindowHeight = newHeight;
+ fireEvent = true;
+ }
+ }
+
+ if (fireEvent) {
+ fireEvent(new BrowserWindowResizeEvent(this, browserWindowWidth,
+ browserWindowHeight));
+ }
+
+ }
+
+ /**
+ * Adds a new {@link BrowserWindowResizeListener} to this root. The listener
+ * will be notified whenever the browser window within which this root
+ * resides is resized.
+ *
+ * @param resizeListener
+ * the listener to add
+ *
+ * @see BrowserWindowResizeListener#browserWindowResized(BrowserWindowResizeEvent)
+ * @see #setResizeLazy(boolean)
+ */
+ public void addListener(BrowserWindowResizeListener resizeListener) {
+ addListener(BrowserWindowResizeEvent.class, resizeListener,
+ BROWSWER_RESIZE_METHOD);
+ }
+
+ /**
+ * Removes a {@link BrowserWindowResizeListener} from this root. The
+ * listener will no longer be notified when the browser window is resized.
+ *
+ * @param resizeListener
+ * the listener to remove
+ */
+ public void removeListener(BrowserWindowResizeListener resizeListener) {
+ removeListener(BrowserWindowResizeEvent.class, resizeListener,
+ BROWSWER_RESIZE_METHOD);
+ }
+
+ /**
+ * Gets the last known height of the browser window in which this root
+ * resides.
+ *
+ * @return the browser window height in pixels
+ */
+ public int getBrowserWindowHeight() {
+ return browserWindowHeight;
+ }
+
+ /**
+ * Gets the last known width of the browser window in which this root
+ * resides.
+ *
+ * @return the browser window width in pixels
+ */
+ public int getBrowserWindowWidth() {
+ return browserWindowWidth;
+ }
+
+ public JavaScript getJavaScript() {
+ if (javaScript == null) {
+ // Create and attach on first use
+ javaScript = new JavaScript();
+ javaScript.extend(root);
+ }
+
+ return javaScript;
+ }
+
+ public void paintContent(PaintTarget target) throws PaintException {
+ if (!openList.isEmpty()) {
+ for (final Iterator<OpenResource> i = openList.iterator(); i
+ .hasNext();) {
+ (i.next()).paintContent(target);
+ }
+ openList.clear();
+ }
+
+ // Paint notifications
+ if (notifications != null) {
+ target.startTag("notifications");
+ for (final Iterator<Notification> it = notifications.iterator(); it
+ .hasNext();) {
+ final Notification n = it.next();
+ target.startTag("notification");
+ if (n.getCaption() != null) {
+ target.addAttribute(
+ VNotification.ATTRIBUTE_NOTIFICATION_CAPTION,
+ n.getCaption());
+ }
+ if (n.getDescription() != null) {
+ target.addAttribute(
+ VNotification.ATTRIBUTE_NOTIFICATION_MESSAGE,
+ n.getDescription());
+ }
+ if (n.getIcon() != null) {
+ target.addAttribute(
+ VNotification.ATTRIBUTE_NOTIFICATION_ICON,
+ n.getIcon());
+ }
+ if (!n.isHtmlContentAllowed()) {
+ target.addAttribute(
+ VRoot.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED, true);
+ }
+ target.addAttribute(
+ VNotification.ATTRIBUTE_NOTIFICATION_POSITION,
+ n.getPosition());
+ target.addAttribute(VNotification.ATTRIBUTE_NOTIFICATION_DELAY,
+ n.getDelayMsec());
+ if (n.getStyleName() != null) {
+ target.addAttribute(
+ VNotification.ATTRIBUTE_NOTIFICATION_STYLE,
+ n.getStyleName());
+ }
+ target.endTag("notification");
+ }
+ target.endTag("notifications");
+ notifications = null;
+ }
+
+ if (fragment != null) {
+ target.addAttribute(VRoot.FRAGMENT_VARIABLE, fragment);
+ }
+
+ }
+
+ /**
+ * Opens the given resource in this root. The contents of this Root is
+ * replaced by the {@code Resource}.
+ *
+ * @param resource
+ * the resource to show in this root
+ */
+ public void open(Resource resource) {
+ openList.add(new OpenResource(resource, null, -1, -1, BORDER_DEFAULT));
+ root.requestRepaint();
+ }
+
+ /**
+ * Opens the given resource in a window with the given name.
+ * <p>
+ * The supplied {@code windowName} is used as the target name in a
+ * window.open call in the client. This means that special values such as
+ * "_blank", "_self", "_top", "_parent" have special meaning. An empty or
+ * <code>null</code> window name is also a special case.
+ * </p>
+ * <p>
+ * "", null and "_self" as {@code windowName} all causes the resource to be
+ * opened in the current window, replacing any old contents. For
+ * downloadable content you should avoid "_self" as "_self" causes the
+ * client to skip rendering of any other changes as it considers them
+ * irrelevant (the page will be replaced by the resource). This can speed up
+ * the opening of a resource, but it might also put the client side into an
+ * inconsistent state if the window content is not completely replaced e.g.,
+ * if the resource is downloaded instead of displayed in the browser.
+ * </p>
+ * <p>
+ * "_blank" as {@code windowName} causes the resource to always be opened in
+ * a new window or tab (depends on the browser and browser settings).
+ * </p>
+ * <p>
+ * "_top" and "_parent" as {@code windowName} works as specified by the HTML
+ * standard.
+ * </p>
+ * <p>
+ * Any other {@code windowName} will open the resource in a window with that
+ * name, either by opening a new window/tab in the browser or by replacing
+ * the contents of an existing window with that name.
+ * </p>
+ *
+ * @param resource
+ * the resource.
+ * @param windowName
+ * the name of the window.
+ */
+ public void open(Resource resource, String windowName) {
+ openList.add(new OpenResource(resource, windowName, -1, -1,
+ BORDER_DEFAULT));
+ root.requestRepaint();
+ }
+
+ /**
+ * Opens the given resource in a window with the given size, border and
+ * name. For more information on the meaning of {@code windowName}, see
+ * {@link #open(Resource, String)}.
+ *
+ * @param resource
+ * the resource.
+ * @param windowName
+ * the name of the window.
+ * @param width
+ * the width of the window in pixels
+ * @param height
+ * the height of the window in pixels
+ * @param border
+ * the border style of the window. See {@link #BORDER_NONE
+ * Window.BORDER_* constants}
+ */
+ public void open(Resource resource, String windowName, int width,
+ int height, int border) {
+ openList.add(new OpenResource(resource, windowName, width, height,
+ border));
+ root.requestRepaint();
+ }
+
+ /**
+ * Internal helper method to actually add a notification.
+ *
+ * @param notification
+ * the notification to add
+ */
+ private void addNotification(Notification notification) {
+ if (notifications == null) {
+ notifications = new LinkedList<Notification>();
+ }
+ notifications.add(notification);
+ root.requestRepaint();
+ }
+
+ /**
+ * Shows a notification message.
+ *
+ * @see Notification
+ * @see #showNotification(String)
+ * @see #showNotification(String, int)
+ * @see #showNotification(String, String)
+ * @see #showNotification(String, String, int)
+ *
+ * @param notification
+ * The notification message to show
+ */
+ public void showNotification(Notification notification) {
+ addNotification(notification);
+ }
+
+ public static Page getCurrent() {
+ Root currentRoot = Root.getCurrentRoot();
+ if (currentRoot == null) {
+ return null;
+ }
+ return currentRoot.getPage();
+ }
+
+ public void setTitle(String title) {
+ root.getRpcProxy(PageClientRpc.class).setTitle(title);
+ }
+
+}
diff --git a/src/com/vaadin/terminal/UserError.java b/src/com/vaadin/terminal/UserError.java
index baaf331fa0..a7a4fd89e2 100644
--- a/src/com/vaadin/terminal/UserError.java
+++ b/src/com/vaadin/terminal/UserError.java
@@ -44,6 +44,16 @@ public class UserError extends AbstractErrorMessage {
super(textErrorMessage);
}
+ /**
+ * Creates an error message with level and content mode.
+ *
+ * @param message
+ * the error message.
+ * @param contentMode
+ * the content Mode.
+ * @param errorLevel
+ * the level of error.
+ */
public UserError(String message, ContentMode contentMode,
ErrorLevel errorLevel) {
super(message);
diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java b/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java
index 244f310c1a..960b0a8b0e 100644
--- a/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java
+++ b/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java
@@ -18,6 +18,7 @@ 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.Timer;
+import com.google.gwt.user.client.Window;
import com.vaadin.terminal.gwt.client.ui.UnknownComponentConnector;
public class ApplicationConfiguration implements EntryPoint {
@@ -346,6 +347,7 @@ public class ApplicationConfiguration implements EntryPoint {
*/
public static void startApplication(final String applicationId) {
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+
public void execute() {
ApplicationConfiguration appConf = getConfigFromDOM(applicationId);
ApplicationConnection a = GWT
@@ -568,6 +570,7 @@ public class ApplicationConfiguration implements EntryPoint {
* GWT hosted mode.
*/
GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
+
public void onUncaughtException(Throwable e) {
/*
* Note in case of null console (without ?debug) we eat
@@ -602,12 +605,15 @@ public class ApplicationConfiguration implements EntryPoint {
*
* @return true if client side is currently been debugged
*/
- public native static boolean isDebugMode()
+ public static boolean isDebugMode() {
+ return isDebugAvailable()
+ && Window.Location.getParameter("debug") != null;
+ }
+
+ private native static boolean isDebugAvailable()
/*-{
if($wnd.vaadin.debug) {
- var parameters = $wnd.location.search;
- var re = /debug[^\/]*$/;
- return re.test(parameters);
+ return true;
} else {
return false;
}
@@ -618,12 +624,11 @@ public class ApplicationConfiguration implements EntryPoint {
*
* @return <code>true</code> if debug logging should be quiet
*/
- public native static boolean isQuietDebugMode()
- /*-{
- var uri = $wnd.location;
- var re = /debug=q[^\/]*$/;
- return re.test(uri);
- }-*/;
+ 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
diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
index 93a51e6e96..f0470c8ee8 100644
--- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
+++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
@@ -40,7 +40,7 @@ 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.terminal.gwt.client.ApplicationConfiguration.ErrorMessage;
-import com.vaadin.terminal.gwt.client.communication.HasJavascriptConnectorHelper;
+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.MethodInvocation;
@@ -50,6 +50,7 @@ import com.vaadin.terminal.gwt.client.communication.SharedState;
import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
import com.vaadin.terminal.gwt.client.communication.Type;
import com.vaadin.terminal.gwt.client.communication.UidlValue;
+import com.vaadin.terminal.gwt.client.extensions.AbstractExtensionConnector;
import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector;
import com.vaadin.terminal.gwt.client.ui.VContextMenu;
import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager;
@@ -370,6 +371,25 @@ public class ApplicationConnection {
}-*/;
/**
+ * 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();
+ }
+ }
+ }-*/;
+
+ /**
* Get the active Console for writing debug messages. May return an actual
* logging console, or the NullConsole if debugging is not turned on.
*
@@ -851,6 +871,14 @@ public class ApplicationConnection {
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();
}
}
});
@@ -1415,8 +1443,8 @@ public class ApplicationConnection {
JSONObject stateJson = new JSONObject(
states.getJavaScriptObject(connectorId));
- if (connector instanceof HasJavascriptConnectorHelper) {
- ((HasJavascriptConnectorHelper) connector)
+ if (connector instanceof HasJavaScriptConnectorHelper) {
+ ((HasJavaScriptConnectorHelper) connector)
.getJavascriptConnectorHelper()
.setNativeState(
stateJson.getJavaScriptObject());
@@ -1491,6 +1519,10 @@ public class ApplicationConnection {
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
diff --git a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java
index e12c002930..82cf925ec1 100644
--- a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java
+++ b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java
@@ -31,6 +31,9 @@ public class BrowserInfo {
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;
@@ -169,7 +172,9 @@ public class BrowserInfo {
if (osClass != null) {
cssClass = cssClass + " " + prefix + osClass;
}
-
+ if (isTouchDevice()) {
+ cssClass = cssClass + " " + prefix + UI_TOUCH;
+ }
}
return cssClass;
@@ -344,15 +349,14 @@ public class BrowserInfo {
if (!isTouchDevice()) {
return false;
}
-
- if (isAndroid() && isWebkit() && getWebkitVersion() < 534) {
- return true;
+ if (isAndroid() && isWebkit() && getWebkitVersion() >= 534) {
+ return false;
}
- // if (isIOS() && isWebkit() && getWebkitVersion() < ???) {
- // return true;
+ // Cannot enable native touch scrolling on iOS 5 until #8792 is resolved
+ // if (isIOS() && isWebkit() && getWebkitVersion() >= 534) {
+ // return false;
// }
-
- return false;
+ return true;
}
/**
diff --git a/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java b/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java
new file mode 100644
index 0000000000..bd62a759cb
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java
@@ -0,0 +1,372 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+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.terminal.gwt.client.communication.MethodInvocation;
+import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
+import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler;
+
+public class JavaScriptConnectorHelper {
+
+ public interface JavaScriptConnectorState {
+ public Set<String> getCallbackNames();
+
+ public Map<String, Set<String>> getRpcInterfaces();
+ }
+
+ 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() {
+ 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, 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, 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);
+ }),
+ 'getWidgetElement': $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);
+ },
+ };
+ }-*/;
+
+ 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), true);
+ }
+
+ 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, true);
+ }
+
+ 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/src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java b/src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java
new file mode 100644
index 0000000000..2a97e4a770
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java
@@ -0,0 +1,32 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client;
+
+import com.vaadin.terminal.AbstractJavaScriptExtension;
+import com.vaadin.terminal.gwt.client.communication.HasJavaScriptConnectorHelper;
+import com.vaadin.terminal.gwt.client.extensions.AbstractExtensionConnector;
+import com.vaadin.terminal.gwt.client.ui.Connect;
+
+@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();
+ }
+
+ public JavaScriptConnectorHelper getJavascriptConnectorHelper() {
+ return helper;
+ }
+
+ @Override
+ public JavaScriptExtensionState getState() {
+ return (JavaScriptExtensionState) super.getState();
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/JavaScriptExtensionState.java b/src/com/vaadin/terminal/gwt/client/JavaScriptExtensionState.java
new file mode 100644
index 0000000000..e7bfbc4bb2
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/JavaScriptExtensionState.java
@@ -0,0 +1,36 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper.JavaScriptConnectorState;
+import com.vaadin.terminal.gwt.client.communication.SharedState;
+
+public class JavaScriptExtensionState extends SharedState implements
+ JavaScriptConnectorState {
+
+ private Set<String> callbackNames = new HashSet<String>();
+ private Map<String, Set<String>> rpcInterfaces = new HashMap<String, Set<String>>();
+
+ public Set<String> getCallbackNames() {
+ return callbackNames;
+ }
+
+ public void setCallbackNames(Set<String> callbackNames) {
+ this.callbackNames = callbackNames;
+ }
+
+ public Map<String, Set<String>> getRpcInterfaces() {
+ return rpcInterfaces;
+ }
+
+ public void setRpcInterfaces(Map<String, Set<String>> rpcInterfaces) {
+ this.rpcInterfaces = rpcInterfaces;
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/JavascriptConnectorHelper.java b/src/com/vaadin/terminal/gwt/client/JavascriptConnectorHelper.java
deleted file mode 100644
index ab0e62222c..0000000000
--- a/src/com/vaadin/terminal/gwt/client/JavascriptConnectorHelper.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client;
-
-import java.util.ArrayList;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.JsArray;
-import com.google.gwt.json.client.JSONArray;
-import com.vaadin.terminal.gwt.client.communication.MethodInvocation;
-
-public class JavascriptConnectorHelper {
-
- private final ServerConnector connector;
- private final JavaScriptObject nativeState = JavaScriptObject
- .createObject();
- private final JavaScriptObject rpcMap = JavaScriptObject.createObject();
-
- private JavaScriptObject connectorWrapper;
- private int tag;
-
- public JavascriptConnectorHelper(ServerConnector connector) {
- this.connector = connector;
- }
-
- public boolean init() {
- 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();
- }
-
- return connectorWrapper;
- }
-
- protected JavaScriptObject createConnectorWrapper() {
- return createConnectorWrapper(this, nativeState, rpcMap,
- connector.getConnectorId());
- }
-
- public void fireNativeStateChange() {
- fireNativeStateChange(getConnectorWrapper());
- }
-
- private static native void fireNativeStateChange(
- JavaScriptObject connectorWrapper)
- /*-{
- if (typeof connectorWrapper.onStateChange == 'function') {
- connectorWrapper.onStateChange();
- }
- }-*/;
-
- private static native JavaScriptObject createConnectorWrapper(
- JavascriptConnectorHelper h, JavaScriptObject nativeState,
- JavaScriptObject registeredRpc, String connectorId)
- /*-{
- return {
- 'getConnectorId': function() {
- return connectorId;
- },
- 'getState': function() {
- return nativeState;
- },
- 'getRpcProxyFunction': function(iface, method) {
- return $entry(function() {
- h.@com.vaadin.terminal.gwt.client.JavascriptConnectorHelper::fireRpc(Ljava/lang/String;Ljava/lang/String;Lcom/google/gwt/core/client/JsArray;)(iface, method, arguments);
- });
- },
- 'getCallback': function(name) {
- return $entry(function() {
- var args = [name, Array.prototype.slice.call(arguments, 0)];
- var iface = "com.vaadin.ui.JavascriptManager$JavascriptCallbackRpc";
- var method = "call";
- h.@com.vaadin.terminal.gwt.client.JavascriptConnectorHelper::fireRpc(Ljava/lang/String;Ljava/lang/String;Lcom/google/gwt/core/client/JsArray;)(iface, method, args);
- });
- },
- 'registerCallback': function(name, callback) {
- //TODO maintain separate map
- if (!registeredRpc[name]) {
- registeredRpc[name] = [];
- }
- registeredRpc[name].push(callback);
- },
- 'registerRpc': function(iface, rpcHandler) {
- if (!registeredRpc[iface]) {
- registeredRpc[iface] = [];
- }
- registeredRpc[iface].push(rpcHandler);
- },
- };
- }-*/;
-
- private void fireRpc(String iface, String method,
- JsArray<JavaScriptObject> arguments) {
- 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), true);
- }
-
- 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) {
- if ("com.vaadin.ui.JavascriptManager$JavascriptCallbackRpc"
- .equals(invocation.getInterfaceName())
- && "call".equals(invocation.getMethodName())) {
- invokeJsRpc(rpcMap, parametersJson.get(0).isString().stringValue(),
- null, parametersJson.get(1).isArray().getJavaScriptObject());
- } else {
- invokeJsRpc(rpcMap, invocation.getInterfaceName(),
- invocation.getMethodName(),
- parametersJson.getJavaScriptObject());
- }
- }
-
- 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];
- if (methodName === null && typeof target === 'function') {
- target.apply($wnd, parameters);
- } else {
- target[methodName].apply(target, parameters);
- }
- }
- }-*/;
-
-}
diff --git a/src/com/vaadin/terminal/gwt/client/JavascriptExtension.java b/src/com/vaadin/terminal/gwt/client/JavascriptExtension.java
deleted file mode 100644
index 6c098a52f6..0000000000
--- a/src/com/vaadin/terminal/gwt/client/JavascriptExtension.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client;
-
-import com.vaadin.terminal.AbstractJavascriptExtension;
-import com.vaadin.terminal.gwt.client.communication.HasJavascriptConnectorHelper;
-import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
-import com.vaadin.terminal.gwt.client.ui.AbstractConnector;
-import com.vaadin.terminal.gwt.client.ui.Connect;
-
-@Connect(AbstractJavascriptExtension.class)
-public class JavascriptExtension extends AbstractConnector implements
- HasJavascriptConnectorHelper {
- private final JavascriptConnectorHelper helper = new JavascriptConnectorHelper(
- this);
-
- @Override
- protected void init() {
- helper.init();
- }
-
- @Override
- public void onStateChanged(StateChangeEvent stateChangeEvent) {
- super.onStateChanged(stateChangeEvent);
- helper.fireNativeStateChange();
- }
-
- public JavascriptConnectorHelper getJavascriptConnectorHelper() {
- return helper;
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/client/Util.java b/src/com/vaadin/terminal/gwt/client/Util.java
index 87bf27fc27..d3cb54160d 100644
--- a/src/com/vaadin/terminal/gwt/client/Util.java
+++ b/src/com/vaadin/terminal/gwt/client/Util.java
@@ -911,6 +911,22 @@ public class Util {
}
/**
+ * 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.
diff --git a/src/com/vaadin/terminal/gwt/client/WidgetSet.java b/src/com/vaadin/terminal/gwt/client/WidgetSet.java
index ecbfb0ecc9..3d7e838c62 100644
--- a/src/com/vaadin/terminal/gwt/client/WidgetSet.java
+++ b/src/com/vaadin/terminal/gwt/client/WidgetSet.java
@@ -5,7 +5,7 @@
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.communication.HasJavaScriptConnectorHelper;
import com.vaadin.terminal.gwt.client.ui.UnknownComponentConnector;
public class WidgetSet {
@@ -54,8 +54,8 @@ public class WidgetSet {
* let the auto generated code instantiate this type
*/
ServerConnector connector = widgetMap.instantiate(classType);
- if (connector instanceof HasJavascriptConnectorHelper) {
- ((HasJavascriptConnectorHelper) connector)
+ if (connector instanceof HasJavaScriptConnectorHelper) {
+ ((HasJavaScriptConnectorHelper) connector)
.getJavascriptConnectorHelper().setTag(tag);
}
return connector;
diff --git a/src/com/vaadin/terminal/gwt/client/communication/HasJavaScriptConnectorHelper.java b/src/com/vaadin/terminal/gwt/client/communication/HasJavaScriptConnectorHelper.java
new file mode 100644
index 0000000000..a5191a5fed
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/communication/HasJavaScriptConnectorHelper.java
@@ -0,0 +1,11 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.communication;
+
+import com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper;
+
+public interface HasJavaScriptConnectorHelper {
+ public JavaScriptConnectorHelper getJavascriptConnectorHelper();
+}
diff --git a/src/com/vaadin/terminal/gwt/client/communication/HasJavascriptConnectorHelper.java b/src/com/vaadin/terminal/gwt/client/communication/HasJavascriptConnectorHelper.java
deleted file mode 100644
index 74bc75da66..0000000000
--- a/src/com/vaadin/terminal/gwt/client/communication/HasJavascriptConnectorHelper.java
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.communication;
-
-import com.vaadin.terminal.gwt.client.JavascriptConnectorHelper;
-
-public interface HasJavascriptConnectorHelper {
- public JavascriptConnectorHelper getJavascriptConnectorHelper();
-}
diff --git a/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java b/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java
index e0ffb40125..07d6292ce2 100644
--- a/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java
+++ b/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java
@@ -89,8 +89,8 @@ public class RpcManager {
MethodInvocation invocation = new MethodInvocation(connectorId,
interfaceName, methodName);
- if (connector instanceof HasJavascriptConnectorHelper) {
- ((HasJavascriptConnectorHelper) connector)
+ if (connector instanceof HasJavaScriptConnectorHelper) {
+ ((HasJavaScriptConnectorHelper) connector)
.getJavascriptConnectorHelper().invokeJsRpc(invocation,
parametersJson);
} else {
diff --git a/src/com/vaadin/terminal/gwt/client/extensions/AbstractExtensionConnector.java b/src/com/vaadin/terminal/gwt/client/extensions/AbstractExtensionConnector.java
new file mode 100644
index 0000000000..bcefcf05cb
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/extensions/AbstractExtensionConnector.java
@@ -0,0 +1,27 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+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 {
+ @Override
+ public void setParent(ServerConnector parent) {
+ ServerConnector oldParent = getParent();
+ if (oldParent != null && oldParent != parent) {
+ throw new IllegalStateException(
+ "An extension can not be moved from one parent to another.");
+ }
+
+ super.setParent(parent);
+
+ extend(parent);
+ }
+
+ protected void extend(ServerConnector target) {
+ // Default does nothing
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/ExecuteJavaScriptRpc.java b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/ExecuteJavaScriptRpc.java
new file mode 100644
index 0000000000..f1185586d5
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/ExecuteJavaScriptRpc.java
@@ -0,0 +1,11 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.extensions.javascriptmanager;
+
+import com.vaadin.terminal.gwt.client.communication.ClientRpc;
+
+public interface ExecuteJavaScriptRpc extends ClientRpc {
+ public void executeJavaScript(String script);
+}
diff --git a/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerConnector.java b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerConnector.java
new file mode 100644
index 0000000000..8656783a86
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerConnector.java
@@ -0,0 +1,119 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+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.terminal.gwt.client.communication.MethodInvocation;
+import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
+import com.vaadin.terminal.gwt.client.extensions.AbstractExtensionConnector;
+import com.vaadin.terminal.gwt.client.ui.Connect;
+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() {
+ 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), true);
+ }
+
+ @Override
+ public JavaScriptManagerState getState() {
+ return (JavaScriptManagerState) super.getState();
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavascriptManagerState.java b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerState.java
index 77794ffdca..fc246aff04 100644
--- a/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavascriptManagerState.java
+++ b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerState.java
@@ -9,7 +9,7 @@ import java.util.Set;
import com.vaadin.terminal.gwt.client.communication.SharedState;
-public class JavascriptManagerState extends SharedState {
+public class JavaScriptManagerState extends SharedState {
private Set<String> names = new HashSet<String>();
public Set<String> getNames() {
diff --git a/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavascriptManagerConnector.java b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavascriptManagerConnector.java
deleted file mode 100644
index 979a6d22c4..0000000000
--- a/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavascriptManagerConnector.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-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.terminal.gwt.client.communication.MethodInvocation;
-import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
-import com.vaadin.terminal.gwt.client.ui.AbstractConnector;
-import com.vaadin.terminal.gwt.client.ui.Connect;
-import com.vaadin.ui.JavascriptManager;
-
-@Connect(JavascriptManager.class)
-public class JavascriptManagerConnector extends AbstractConnector {
- private Set<String> currentNames = new HashSet<String>();
-
- @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;
- $wnd[name] = $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
- private native void removeCallback(String name)
- /*-{
- delete $wnd[name];
- }-*/;
-
- 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.JavascriptManager$JavascriptCallbackRpc",
- "call", parameters), true);
- }
-
- @Override
- public JavascriptManagerState getState() {
- return (JavascriptManagerState) super.getState();
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/AbstractClickEventHandler.java b/src/com/vaadin/terminal/gwt/client/ui/AbstractClickEventHandler.java
index 31204aa0c6..e0ca798682 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/AbstractClickEventHandler.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/AbstractClickEventHandler.java
@@ -3,29 +3,76 @@
*/
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 DoubleClickHandler,
- ContextMenuHandler, MouseUpHandler {
+public abstract class AbstractClickEventHandler implements MouseDownHandler,
+ MouseUpHandler, DoubleClickHandler, ContextMenuHandler {
- private HandlerRegistration doubleClickHandlerRegistration;
+ 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() {
+
+ 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;
@@ -36,25 +83,28 @@ public abstract class AbstractClickEventHandler implements DoubleClickHandler,
// Handle registering/unregistering of click handler depending on if
// server side listeners have been added or removed.
if (hasEventListener()) {
- if (mouseUpHandlerRegistration == null) {
+ if (mouseDownHandlerRegistration == null) {
+ mouseDownHandlerRegistration = registerHandler(this,
+ MouseDownEvent.getType());
mouseUpHandlerRegistration = registerHandler(this,
MouseUpEvent.getType());
- contextMenuHandlerRegistration = registerHandler(this,
- ContextMenuEvent.getType());
doubleClickHandlerRegistration = registerHandler(this,
DoubleClickEvent.getType());
+ contextMenuHandlerRegistration = registerHandler(this,
+ ContextMenuEvent.getType());
}
} else {
- if (mouseUpHandlerRegistration != null) {
+ if (mouseDownHandlerRegistration != null) {
// Remove existing handlers
- doubleClickHandlerRegistration.removeHandler();
+ mouseDownHandlerRegistration.removeHandler();
mouseUpHandlerRegistration.removeHandler();
+ doubleClickHandlerRegistration.removeHandler();
contextMenuHandlerRegistration.removeHandler();
- contextMenuHandlerRegistration = null;
+ mouseDownHandlerRegistration = null;
mouseUpHandlerRegistration = null;
doubleClickHandlerRegistration = null;
-
+ contextMenuHandlerRegistration = null;
}
}
@@ -93,6 +143,7 @@ public abstract class AbstractClickEventHandler implements DoubleClickHandler,
* Event handler for context menu. Prevents the browser context menu from
* popping up if there is a listener for right clicks.
*/
+
public void onContextMenu(ContextMenuEvent event) {
if (hasEventListener() && shouldFireEvent(event)) {
// Prevent showing the browser's context menu when there is a right
@@ -101,18 +152,34 @@ public abstract class AbstractClickEventHandler implements DoubleClickHandler,
}
}
- /**
- * Event handler for mouse up. This is used to detect all single click
- * events.
- */
+ 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);
+ }
+
public void onMouseUp(MouseUpEvent event) {
- // TODO For perfect accuracy we should check that a mousedown has
- // occured on this element before this mouseup and that no mouseup
- // has occured anywhere after that.
- if (hasEventListener() && shouldFireEvent(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;
}
/**
@@ -140,6 +207,7 @@ public abstract class AbstractClickEventHandler implements DoubleClickHandler,
* 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.
*/
+
public void onDoubleClick(DoubleClickEvent event) {
if (hasEventListener() && shouldFireEvent(event)) {
fireClick(event.getNativeEvent());
diff --git a/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java b/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java
index 67dbd2d9d9..f0b9d518ca 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java
@@ -131,7 +131,22 @@ public abstract class AbstractComponentConnector extends AbstractConnector
public void setWidgetEnabled(boolean widgetEnabled) {
if (getWidget() instanceof HasEnabled) {
+ // set widget specific enabled state
((HasEnabled) getWidget()).setEnabled(widgetEnabled);
+ // add or remove v-disabled style name from the widget
+ getWidget().setStyleName(ApplicationConnection.DISABLED_CLASSNAME,
+ !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 RootConnector)) {
+ VConsole.error("Parent of connector "
+ + Util.getConnectorString(this)
+ + " is null. This is typically an indication of a broken component hierarchy");
+ }
+ }
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java b/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java
index cffdb1e68a..758f798ef2 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java
@@ -28,6 +28,7 @@ public abstract class ClickEventHandler extends AbstractClickEventHandler {
* @param event
* The native event that caused this click event
*/
+ @Override
protected void fireClick(NativeEvent event) {
MouseEventDetails mouseDetails = MouseEventDetailsBuilder
.buildMouseEventDetails(event, getRelativeToElement());
diff --git a/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java b/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java
index 62697c4d98..ef1ea8521b 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java
@@ -34,8 +34,8 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements
public FocusableScrollPanel() {
// Prevent IE standard mode bug when a AbsolutePanel is contained.
+ TouchScrollDelegate.enableTouchScrolling(this, getElement());
Style style = getElement().getStyle();
- style.setOverflow(Overflow.AUTO);
style.setProperty("zoom", "1");
style.setPosition(Position.RELATIVE);
}
@@ -153,7 +153,8 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements
* the new vertical scroll position, in pixels
*/
public void setScrollPosition(int position) {
- if (BrowserInfo.get().isAndroidWithBrokenScrollTop()) {
+ 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) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java
new file mode 100644
index 0000000000..bb062a6677
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java
@@ -0,0 +1,42 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui;
+
+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();
+ }
+
+ public JavaScriptConnectorHelper getJavascriptConnectorHelper() {
+ return helper;
+ }
+
+ @Override
+ public JavaScriptComponentState getState() {
+ return (JavaScriptComponentState) super.getState();
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentState.java b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentState.java
new file mode 100644
index 0000000000..6728f85ec9
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentState.java
@@ -0,0 +1,37 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import com.vaadin.terminal.gwt.client.ComponentState;
+import com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper.JavaScriptConnectorState;
+
+public class JavaScriptComponentState extends ComponentState implements
+ JavaScriptConnectorState {
+
+ private Set<String> callbackNames = new HashSet<String>();
+ private Map<String, Set<String>> rpcInterfaces = new HashMap<String, Set<String>>();
+
+ public Set<String> getCallbackNames() {
+ return callbackNames;
+ }
+
+ public void setCallbackNames(Set<String> callbackNames) {
+ this.callbackNames = callbackNames;
+ }
+
+ public Map<String, Set<String>> getRpcInterfaces() {
+ return rpcInterfaces;
+ }
+
+ public void setRpcInterfaces(Map<String, Set<String>> rpcInterfaces) {
+ this.rpcInterfaces = rpcInterfaces;
+ }
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/JavascriptWidget.java b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptWidget.java
index 93a4417b1c..e6c3323893 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/JavascriptWidget.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptWidget.java
@@ -8,13 +8,13 @@ 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() {
+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>";
+ 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>";
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/JavascriptComponentConnector.java b/src/com/vaadin/terminal/gwt/client/ui/JavascriptComponentConnector.java
deleted file mode 100644
index 57e65e91c6..0000000000
--- a/src/com/vaadin/terminal/gwt/client/ui/JavascriptComponentConnector.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client.ui;
-
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.user.client.Element;
-import com.vaadin.terminal.gwt.client.JavascriptConnectorHelper;
-import com.vaadin.terminal.gwt.client.communication.HasJavascriptConnectorHelper;
-import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
-import com.vaadin.ui.AbstractJavascriptComponent;
-
-@Connect(AbstractJavascriptComponent.class)
-public 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
- protected JavaScriptObject createConnectorWrapper() {
- JavaScriptObject connectorWrapper = super.createConnectorWrapper();
- addGetWidgetElement(connectorWrapper, getWidget().getElement());
- return connectorWrapper;
- }
- };
-
- @Override
- protected void init() {
- helper.init();
- }
-
- @Override
- public void onStateChanged(StateChangeEvent stateChangeEvent) {
- super.onStateChanged(stateChangeEvent);
- helper.fireNativeStateChange();
- }
-
- private static native void addGetWidgetElement(
- JavaScriptObject connectorWrapper, Element element)
- /*-{
- connectorWrapper.getWidgetElement = function() {
- return element;
- };
- }-*/;
-
- @Override
- public JavascriptWidget getWidget() {
- return (JavascriptWidget) super.getWidget();
- }
-
- public JavascriptConnectorHelper getJavascriptConnectorHelper() {
- return helper;
- }
-}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java
index 8b2248aff6..7302f9f2ac 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java
@@ -4,6 +4,8 @@
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;
@@ -15,10 +17,12 @@ 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;
@@ -68,7 +72,7 @@ public class TouchScrollDelegate implements NativePreviewHandler {
private static final double DECELERATION = 0.002;
private static final int MAX_DURATION = 1500;
private int origY;
- private Element[] scrollableElements;
+ private HashSet<Element> scrollableElements;
private Element scrolledElement;
private int origScrollTop;
private HandlerRegistration handlerRegistration;
@@ -86,8 +90,107 @@ public class TouchScrollDelegate implements NativePreviewHandler {
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);
+ }
+
+ 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) {
- scrollableElements = elements;
+ setElements(elements);
}
public void setScrollHandler(ScrollHandler scrollHandler) {
@@ -535,8 +638,8 @@ public class TouchScrollDelegate implements NativePreviewHandler {
}
}
- public void setElements(com.google.gwt.user.client.Element[] elements) {
- scrollableElements = elements;
+ public void setElements(Element[] elements) {
+ scrollableElements = new HashSet<Element>(Arrays.asList(elements));
}
/**
diff --git a/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java b/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java
index dcd520bbb3..b83d5afb00 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java
@@ -20,6 +20,8 @@ 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.TabsheetBaseConnector;
import com.vaadin.terminal.gwt.client.ui.tabsheet.VTabsheetBase;
@@ -35,8 +37,11 @@ public class VAccordion extends VTabsheetBase {
int selectedUIDLItemIndex = -1;
+ private final TouchScrollHandler touchScrollHandler;
+
public VAccordion() {
super(CLASSNAME);
+ touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this);
}
@Override
@@ -145,7 +150,6 @@ public class VAccordion extends VTabsheetBase {
}
}
}
-
if (!alreadyOpen) {
item.open();
activeTabIndex = itemIndex;
@@ -342,11 +346,13 @@ public class VAccordion extends VTabsheetBase {
DOM.appendChild(captionNode, caption.getElement());
DOM.appendChild(getElement(), captionNode);
DOM.appendChild(getElement(), content);
- setStyleName(CLASSNAME + "-item");
- DOM.setElementProperty(content, "className", CLASSNAME
- + "-item-content");
- DOM.setElementProperty(captionNode, "className", CLASSNAME
- + "-item-caption");
+
+ getElement().addClassName(CLASSNAME + "-item");
+ captionNode.addClassName(CLASSNAME + "-item-caption");
+ content.addClassName(CLASSNAME + "-item-content");
+
+ touchScrollHandler.addElement(getContainerElement());
+
close();
}
@@ -488,6 +494,7 @@ public class VAccordion extends VTabsheetBase {
protected void removeTab(int index) {
StackItem item = getStackItem(index);
remove(item);
+ touchScrollHandler.removeElement(item.getContainerElement());
}
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java b/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java
index e5e7dbba8b..0cd8bc54f4 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java
@@ -10,6 +10,7 @@ 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;
@@ -61,7 +62,9 @@ public class VButton extends FocusWidget implements ClickHandler {
private boolean isCapturing;
/**
- * If <code>true</code>, this widget has focus with the space bar down.
+ * 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;
@@ -74,6 +77,14 @@ public class VButton extends FocusWidget implements ClickHandler {
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);
@@ -229,37 +240,28 @@ public class VButton extends FocusWidget implements ClickHandler {
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;
-
- /*
- * If click shortcut is space then the shortcut handler will
- * take care of the click.
- */
- if (clickShortcut != 32 /* space */) {
- onClick();
- }
-
+ onClick();
+ event.stopPropagation();
event.preventDefault();
}
break;
case Event.ONKEYPRESS:
if (event.getKeyCode() == KeyCodes.KEY_ENTER) {
-
- /*
- * If click shortcut is enter then the shortcut handler will
- * take care of the click.
- */
- if (clickShortcut != KeyCodes.KEY_ENTER) {
- onClick();
- }
-
+ onClick();
+ event.stopPropagation();
event.preventDefault();
}
break;
@@ -336,12 +338,10 @@ public class VButton extends FocusWidget implements ClickHandler {
Accessibility.removeState(getElement(),
Accessibility.STATE_PRESSED);
super.setTabIndex(-1);
- addStyleName(ApplicationConnection.DISABLED_CLASSNAME);
} else {
Accessibility.setState(getElement(),
Accessibility.STATE_PRESSED, "false");
super.setTabIndex(tabIndex);
- removeStyleName(ApplicationConnection.DISABLED_CLASSNAME);
}
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java b/src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java
index d29eda0d6a..8c5d521445 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java
@@ -69,7 +69,8 @@ import com.vaadin.terminal.gwt.client.ui.menubar.MenuItem;
*/
@SuppressWarnings("deprecation")
public class VFilterSelect extends Composite implements Field, KeyDownHandler,
- KeyUpHandler, ClickHandler, FocusHandler, BlurHandler, Focusable {
+ KeyUpHandler, ClickHandler, FocusHandler, BlurHandler, Focusable,
+ SubPartAware {
/**
* Represents a suggestion in the suggestion popup box
@@ -100,6 +101,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* contains an image tag with the rows icon (if an icon has been
* specified) and the caption of the item
*/
+
public String getDisplayString() {
final StringBuffer sb = new StringBuffer();
if (iconUri != null) {
@@ -122,6 +124,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
/**
* Get a string that represents this item. This is used in the text box.
*/
+
public String getReplacementString() {
return caption;
}
@@ -147,6 +150,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
/**
* Executes a selection of this item.
*/
+
public void execute() {
onSuggestionSelected(this);
}
@@ -392,6 +396,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* 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) {
@@ -449,6 +454,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* com.google.gwt.user.client.ui.PopupPanel$PositionCallback#setPosition
* (int, int)
*/
+
public void setPosition(int offsetWidth, int offsetHeight) {
int top = -1;
@@ -541,6 +547,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* 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()) {
@@ -824,6 +831,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* com.google.gwt.user.client.ui.TextBoxBase#onBrowserEvent(com.google
* .gwt.user.client.Event)
*/
+
@Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
@@ -832,8 +840,8 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
}
}
- @Override
// Overridden to avoid selecting text when text input is disabled
+ @Override
public void setSelectionRange(int pos, int length) {
if (textInputEnabled) {
super.setSelectionRange(pos, length);
@@ -857,6 +865,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt
* .user.client.Event)
*/
+
@Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
@@ -951,6 +960,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
public VFilterSelect() {
selectedItemIcon.setStyleName("v-icon");
selectedItemIcon.addLoadHandler(new LoadHandler() {
+
public void onLoad(LoadEvent event) {
if (BrowserInfo.get().isIE8()) {
// IE8 needs some help to discover it should reposition the
@@ -1203,6 +1213,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt
* .event.dom.client.KeyDownEvent)
*/
+
public void onKeyDown(KeyDownEvent event) {
if (enabled && !readonly) {
int keyCode = event.getNativeKeyCode();
@@ -1364,6 +1375,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* @param event
* The KeyUpEvent of the key depressed
*/
+
public void onKeyUp(KeyUpEvent event) {
if (enabled && !readonly) {
switch (event.getNativeKeyCode()) {
@@ -1411,6 +1423,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
/**
* Listener for popupopener
*/
+
public void onClick(ClickEvent event) {
if (textInputEnabled
&& event.getNativeEvent().getEventTarget().cast() == tb
@@ -1474,6 +1487,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event
* .dom.client.FocusEvent)
*/
+
public void onFocus(FocusEvent event) {
/*
@@ -1567,6 +1581,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
*
* @see com.vaadin.terminal.gwt.client.Focusable#focus()
*/
+
public void focus() {
focused = true;
if (prompting && !readonly) {
@@ -1674,4 +1689,22 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
super.onDetach();
suggestionPopup.hide();
}
+
+ public Element getSubPartElement(String subPart) {
+ if ("textbox".equals(subPart)) {
+ return this.tb.getElement();
+ } else if ("button".equals(subPart)) {
+ return this.popupOpener.getElement();
+ }
+ return null;
+ }
+
+ 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/src/com/vaadin/terminal/gwt/client/ui/dd/AcceptCriterion.java b/src/com/vaadin/terminal/gwt/client/ui/dd/AcceptCriterion.java
new file mode 100644
index 0000000000..32dac10170
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/AcceptCriterion.java
@@ -0,0 +1,33 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui.dd;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation type used to point the server side counterpart for client side
+ * a {@link VAcceptCriterion} class.
+ * <p>
+ * Annotations are used at GWT compilation phase, so remember to rebuild your
+ * widgetset if you do changes for {@link AcceptCriterion} mappings.
+ *
+ * Prior to Vaadin 7, the mapping was done with an annotation on server side
+ * classes.
+ *
+ * @since 7.0
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface AcceptCriterion {
+ /**
+ * @return the fully qualified class name of the server side counterpart for
+ * the annotated criterion
+ */
+ String value();
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java b/src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java
index 02c1fe5061..97f5eb86fd 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java
@@ -5,6 +5,7 @@ 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.terminal.gwt.client.Util;
public class DDUtil {
@@ -43,8 +44,11 @@ public class DDUtil {
public static VerticalDropLocation getVerticalDropLocation(Element element,
int offsetHeight, int clientY, double topBottomRatio) {
- int absoluteTop = element.getAbsoluteTop();
- int fromTop = clientY - absoluteTop;
+ // 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) {
@@ -74,14 +78,17 @@ public class DDUtil {
public static HorizontalDropLocation getHorizontalDropLocation(
Element element, int clientX, double leftRightRatio) {
- int absoluteLeft = element.getAbsoluteLeft();
+ // 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 fromTop = clientX - absoluteLeft;
+ int fromLeft = clientX - elementLeft;
- float percentageFromTop = (fromTop / (float) offsetWidth);
- if (percentageFromTop < leftRightRatio) {
+ float percentageFromLeft = (fromLeft / (float) offsetWidth);
+ if (percentageFromLeft < leftRightRatio) {
return HorizontalDropLocation.LEFT;
- } else if (percentageFromTop > 1 - leftRightRatio) {
+ } else if (percentageFromLeft > 1 - leftRightRatio) {
return HorizontalDropLocation.RIGHT;
} else {
return HorizontalDropLocation.CENTER;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptAll.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptAll.java
index 51782c002d..07e931fb02 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptAll.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptAll.java
@@ -8,6 +8,7 @@ package com.vaadin.terminal.gwt.client.ui.dd;
import com.vaadin.terminal.gwt.client.UIDL;
+@AcceptCriterion("com.vaadin.event.dd.acceptcriteria.AcceptAll")
final public class VAcceptAll extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VAnd.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VAnd.java
index 65c67e6b8a..727c30075c 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VAnd.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VAnd.java
@@ -8,6 +8,7 @@ package com.vaadin.terminal.gwt.client.ui.dd;
import com.vaadin.terminal.gwt.client.UIDL;
+@AcceptCriterion("com.vaadin.event.dd.acceptcriteria.And")
final public class VAnd extends VAcceptCriterion implements VAcceptCallback {
private boolean b1;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VContainsDataFlavor.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VContainsDataFlavor.java
index 4a95034d4a..5786068174 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VContainsDataFlavor.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VContainsDataFlavor.java
@@ -8,6 +8,7 @@ package com.vaadin.terminal.gwt.client.ui.dd;
import com.vaadin.terminal.gwt.client.UIDL;
+@AcceptCriterion("com.vaadin.event.dd.acceptcriteria.ContainsDataFlavor")
final public class VContainsDataFlavor extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VDragSourceIs.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VDragSourceIs.java
index aabbf58b24..58550af918 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VDragSourceIs.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VDragSourceIs.java
@@ -12,6 +12,7 @@ import com.vaadin.terminal.gwt.client.UIDL;
*
* @since 6.3
*/
+@AcceptCriterion("com.vaadin.event.dd.acceptcriteria.SourceIs")
final public class VDragSourceIs extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VIsOverId.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VIsOverId.java
index 90e2b033c9..3fc54e6fd3 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VIsOverId.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VIsOverId.java
@@ -10,6 +10,7 @@ import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.ConnectorMap;
import com.vaadin.terminal.gwt.client.UIDL;
+@AcceptCriterion("com.vaadin.ui.AbstractSelect.TargetItemIs")
final public class VIsOverId extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VItemIdIs.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VItemIdIs.java
index eb55c1a91c..5f1fe978b5 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VItemIdIs.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VItemIdIs.java
@@ -9,6 +9,7 @@ package com.vaadin.terminal.gwt.client.ui.dd;
import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.UIDL;
+@AcceptCriterion("com.vaadin.ui.AbstractSelect.AcceptItem")
final public class VItemIdIs extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VLazyInitItemIdentifiers.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VLazyInitItemIdentifiers.java
index b824c1cb65..e972371b9f 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VLazyInitItemIdentifiers.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VLazyInitItemIdentifiers.java
@@ -13,11 +13,23 @@ import com.vaadin.terminal.gwt.client.UIDL;
/**
*
*/
-final public class VLazyInitItemIdentifiers extends VAcceptCriterion {
+public class VLazyInitItemIdentifiers extends VAcceptCriterion {
private boolean loaded = false;
private HashSet<String> hashSet;
private VDragEvent lastDragEvent;
+ @AcceptCriterion("com.vaadin.ui.Table.TableDropCriterion")
+ final public static class VTableLazyInitItemIdentifiers extends
+ VLazyInitItemIdentifiers {
+ // all logic in superclass
+ }
+
+ @AcceptCriterion("com.vaadin.ui.Tree.TreeDropCriterion")
+ final public static class VTreeLazyInitItemIdentifiers extends
+ VLazyInitItemIdentifiers {
+ // all logic in superclass
+ }
+
@Override
public void accept(final VDragEvent drag, UIDL configuration,
final VAcceptCallback callback) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VNot.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VNot.java
index f4ba868497..e91ad6149a 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VNot.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VNot.java
@@ -13,6 +13,7 @@ import com.vaadin.terminal.gwt.client.VConsole;
* TODO implementation could now be simplified/optimized
*
*/
+@AcceptCriterion("com.vaadin.event.dd.acceptcriteria.Not")
final public class VNot extends VAcceptCriterion {
private boolean b1;
private VAcceptCriterion crit1;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VOr.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VOr.java
index e47447b7fc..3664326568 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VOr.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VOr.java
@@ -11,6 +11,7 @@ import com.vaadin.terminal.gwt.client.UIDL;
/**
*
*/
+@AcceptCriterion("com.vaadin.event.dd.acceptcriteria.Or")
final public class VOr extends VAcceptCriterion implements VAcceptCallback {
private boolean accepted;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VServerAccept.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VServerAccept.java
index bccb6656aa..e679b64369 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VServerAccept.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VServerAccept.java
@@ -8,6 +8,7 @@ package com.vaadin.terminal.gwt.client.ui.dd;
import com.vaadin.terminal.gwt.client.UIDL;
+@AcceptCriterion("com.vaadin.event.dd.acceptcriteria.ServerSideCriterion")
final public class VServerAccept extends VAcceptCriterion {
@Override
public void accept(final VDragEvent drag, UIDL configuration,
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VSourceIsTarget.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VSourceIsTarget.java
index 430b422b34..9bbabe9d29 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VSourceIsTarget.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VSourceIsTarget.java
@@ -9,6 +9,7 @@ package com.vaadin.terminal.gwt.client.ui.dd;
import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.UIDL;
+@AcceptCriterion("com.vaadin.event.dd.acceptcriteria.SourceIsTarget")
final public class VSourceIsTarget extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetDetailIs.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetDetailIs.java
index 713a0d6646..7d92359f7d 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetDetailIs.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetDetailIs.java
@@ -8,6 +8,7 @@ package com.vaadin.terminal.gwt.client.ui.dd;
import com.vaadin.terminal.gwt.client.UIDL;
+@AcceptCriterion("com.vaadin.event.dd.acceptcriteria.TargetDetailIs")
final public class VTargetDetailIs extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetInSubtree.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetInSubtree.java
index f69fa85290..3db44f3162 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetInSubtree.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetInSubtree.java
@@ -11,6 +11,7 @@ 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;
+@AcceptCriterion("com.vaadin.ui.Tree.TargetInSubtree")
final public class VTargetInSubtree extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java b/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java
index 57f6835bcc..2a78cc4433 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java
@@ -57,6 +57,9 @@ public class DragAndDropWrapperConnector extends CustomComponentConnector
getWidget().initDragStartMode();
getWidget().html5DataFlavors = uidl
.getMapAttribute(VDragAndDropWrapper.HTML5_DATA_FLAVORS);
+
+ // Used to prevent wrapper from stealing tooltips when not defined
+ getWidget().hasTooltip = getState().hasDescription();
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java b/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java
index d09b81e1e1..4c36e92bbb 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java
@@ -60,6 +60,8 @@ public class VDragAndDropWrapper extends VCustomComponent implements
private static final String CLASSNAME = "v-ddwrapper";
protected static final String DRAGGABLE = "draggable";
+ boolean hasTooltip = false;
+
public VDragAndDropWrapper() {
super();
sinkEvents(VTooltip.TOOLTIP_EVENTS);
@@ -67,6 +69,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
hookHtml5Events(getElement());
setStyleName(CLASSNAME);
addDomHandler(new MouseDownHandler() {
+
public void onMouseDown(MouseDownEvent event) {
if (startDrag(event.getNativeEvent())) {
event.preventDefault(); // prevent text selection
@@ -75,6 +78,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
}, MouseDownEvent.getType());
addDomHandler(new TouchStartHandler() {
+
public void onTouchStart(TouchStartEvent event) {
if (startDrag(event.getNativeEvent())) {
/*
@@ -92,7 +96,8 @@ public class VDragAndDropWrapper extends VCustomComponent implements
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
- if (client != null) {
+ if (hasTooltip && client != null) {
+ // Override child tooltips if the wrapper has a tooltip defined
client.handleTooltipEvent(event, this);
}
}
@@ -172,6 +177,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
private boolean uploading;
private ReadyStateChangeHandler readyStateChangeHandler = new ReadyStateChangeHandler() {
+
public void onReadyStateChange(XMLHttpRequest xhr) {
if (xhr.getReadyState() == XMLHttpRequest.DONE) {
// visit server for possible
@@ -269,6 +275,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
try {
dragleavetimer = new Timer() {
+
@Override
public void run() {
// Yes, dragleave happens before drop. Makes no sense to me.
@@ -455,6 +462,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
if (detailsChanged) {
currentlyValid = false;
validate(new VAcceptCallback() {
+
public void accepted(VDragEvent event) {
dragAccepted(drag);
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/form/VForm.java b/src/com/vaadin/terminal/gwt/client/ui/form/VForm.java
index e3a0c9b321..81f24a8e7e 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/form/VForm.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/form/VForm.java
@@ -4,7 +4,6 @@
package com.vaadin.terminal.gwt.client.ui.form;
-import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.shared.HandlerRegistration;
@@ -27,7 +26,6 @@ public class VForm extends ComplexPanel implements KeyDownHandler {
Widget lo;
Element legend = DOM.createLegend();
Element caption = DOM.createSpan();
- private Element errorIndicatorElement = DOM.createDiv();
Element desc = DOM.createDiv();
Icon icon;
VErrorMessage errorMessage = new VErrorMessage();
@@ -52,9 +50,6 @@ public class VForm extends ComplexPanel implements KeyDownHandler {
setStyleName(CLASSNAME);
fieldSet.appendChild(legend);
legend.appendChild(caption);
- errorIndicatorElement.setClassName("v-errorindicator");
- errorIndicatorElement.getStyle().setDisplay(Display.NONE);
- errorIndicatorElement.setInnerText(" "); // needed for IE
desc.setClassName("v-form-description");
fieldSet.appendChild(desc); // Adding description for initial padding
// measurements, removed later if no
diff --git a/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java b/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java
index 01ac4fab6a..dd6e741126 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java
@@ -127,11 +127,4 @@ public class VNativeButton extends Button implements ClickHandler {
clickPending = false;
}
- @Override
- public void setEnabled(boolean enabled) {
- if (isEnabled() != enabled) {
- super.setEnabled(enabled);
- setStyleName(ApplicationConnection.DISABLED_CLASSNAME, !enabled);
- }
- }
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java b/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java
index 0d222044ba..fb853b8a55 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java
@@ -43,6 +43,8 @@ public class VNotification extends VOverlay {
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;
@@ -159,6 +161,7 @@ public class VNotification extends VOverlay {
addStyleDependentName(style);
}
super.show();
+ notifications.add(this);
setPosition(position);
/**
* Android 4 fails to render notifications correctly without a little
@@ -180,6 +183,7 @@ public class VNotification extends VOverlay {
temporaryStyle = null;
}
super.hide();
+ notifications.remove(this);
fireEvent(new HideEvent(this));
}
@@ -435,4 +439,19 @@ public class VNotification extends VOverlay {
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/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java b/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java
index 5b97fc110f..d9096526f3 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java
@@ -111,6 +111,8 @@ public class PanelConnector extends AbstractComponentContainerConnector
getWidget().captionNode.setClassName(captionClass);
getWidget().contentNode.setClassName(contentClass);
getWidget().bottomDecoration.setClassName(decoClass);
+
+ getWidget().makeScrollable();
}
if (!isRealUpdate(uidl)) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java b/src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java
index e2d3d443a0..6a06367acd 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java
@@ -6,8 +6,6 @@ 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.event.dom.client.TouchStartEvent;
-import com.google.gwt.event.dom.client.TouchStartHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
@@ -18,6 +16,7 @@ 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 {
@@ -46,7 +45,7 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner,
int scrollLeft;
- private TouchScrollDelegate touchScrollDelegate;
+ private TouchScrollHandler touchScrollHandler;
public VPanel() {
super();
@@ -74,11 +73,11 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner,
setStyleName(CLASSNAME);
DOM.sinkEvents(getElement(), Event.ONKEYDOWN);
DOM.sinkEvents(contentNode, Event.ONSCROLL | Event.TOUCHEVENTS);
- addHandler(new TouchStartHandler() {
- public void onTouchStart(TouchStartEvent event) {
- getTouchScrollDelegate().onTouchStart(event);
- }
- }, TouchStartEvent.getType());
+
+ contentNode.getStyle().setProperty("position", "relative");
+ getElement().getStyle().setProperty("overflow", "hidden");
+
+ makeScrollable();
}
/**
@@ -100,6 +99,7 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner,
*
* @see com.vaadin.terminal.gwt.client.Focusable#focus()
*/
+
public void focus() {
setFocus(true);
@@ -174,16 +174,17 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner,
}
}
- protected TouchScrollDelegate getTouchScrollDelegate() {
- if (touchScrollDelegate == null) {
- touchScrollDelegate = new TouchScrollDelegate(contentNode);
- }
- return touchScrollDelegate;
-
- }
-
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/src/com/vaadin/terminal/gwt/client/ui/root/PageClientRpc.java b/src/com/vaadin/terminal/gwt/client/ui/root/PageClientRpc.java
new file mode 100644
index 0000000000..a02ecc8ded
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/root/PageClientRpc.java
@@ -0,0 +1,13 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui.root;
+
+import com.vaadin.terminal.gwt.client.communication.ClientRpc;
+
+public interface PageClientRpc extends ClientRpc {
+
+ public void setTitle(String title);
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java b/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java
index 9be41a9623..1a62e566ad 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java
@@ -61,6 +61,11 @@ public class RootConnector extends AbstractComponentContainerConnector
@Override
protected void init() {
super.init();
+ registerRpc(PageClientRpc.class, new PageClientRpc() {
+ public void setTitle(String title) {
+ com.google.gwt.user.client.Window.setTitle(title);
+ }
+ });
}
public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) {
@@ -93,12 +98,9 @@ public class RootConnector extends AbstractComponentContainerConnector
}
getWidget().setStyleName(styles.trim());
- clickEventHandler.handleEventHandlerRegistration();
+ getWidget().makeScrollable();
- if (!getWidget().isEmbedded() && getState().getCaption() != null) {
- // only change window title if we're in charge of the whole page
- com.google.gwt.user.client.Window.setTitle(getState().getCaption());
- }
+ clickEventHandler.handleEventHandlerRegistration();
// Process children
int childIndex = 0;
@@ -168,9 +170,6 @@ public class RootConnector extends AbstractComponentContainerConnector
getWidget().id, client);
}
getWidget().actionHandler.updateActionMap(childUidl);
- } else if (tag == "execJS") {
- String script = childUidl.getStringAttribute("script");
- VRoot.eval(script);
} else if (tag == "notifications") {
for (final Iterator<?> it = childUidl.getChildIterator(); it
.hasNext();) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java b/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java
index 12a69d5556..0af8919280 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java
@@ -7,6 +7,7 @@ package com.vaadin.terminal.gwt.client.ui.root;
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.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
@@ -26,6 +27,8 @@ 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;
@@ -37,21 +40,36 @@ public class VRoot extends SimplePanel implements ResizeHandler,
public static final String FRAGMENT_VARIABLE = "fragment";
+ public static final String BROWSER_HEIGHT_VAR = "browserHeight";
+
+ public static final String BROWSER_WIDTH_VAR = "browserWidth";
+
private static final String CLASSNAME = "v-view";
public static final String NOTIFICATION_HTML_CONTENT_NOT_ALLOWED = "useplain";
+ private static int MONITOR_PARENT_TIMER_INTERVAL = 1000;
+
String theme;
String id;
ShortcutActionHandler actionHandler;
- /** stored width for IE resize optimization */
- private int width;
+ /*
+ * 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;
- /** stored height for IE resize optimization */
- private int height;
+ /*
+ * Last know view size used to detect whether new dimensions should be sent
+ * to the server.
+ */
+ private int viewWidth;
+ private int viewHeight;
ApplicationConnection connection;
@@ -59,13 +77,19 @@ public class VRoot extends SimplePanel implements ResizeHandler,
public static final String CLICK_EVENT_ID = "click";
/**
- * We are postponing resize process with IE. IE bugs with scrollbars in some
- * situations, that causes false onWindowResized calls. With Timer we will
- * give IE some time to decide if it really wants to keep current size
- * (scrollbars).
+ * 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;
@@ -85,6 +109,8 @@ public class VRoot extends SimplePanel implements ResizeHandler,
private HandlerRegistration historyHandlerRegistration;
+ private TouchScrollHandler touchScrollHandler;
+
/**
* The current URI fragment, used to avoid sending updates if nothing has
* changed.
@@ -96,6 +122,7 @@ public class VRoot extends SimplePanel implements ResizeHandler,
* whenever the value changes.
*/
private final ValueChangeHandler<String> historyChangeHandler = new ValueChangeHandler<String>() {
+
public void onValueChange(ValueChangeEvent<String> event) {
String newFragment = event.getValue();
@@ -110,9 +137,9 @@ public class VRoot extends SimplePanel implements ResizeHandler,
private VLazyExecutor delayedResizeExecutor = new VLazyExecutor(200,
new ScheduledCommand() {
+
public void execute() {
- windowSizeMaybeChanged(Window.getClientWidth(),
- Window.getClientHeight());
+ performSizeCheck();
}
});
@@ -124,6 +151,29 @@ public class VRoot extends SimplePanel implements ResizeHandler,
// 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
@@ -142,32 +192,95 @@ public class VRoot extends SimplePanel implements ResizeHandler,
}
/**
- * Called when the window might have been resized.
+ * 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.
*
- * @param newWidth
+ * 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 newHeight
+ * @param newWindowHeight
* The new height of the window
+ *
+ * @deprecated use {@link #performSizeCheck()}
*/
- protected void windowSizeMaybeChanged(int newWidth, int newHeight) {
+ @Deprecated
+ protected void windowSizeMaybeChanged(int newWindowWidth,
+ int newWindowHeight) {
boolean changed = false;
ComponentConnector connector = ConnectorMap.get(connection)
.getConnector(this);
- if (width != newWidth) {
- width = newWidth;
+ if (windowWidth != newWindowWidth) {
+ windowWidth = newWindowWidth;
changed = true;
- connector.getLayoutManager().reportOuterWidth(connector, newWidth);
- VConsole.log("New window width: " + width);
+ connector.getLayoutManager().reportOuterWidth(connector,
+ newWindowWidth);
+ VConsole.log("New window width: " + windowWidth);
}
- if (height != newHeight) {
- height = newHeight;
+ if (windowHeight != newWindowHeight) {
+ windowHeight = newWindowHeight;
changed = true;
- connector.getLayoutManager()
- .reportOuterHeight(connector, newHeight);
- VConsole.log("New window height: " + height);
+ 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) {
- VConsole.log("Running layout functions due to window resize");
+ /*
+ * 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();
@@ -188,21 +301,6 @@ public class VRoot extends SimplePanel implements ResizeHandler,
}-*/;
/**
- * Evaluate the given script in the browser document.
- *
- * @param script
- * Script to be executed.
- */
- static native void eval(String script)
- /*-{
- try {
- if (script == null) return;
- $wnd.eval(script);
- } catch (e) {
- }
- }-*/;
-
- /**
* 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.
@@ -214,6 +312,17 @@ public class VRoot extends SimplePanel implements ResizeHandler,
.contains(ApplicationConnection.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);
@@ -251,14 +360,19 @@ public class VRoot extends SimplePanel implements ResizeHandler,
* com.google.gwt.event.logical.shared.ResizeHandler#onResize(com.google
* .gwt.event.logical.shared.ResizeEvent)
*/
+
public void onResize(ResizeEvent event) {
- onResize();
+ 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.
*/
- void onResize() {
+ 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
@@ -274,8 +388,7 @@ public class VRoot extends SimplePanel implements ResizeHandler,
if (lazy) {
delayedResizeExecutor.trigger();
} else {
- windowSizeMaybeChanged(Window.getClientWidth(),
- Window.getClientHeight());
+ performSizeCheck();
}
}
@@ -283,8 +396,19 @@ public class VRoot extends SimplePanel implements ResizeHandler,
* Send new dimensions to the server.
*/
private void sendClientResized() {
- connection.updateVariable(id, "height", height, false);
- connection.updateVariable(id, "width", width, immediate);
+ Element parentElement = getElement().getParentElement();
+ int viewHeight = parentElement.getClientHeight();
+ int viewWidth = parentElement.getClientWidth();
+
+ connection.updateVariable(id, "height", viewHeight, false);
+ connection.updateVariable(id, "width", viewWidth, false);
+
+ int windowWidth = Window.getClientWidth();
+ int windowHeight = Window.getClientHeight();
+
+ connection.updateVariable(id, BROWSER_WIDTH_VAR, windowWidth, false);
+ connection.updateVariable(id, BROWSER_HEIGHT_VAR, windowHeight,
+ immediate);
}
public native static void goTo(String url)
@@ -319,4 +443,13 @@ public class VRoot extends SimplePanel implements ResizeHandler,
getElement().focus();
}
+ /**
+ * Ensures the root is scrollable eg. after style name changes.
+ */
+ void makeScrollable() {
+ if (touchScrollHandler == null) {
+ touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this);
+ }
+ touchScrollHandler.addElement(getElement());
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java b/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java
index 9ff614252d..5c7ee7a784 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java
@@ -18,6 +18,7 @@ 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.VTooltip;
import com.vaadin.terminal.gwt.client.ui.Field;
import com.vaadin.terminal.gwt.client.ui.SimpleFocusablePanel;
import com.vaadin.terminal.gwt.client.ui.VLazyExecutor;
@@ -51,6 +52,7 @@ public class VSlider extends SimpleFocusablePanel implements Field,
private final HTML feedback = new HTML("", false);
private final VOverlay feedbackPopup = new VOverlay(true, false, true) {
+
@Override
public void show() {
super.show();
@@ -112,6 +114,8 @@ public class VSlider extends SimpleFocusablePanel implements Field,
feedbackPopup.addStyleName(CLASSNAME + "-feedback");
feedbackPopup.setWidget(feedback);
+
+ sinkEvents(VTooltip.TOOLTIP_EVENTS);
}
void setFeedbackValue(double value) {
@@ -139,8 +143,12 @@ public class VSlider extends SimpleFocusablePanel implements Field,
void buildBase() {
final String styleAttribute = vertical ? "height" : "width";
+ final String oppositeStyleAttribute = vertical ? "width" : "height";
final String domProperty = vertical ? "offsetHeight" : "offsetWidth";
+ // clear unnecessary opposite style attribute
+ DOM.setStyleAttribute(base, oppositeStyleAttribute, "");
+
final Element p = DOM.getParent(getElement());
if (DOM.getElementPropertyInt(p, domProperty) > 50) {
if (vertical) {
@@ -153,6 +161,7 @@ public class VSlider extends SimpleFocusablePanel implements Field,
// (supposedly) been drawn completely.
DOM.setStyleAttribute(base, styleAttribute, MIN_SIZE + "px");
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
final Element p = DOM.getParent(getElement());
if (DOM.getElementPropertyInt(p, domProperty) > (MIN_SIZE + 5)) {
@@ -173,9 +182,14 @@ public class VSlider extends SimpleFocusablePanel implements Field,
void buildHandle() {
final String handleAttribute = vertical ? "marginTop" : "marginLeft";
+ final String oppositeHandleAttribute = vertical ? "marginLeft"
+ : "marginTop";
DOM.setStyleAttribute(handle, handleAttribute, "0");
+ // clear unnecessary opposite handle attribute
+ DOM.setStyleAttribute(handle, oppositeHandleAttribute, "");
+
// Restore visibility
DOM.setStyleAttribute(handle, "visibility", "visible");
@@ -277,6 +291,9 @@ public class VSlider extends SimpleFocusablePanel implements Field,
event.preventDefault(); // avoid simulated events
event.stopPropagation();
}
+ if (client != null) {
+ client.handleTooltipEvent(event, this);
+ }
}
private void processMouseWheelEvent(final Event event) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java
index 10e5dbe37a..e33755bc9b 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java
@@ -127,6 +127,12 @@ public abstract class AbstractSplitPanelConnector extends
getWidget().setStylenames();
+ getWidget().minimumPosition = splitterState.getMinPosition()
+ + splitterState.getMinPositionUnit();
+
+ getWidget().maximumPosition = splitterState.getMaxPosition()
+ + splitterState.getMaxPositionUnit();
+
getWidget().position = splitterState.getPosition()
+ splitterState.getPositionUnit();
@@ -136,6 +142,7 @@ public abstract class AbstractSplitPanelConnector extends
getLayoutManager().setNeedsLayout(this);
+ getWidget().makeScrollable();
}
public void layout() {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelState.java b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelState.java
index 8b80eed840..db3a39d3a5 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelState.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelState.java
@@ -49,6 +49,10 @@ public class AbstractSplitPanelState extends ComponentState {
public static class SplitterState implements Serializable {
private float position;
private String positionUnit;
+ private float minPosition;
+ private String minPositionUnit;
+ private float maxPosition;
+ private String maxPositionUnit;
private boolean positionReversed = false;
private boolean locked = false;
@@ -68,6 +72,38 @@ public class AbstractSplitPanelState extends ComponentState {
this.positionUnit = positionUnit;
}
+ public float getMinPosition() {
+ return minPosition;
+ }
+
+ public void setMinPosition(float minPosition) {
+ this.minPosition = minPosition;
+ }
+
+ public String getMinPositionUnit() {
+ return minPositionUnit;
+ }
+
+ public void setMinPositionUnit(String minPositionUnit) {
+ this.minPositionUnit = minPositionUnit;
+ }
+
+ public float getMaxPosition() {
+ return maxPosition;
+ }
+
+ public void setMaxPosition(float maxPosition) {
+ this.maxPosition = maxPosition;
+ }
+
+ public String getMaxPositionUnit() {
+ return maxPositionUnit;
+ }
+
+ public void setMaxPositionUnit(String maxPositionUnit) {
+ this.maxPositionUnit = maxPositionUnit;
+ }
+
public boolean isPositionReversed() {
return positionReversed;
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java
index 166e79e92e..e2f30c6676 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java
@@ -4,6 +4,7 @@
package com.vaadin.terminal.gwt.client.ui.splitpanel;
+import java.util.Collections;
import java.util.List;
import com.google.gwt.dom.client.Node;
@@ -31,6 +32,7 @@ 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;
@@ -76,7 +78,7 @@ public class VAbstractSplitPanel extends ComplexPanel {
private boolean positionReversed = false;
- List<String> componentStyleNames;
+ List<String> componentStyleNames = Collections.emptyList();
private Element draggingCurtain;
@@ -87,12 +89,16 @@ public class VAbstractSplitPanel extends ComplexPanel {
/* 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;
- private TouchScrollDelegate touchScrollDelegate;
-
public VAbstractSplitPanel() {
this(ORIENTATION_HORIZONTAL);
}
@@ -116,6 +122,8 @@ public class VAbstractSplitPanel extends ComplexPanel {
setOrientation(orientation);
sinkEvents(Event.MOUSEEVENTS);
+ makeScrollable();
+
addDomHandler(new TouchCancelHandler() {
public void onTouchCancel(TouchCancelEvent event) {
// TODO When does this actually happen??
@@ -127,11 +135,8 @@ public class VAbstractSplitPanel extends ComplexPanel {
Node target = event.getTouches().get(0).getTarget().cast();
if (splitter.isOrHasChild(target)) {
onMouseDown(Event.as(event.getNativeEvent()));
- } else {
- getTouchScrollDelegate().onTouchStart(event);
}
}
-
}, TouchStartEvent.getType());
addDomHandler(new TouchMoveHandler() {
public void onTouchMove(TouchMoveEvent event) {
@@ -150,14 +155,6 @@ public class VAbstractSplitPanel extends ComplexPanel {
}
- private TouchScrollDelegate getTouchScrollDelegate() {
- if (touchScrollDelegate == null) {
- touchScrollDelegate = new TouchScrollDelegate(firstContainer,
- secondContainer);
- }
- return touchScrollDelegate;
- }
-
protected void constructDom() {
DOM.appendChild(splitter, DOM.createDiv()); // for styling
DOM.appendChild(getElement(), wrapper);
@@ -172,9 +169,7 @@ public class VAbstractSplitPanel extends ComplexPanel {
DOM.setStyleAttribute(splitter, "position", "absolute");
DOM.setStyleAttribute(secondContainer, "position", "absolute");
- DOM.setStyleAttribute(firstContainer, "overflow", "auto");
- DOM.setStyleAttribute(secondContainer, "overflow", "auto");
-
+ setStylenames();
}
private void setOrientation(int orientation) {
@@ -190,11 +185,6 @@ public class VAbstractSplitPanel extends ComplexPanel {
DOM.setStyleAttribute(firstContainer, "width", "100%");
DOM.setStyleAttribute(secondContainer, "width", "100%");
}
-
- DOM.setElementProperty(firstContainer, "className", CLASSNAME
- + "-first-container");
- DOM.setElementProperty(secondContainer, "className", CLASSNAME
- + "-second-container");
}
@Override
@@ -232,11 +222,109 @@ public class VAbstractSplitPanel extends ComplexPanel {
}
}
+ /**
+ * 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) {
+ float posAsFloat = 0;
+
+ if (pos.indexOf("px") > 0) {
+ int posAsInt = Integer.parseInt(pos.substring(0, pos.length() - 2));
+ int offsetLength = orientation == ORIENTATION_HORIZONTAL ? getOffsetWidth()
+ : getOffsetHeight();
+
+ // 100% needs special handling
+ if (posAsInt + getSplitterSize() >= offsetLength) {
+ posAsInt = offsetLength;
+ }
+ posAsFloat = ((float) posAsInt / (float) offsetLength * 100);
+
+ } else {
+ posAsFloat = Float.parseFloat(pos.substring(0, pos.length() - 1));
+ }
+ return posAsFloat;
+ }
+
+ /**
+ * 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()
@@ -375,7 +463,6 @@ public class VAbstractSplitPanel extends ComplexPanel {
}
break;
}
-
}
void setFirstWidget(Widget w) {
@@ -481,16 +568,7 @@ public class VAbstractSplitPanel extends ComplexPanel {
}
if (position.indexOf("%") > 0) {
- float pos = newX;
- // 100% needs special handling
- if (newX + getSplitterSize() >= getOffsetWidth()) {
- pos = getOffsetWidth();
- }
- // Reversed position
- if (positionReversed) {
- pos = getOffsetWidth() - pos - getSplitterSize();
- }
- position = (pos / getOffsetWidth() * 100) + "%";
+ position = convertToPositionUnits(newX + "px");
} else {
// Reversed position
if (positionReversed) {
@@ -523,16 +601,7 @@ public class VAbstractSplitPanel extends ComplexPanel {
}
if (position.indexOf("%") > 0) {
- float pos = newY;
- // 100% needs special handling
- if (newY + getSplitterSize() >= getOffsetHeight()) {
- pos = getOffsetHeight();
- }
- // Reversed position
- if (positionReversed) {
- pos = getOffsetHeight() - pos - getSplitterSize();
- }
- position = pos / getOffsetHeight() * 100 + "%";
+ position = convertToPositionUnits(newY + "px");
} else {
// Reversed position
if (positionReversed) {
@@ -659,30 +728,24 @@ public class VAbstractSplitPanel extends ComplexPanel {
}
void setStylenames() {
- final String splitterSuffix = (orientation == ORIENTATION_HORIZONTAL ? "-hsplitter"
- : "-vsplitter");
- final String firstContainerSuffix = "-first-container";
- final String secondContainerSuffix = "-second-container";
- String lockedSuffix = "";
-
- String splitterStyle = CLASSNAME + splitterSuffix;
- String firstStyle = CLASSNAME + firstContainerSuffix;
- String secondStyle = CLASSNAME + secondContainerSuffix;
-
- if (locked) {
- splitterStyle = CLASSNAME + splitterSuffix + "-locked";
- lockedSuffix = "-locked";
- }
- for (String style : componentStyleNames) {
- splitterStyle += " " + CLASSNAME + splitterSuffix + "-" + style
- + lockedSuffix;
- firstStyle += " " + CLASSNAME + firstContainerSuffix + "-" + style;
- secondStyle += " " + CLASSNAME + secondContainerSuffix + "-"
- + style;
- }
- DOM.setElementProperty(splitter, "className", splitterStyle);
- DOM.setElementProperty(firstContainer, "className", firstStyle);
- DOM.setElementProperty(secondContainer, "className", secondStyle);
+ 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) {
@@ -693,4 +756,14 @@ public class VAbstractSplitPanel extends ComplexPanel {
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/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java
index c45c26c4ac..c4a57f5c8b 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java
@@ -44,8 +44,6 @@ 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.dom.client.TouchStartEvent;
-import com.google.gwt.event.dom.client.TouchStartHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.user.client.Command;
@@ -236,6 +234,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
private boolean enableDebug = false;
+ private static final boolean hasNativeTouchScrolling = BrowserInfo.get()
+ .isTouchDevice()
+ && !BrowserInfo.get().requiresTouchScrollDelegate();
+
+ private Set<String> noncollapsibleColumns;
+
/**
* Represents a select range of rows
*/
@@ -268,6 +272,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
*
* @see java.lang.Object#toString()
*/
+
@Override
public String toString() {
return startRow.getKey() + "-" + length;
@@ -321,6 +326,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
final FocusableScrollPanel scrollBodyPanel = new FocusableScrollPanel(true);
private KeyPressHandler navKeyPressHandler = new KeyPressHandler() {
+
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
@@ -489,12 +495,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
public VScrollTable() {
setMultiSelectMode(MULTISELECT_MODE_DEFAULT);
- scrollBodyPanel.setStyleName(CLASSNAME + "-body-wrapper");
+ scrollBodyPanel.addStyleName(CLASSNAME + "-body-wrapper");
scrollBodyPanel.addFocusHandler(this);
scrollBodyPanel.addBlurHandler(this);
scrollBodyPanel.addScrollHandler(this);
- scrollBodyPanel.setStyleName(CLASSNAME + "-body");
+ scrollBodyPanel.addStyleName(CLASSNAME + "-body");
/*
* Firefox auto-repeat works correctly only if we use a key press
@@ -509,14 +515,10 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
scrollBodyPanel.addKeyUpHandler(navKeyUpHandler);
scrollBodyPanel.sinkEvents(Event.TOUCHEVENTS);
- scrollBodyPanel.addDomHandler(new TouchStartHandler() {
- public void onTouchStart(TouchStartEvent event) {
- getTouchScrollDelegate().onTouchStart(event);
- }
- }, TouchStartEvent.getType());
scrollBodyPanel.sinkEvents(Event.ONCONTEXTMENU);
scrollBodyPanel.addDomHandler(new ContextMenuHandler() {
+
public void onContextMenu(ContextMenuEvent event) {
handleBodyContextMenu(event);
}
@@ -536,22 +538,13 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
// Add a handler to clear saved context menu details when the menu
// closes. See #8526.
client.getContextMenu().addCloseHandler(new CloseHandler<PopupPanel>() {
+
public void onClose(CloseEvent<PopupPanel> event) {
contextMenu = null;
}
});
}
- protected TouchScrollDelegate getTouchScrollDelegate() {
- if (touchScrollDelegate == null) {
- touchScrollDelegate = new TouchScrollDelegate(
- scrollBodyPanel.getElement());
- touchScrollDelegate.setScrollHandler(this);
- }
- return touchScrollDelegate;
-
- }
-
private void handleBodyContextMenu(ContextMenuEvent event) {
if (enabled && bodyActionKeys != null) {
int left = Util.getTouchOrMouseClientX(event.getNativeEvent());
@@ -896,6 +889,10 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
updateHeader(uidl.getStringArrayAttribute("vcolorder"));
updateFooter(uidl.getStringArrayAttribute("vcolorder"));
+ if (uidl.hasVariable("noncollapsiblecolumns")) {
+ noncollapsibleColumns = uidl
+ .getStringArrayVariableAsSet("noncollapsiblecolumns");
+ }
}
private void updateCollapsedColumns(UIDL uidl) {
@@ -1848,12 +1845,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
isNewBody = false;
if (firstvisible > 0) {
- // FIXME #7607
- // Originally deferred due to Firefox oddities which should not
- // occur any more. Currently deferring breaks Webkit scrolling with
- // relative-height tables, but not deferring instead breaks tables
- // with explicit page length.
+ // Deferred due to some Firefox oddities
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
scrollBodyPanel
.setScrollPosition(measureRowHeightOffset(firstvisible));
@@ -1888,6 +1882,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
*/
scrollBody.reLayoutComponents();
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement());
}
@@ -2218,6 +2213,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
setWidth(tdWidth + "px");
} else {
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
int tdWidth = width
+ scrollBody.getCellExtraWidth();
@@ -2271,6 +2267,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
/**
* Handle column reordering.
*/
+
@Override
public void onBrowserEvent(Event event) {
if (enabled && event != null) {
@@ -2814,6 +2811,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
final int newWidth = width;
Scheduler.get().scheduleDeferred(
new ScheduledCommand() {
+
public void execute() {
setColWidth(colIx, newWidth, true);
}
@@ -2841,6 +2839,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (refreshContentWidths) {
// Recalculate the column sizings if any column has changed
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+
public void execute() {
triggerLazyColumnAdjustment(true);
}
@@ -3029,6 +3028,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
String colKey;
private boolean collapsed;
+ private boolean noncollapsible = false;
private VScrollTableRow currentlyFocusedRow;
public VisibleColumnAction(String colKey) {
@@ -3040,6 +3040,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
@Override
public void execute() {
+ if (noncollapsible) {
+ return;
+ }
client.getContextMenu().hide();
// toggle selected column
if (collapsedColumns.contains(colKey)) {
@@ -3063,17 +3066,28 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
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("<span class=\"v-off\">");
+ buf.append("v-off");
} else {
- buf.append("<span class=\"v-on\">");
+ buf.append("v-on");
+ }
+ if (noncollapsible) {
+ buf.append(" v-disabled");
}
+ buf.append("\">");
+
buf.append(super.getHTML());
buf.append("</span>");
@@ -3085,6 +3099,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
/*
* Returns columns as Action array for column select popup
*/
+
public Action[] getActions() {
Object[] cols;
if (columnReordering && columnOrder != null) {
@@ -3115,6 +3130,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (!c.isEnabled()) {
a.setCollapsed(true);
}
+ if (noncollapsibleColumns.contains(cid)) {
+ a.setNoncollapsible(true);
+ }
actions[i] = a;
}
return actions;
@@ -3200,6 +3218,10 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* The text in the footer
*/
public void setText(String footerText) {
+ if (footerText == null || footerText.equals("")) {
+ footerText = "&nbsp;";
+ }
+
DOM.setInnerHTML(captionContainer, footerText);
}
@@ -3295,6 +3317,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
setWidth(tdWidth + "px");
} else {
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
int borderWidths = 1;
int tdWidth = width
@@ -3541,6 +3564,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* 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)) {
@@ -3557,6 +3581,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
*
* @see com.google.gwt.user.client.ui.HasWidgets#iterator()
*/
+
public Iterator<Widget> iterator() {
return visibleCells.iterator();
}
@@ -3835,7 +3860,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
DOM.appendChild(container, preSpacer);
DOM.appendChild(container, table);
DOM.appendChild(container, postSpacer);
- if (BrowserInfo.get().isTouchDevice()) {
+ if (BrowserInfo.get().requiresTouchScrollDelegate()) {
NodeList<Node> childNodes = container.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Element item = (Element) childNodes.getItem(i);
@@ -4388,7 +4413,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
private String[] actionKeys = null;
private final TableRowElement rowElement;
- private boolean mDown;
private int index;
private Event touchStart;
private static final String ROW_CLASSNAME_EVEN = CLASSNAME + "-row";
@@ -4396,8 +4420,10 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
+ "-row-odd";
private static final int TOUCH_CONTEXT_MENU_TIMEOUT = 500;
private Timer contextTouchTimeout;
+ private Timer dragTouchTimeout;
private int touchStartY;
private int touchStartX;
+ private boolean isDragging = false;
private VScrollTableRow(int rowKey) {
this.rowKey = rowKey;
@@ -4785,12 +4811,128 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
}
+ /**
+ * 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) {
- if (enabled) {
+
+ final boolean touchEventHandled = handleTouchEvent(event);
+
+ if (enabled && !touchEventHandled) {
final int type = event.getTypeInt();
final Element targetTdOrTr = getEventTargetTdOrTr(event);
if (type == Event.ONCONTEXTMENU) {
@@ -4823,7 +4965,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
break;
case Event.ONMOUSEUP:
if (targetCellOrRowFound) {
- mDown = false;
/*
* Queue here, send at the same time as the
* corresponding value change event - see #7127
@@ -4983,6 +5124,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
touchStart.preventDefault();
if (dragmode != 0 || actionKeys != null) {
new Timer() {
+
@Override
public void run() {
TouchScrollDelegate activeScrollDelegate = TouchScrollDelegate
@@ -5021,6 +5163,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (contextTouchTimeout == null
&& actionKeys != null) {
contextTouchTimeout = new Timer() {
+
@Override
public void run() {
if (touchStart != null) {
@@ -5066,9 +5209,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
break;
case Event.ONMOUSEOUT:
- if (targetCellOrRowFound) {
- mDown = false;
- }
break;
default:
break;
@@ -5098,7 +5238,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
protected void startRowDrag(Event event, final int type,
Element targetTdOrTr) {
- mDown = true;
VTransferable transferable = new VTransferable();
transferable.setDragSource(ConnectorMap.get(client)
.getConnector(VScrollTable.this));
@@ -5290,6 +5429,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
*
* @see com.vaadin.terminal.gwt.client.ui.IActionOwner#getActions ()
*/
+
public Action[] getActions() {
if (actionKeys == null) {
return new Action[] {};
@@ -5299,6 +5439,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
final String actionKey = actionKeys[i];
final TreeAction a = new TreeAction(this,
String.valueOf(rowKey), actionKey) {
+
@Override
public void execute() {
super.execute();
@@ -5586,6 +5727,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* column widths "optimally". Doing this lazily to avoid expensive
* calculation when resizing is not yet finished.
*/
+
@Override
public void run() {
if (scrollBody == null) {
@@ -5682,7 +5824,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (isDynamicHeight() && totalRows == pageLength) {
// fix body height (may vary if lazy loading is offhorizontal
// scrollbar appears/disappears)
- int bodyHeight = scrollBody.getRequiredHeight();
+ int bodyHeight = Util.getRequiredHeight(scrollBody);
boolean needsSpaceForHorizontalScrollbar = (availW < usedMinimumWidth);
if (needsSpaceForHorizontalScrollbar) {
bodyHeight += Util.getNativeScrollbarSize();
@@ -5695,6 +5837,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
scrollBody.reLayoutComponents();
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement());
}
@@ -5804,15 +5947,26 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
void updateHeight() {
setContainerHeight();
- updatePageLength();
-
+ 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.
- Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement());
+ // 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() {
+
+ public void execute() {
+ Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement());
+ }
+ });
}
+ triggerLazyColumnAdjustment(false);
+
/*
* setting height may affect wheter the component has scrollbars ->
* needs scrolling or not
@@ -5826,6 +5980,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* lost). Example ITabPanel just set contained components invisible and back
* when changing tabs.
*/
+
@Override
public void setVisible(boolean visible) {
if (isVisible() != visible) {
@@ -5833,6 +5988,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (initializedAndAttached) {
if (visible) {
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
scrollBodyPanel
.setScrollPosition(measureRowHeightOffset(firstRowInViewPort));
@@ -5866,6 +6022,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* This method has logic which rows needs to be requested from server when
* user scrolls
*/
+
public void onScroll(ScrollEvent event) {
scrollLeft = scrollBodyPanel.getElement().getScrollLeft();
scrollTop = scrollBodyPanel.getScrollPosition();
@@ -5894,6 +6051,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
// correct
// value available soon.
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
onScroll(null);
}
@@ -5994,7 +6152,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
return false;
}
- // @Override
+ //
// public int hashCode() {
// return overkey;
// }
@@ -6053,6 +6211,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
deEmphasis();
final TableDDDetails newDetails = dropDetails;
VAcceptCallback cb = new VAcceptCallback() {
+
public void accepted(VDragEvent event) {
if (newDetails.equals(dropDetails)) {
dragAccepted(event);
@@ -6459,6 +6618,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event
* .dom.client.FocusEvent)
*/
+
public void onFocus(FocusEvent event) {
if (isFocusable()) {
hasFocus = true;
@@ -6479,6 +6639,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event
* .dom.client.BlurEvent)
*/
+
public void onBlur(BlurEvent event) {
hasFocus = false;
navKeyDown = false;
@@ -6551,6 +6712,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
*
* @see com.vaadin.terminal.gwt.client.Focusable#focus()
*/
+
public void focus() {
if (isFocusable()) {
scrollBodyPanel.focus();
@@ -6594,6 +6756,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
public void startScrollingVelocityTimer() {
if (scrollingVelocityTimer == null) {
scrollingVelocityTimer = new Timer() {
+
@Override
public void run() {
scrollingVelocity++;
@@ -6630,6 +6793,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
public void lazyRevertFocusToRow(final VScrollTableRow currentlyFocusedRow) {
Scheduler.get().scheduleFinally(new ScheduledCommand() {
+
public void execute() {
if (currentlyFocusedRow != null) {
setRowFocus(currentlyFocusedRow);
diff --git a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java
index c97ede1252..aba5a41f9a 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java
@@ -331,6 +331,11 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
}
return width;
}
+
+ public Element getCloseButton() {
+ return closeButton;
+ }
+
}
static class TabBar extends ComplexPanel implements ClickHandler,
@@ -393,7 +398,14 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
}
public void onClick(ClickEvent event) {
- Widget caption = (Widget) event.getSource();
+ 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()) {
@@ -1021,6 +1033,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
final Style style = scroller.getStyle();
style.setProperty("whiteSpace", "normal");
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
style.setProperty("whiteSpace", "");
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java
index f2b37c3a1c..bd6cddb682 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java
@@ -4,16 +4,12 @@
package com.vaadin.terminal.gwt.client.ui.tabsheet;
-import com.google.gwt.dom.client.Node;
-import com.google.gwt.dom.client.NodeList;
-import com.google.gwt.event.dom.client.TouchStartEvent;
-import com.google.gwt.event.dom.client.TouchStartHandler;
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.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
@@ -27,38 +23,15 @@ import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate;
public class VTabsheetPanel extends ComplexPanel {
private Widget visibleWidget;
- private TouchScrollDelegate touchScrollDelegate;
+
+ private final TouchScrollHandler touchScrollHandler;
/**
* Creates an empty tabsheet panel.
*/
public VTabsheetPanel() {
setElement(DOM.createDiv());
- sinkEvents(Event.TOUCHEVENTS);
- addDomHandler(new TouchStartHandler() {
- public void onTouchStart(TouchStartEvent event) {
- /*
- * All container elements needs to be scrollable by one finger.
- * Update the scrollable element list of touch delegate on each
- * touch start.
- */
- NodeList<Node> childNodes = getElement().getChildNodes();
- Element[] elements = new Element[childNodes.getLength()];
- for (int i = 0; i < elements.length; i++) {
- elements[i] = (Element) childNodes.getItem(i);
- }
- getTouchScrollDelegate().setElements(elements);
- getTouchScrollDelegate().onTouchStart(event);
- }
- }, TouchStartEvent.getType());
- }
-
- protected TouchScrollDelegate getTouchScrollDelegate() {
- if (touchScrollDelegate == null) {
- touchScrollDelegate = new TouchScrollDelegate();
- }
- return touchScrollDelegate;
-
+ touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this);
}
/**
@@ -77,8 +50,8 @@ public class VTabsheetPanel extends ComplexPanel {
private Element createContainerElement() {
Element el = DOM.createDiv();
DOM.setStyleAttribute(el, "position", "absolute");
- DOM.setStyleAttribute(el, "overflow", "auto");
hide(el);
+ touchScrollHandler.addElement(el);
return el;
}
@@ -122,6 +95,7 @@ public class VTabsheetPanel extends ComplexPanel {
if (parent != null) {
DOM.removeChild(getElement(), parent);
}
+ touchScrollHandler.removeElement(parent);
}
return removed;
}
@@ -141,6 +115,8 @@ public class VTabsheetPanel extends ComplexPanel {
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
diff --git a/src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java b/src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java
index f7cd9d133e..9a8e0e9ce1 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java
@@ -379,26 +379,34 @@ public class VTreeTable extends VScrollTable {
rowsToDelete.add(row);
}
}
- 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);
+ 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);
- RowExpandAnimation anim = new RowExpandAnimation(insertedRows);
- anim.run(150);
+ if (!insertedRows.isEmpty()) {
+ // Only animate if there's something to animate (#8810)
+ RowExpandAnimation anim = new RowExpandAnimation(insertedRows);
+ anim.run(150);
+ }
return insertedRows;
}
@@ -521,6 +529,10 @@ public class VTreeTable extends VScrollTable {
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();
@@ -641,6 +653,10 @@ public class VTreeTable extends VScrollTable {
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;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java b/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java
index d08387fc6d..8fd84a9ea6 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java
@@ -40,6 +40,7 @@ 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.
@@ -264,8 +265,10 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
if (!orderingDefered) {
orderingDefered = true;
Scheduler.get().scheduleFinally(new Command() {
+
public void execute() {
doServerSideOrdering();
+ VNotification.bringNotificationsToFront();
}
});
}
@@ -275,6 +278,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
orderingDefered = false;
VWindow[] array = windowOrder.toArray(new VWindow[windowOrder.size()]);
Arrays.sort(array, new Comparator<VWindow>() {
+
public int compare(VWindow o1, VWindow o2) {
/*
* Order by modality, then by bringtofront sequence.
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
index 5b2be308a3..bf29144cc1 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
@@ -64,9 +64,6 @@ import com.vaadin.ui.Root;
public abstract class AbstractApplicationPortlet extends GenericPortlet
implements Constants {
- private static final Logger logger = Logger
- .getLogger(AbstractApplicationPortlet.class.getName());
-
public static class WrappedHttpAndPortletRequest extends
WrappedPortletRequest {
@@ -203,6 +200,8 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
*/
public static final String PORTAL_PARAMETER_VAADIN_THEME = "vaadin.theme";
+ public static final String WRITE_AJAX_PAGE_SCRIPT_WIDGETSET_SHOULD_WRITE = "writeAjaxPageScriptWidgetsetShouldWrite";
+
// TODO some parts could be shared with AbstractApplicationServlet
// TODO Can we close the application when the portlet is removed? Do we know
@@ -213,6 +212,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
private boolean productionMode = false;
private DeploymentConfiguration deploymentConfiguration = new DeploymentConfiguration() {
+
public String getConfiguredWidgetset(WrappedRequest request) {
String widgetset = getApplicationOrSystemProperty(
@@ -271,6 +271,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
* @return The location of static resources (inside which there should
* be a VAADIN directory). Does not end with a slash (/).
*/
+
public String getStaticFileLocation(WrappedRequest request) {
String staticFileLocation = WrappedPortletRequest.cast(request)
.getPortalProperty(
@@ -329,7 +330,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
* Print an information/warning message about running with xsrf
* protection disabled
*/
- logger.warning(WARNING_XSRF_PROTECTION_DISABLED);
+ getLogger().warning(WARNING_XSRF_PROTECTION_DISABLED);
}
}
@@ -345,7 +346,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
if (!productionMode) {
/* Print an information/warning message about running in debug mode */
// TODO Maybe we need a different message for portlets?
- logger.warning(NOT_PRODUCTION_MODE_INFO);
+ getLogger().warning(NOT_PRODUCTION_MODE_INFO);
}
}
@@ -665,11 +666,12 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
} catch (final SessionExpiredException e) {
// TODO Figure out a better way to deal with
// SessionExpiredExceptions
- logger.finest("A user session has expired");
+ getLogger().finest("A user session has expired");
} catch (final GeneralSecurityException e) {
// TODO Figure out a better way to deal with
// GeneralSecurityExceptions
- logger.fine("General security exception, the security key was probably incorrect.");
+ getLogger()
+ .fine("General security exception, the security key was probably incorrect.");
} catch (final Throwable e) {
handleServiceException(request, response, application, e);
} finally {
@@ -690,9 +692,11 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
Root.setCurrentRoot(null);
Application.setCurrentApplication(null);
- requestTimer
- .stop((AbstractWebApplicationContext) application
- .getContext());
+ PortletSession session = request
+ .getPortletSession(false);
+ if (session != null) {
+ requestTimer.stop(getApplicationContext(session));
+ }
}
}
}
@@ -729,7 +733,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
private void handleUnknownRequest(PortletRequest request,
PortletResponse response) {
- logger.warning("Unknown request type");
+ getLogger().warning("Unknown request type");
}
/**
@@ -795,8 +799,9 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
os.write(buffer, 0, bytes);
}
} else {
- logger.info("Requested resource [" + resourceID
- + "] could not be found");
+ getLogger().info(
+ "Requested resource [" + resourceID
+ + "] could not be found");
response.setProperty(ResourceResponse.HTTP_STATUS_CODE,
Integer.toString(HttpServletResponse.SC_NOT_FOUND));
}
@@ -1141,4 +1146,8 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
return PortletApplicationContext2.getApplicationContext(portletSession);
}
+ private static final Logger getLogger() {
+ return Logger.getLogger(AbstractApplicationPortlet.class.getName());
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
index 905cfe7e3c..2179761d31 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
@@ -87,9 +87,6 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
// TODO Move some (all?) of the constants to a separate interface (shared
// with portlet)
- private static final Logger logger = Logger
- .getLogger(AbstractApplicationServlet.class.getName());
-
private Properties applicationProperties;
private boolean productionMode = false;
@@ -99,6 +96,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
private int resourceCacheTime = 3600;
private DeploymentConfiguration deploymentConfiguration = new DeploymentConfiguration() {
+
public String getStaticFileLocation(WrappedRequest request) {
HttpServletRequest servletRequest = WrappedHttpServletRequest
.cast(request);
@@ -149,8 +147,8 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
* if an exception has occurred that interferes with the
* servlet's normal operation.
*/
- @SuppressWarnings("unchecked")
@Override
+ @SuppressWarnings("unchecked")
public void init(javax.servlet.ServletConfig servletConfig)
throws javax.servlet.ServletException {
super.init(servletConfig);
@@ -186,7 +184,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
* Print an information/warning message about running with xsrf
* protection disabled
*/
- logger.warning(WARNING_XSRF_PROTECTION_DISABLED);
+ getLogger().warning(WARNING_XSRF_PROTECTION_DISABLED);
}
}
@@ -200,7 +198,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
if (!productionMode) {
/* Print an information/warning message about running in debug mode */
- logger.warning(NOT_PRODUCTION_MODE_INFO);
+ getLogger().warning(NOT_PRODUCTION_MODE_INFO);
}
}
@@ -214,7 +212,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
} catch (NumberFormatException nfe) {
// Default is 1h
resourceCacheTime = 3600;
- logger.warning(WARNING_RESOURCE_CACHING_TIME_NOT_NUMERIC);
+ getLogger().warning(WARNING_RESOURCE_CACHING_TIME_NOT_NUMERIC);
}
}
@@ -333,6 +331,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
* @throws IOException
* if the request for the TRACE cannot be handled.
*/
+
@Override
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
@@ -478,9 +477,10 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
Root.setCurrentRoot(null);
Application.setCurrentApplication(null);
- requestTimer
- .stop((AbstractWebApplicationContext) application
- .getContext());
+ HttpSession session = request.getSession(false);
+ if (session != null) {
+ requestTimer.stop(getApplicationContext(session));
+ }
}
}
@@ -796,8 +796,8 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
resultPath = url.getFile();
} catch (final Exception e) {
// FIXME: Handle exception
- logger.log(Level.INFO, "Could not find resource path " + path,
- e);
+ getLogger().log(Level.INFO,
+ "Could not find resource path " + path, e);
}
}
return resultPath;
@@ -1054,10 +1054,11 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
if (resourceUrl == null) {
// cannot serve requested file
- logger.info("Requested resource ["
- + filename
- + "] not found from filesystem or through class loader."
- + " Add widgetset and/or theme JAR to your classpath or add files to WebContent/VAADIN folder.");
+ getLogger()
+ .info("Requested resource ["
+ + filename
+ + "] not found from filesystem or through class loader."
+ + " Add widgetset and/or theme JAR to your classpath or add files to WebContent/VAADIN folder.");
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
@@ -1065,9 +1066,10 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
// security check: do not permit navigation out of the VAADIN
// directory
if (!isAllowedVAADINResourceUrl(request, resourceUrl)) {
- logger.info("Requested resource ["
- + filename
- + "] not accessible in the VAADIN directory or access to it is forbidden.");
+ getLogger()
+ .info("Requested resource ["
+ + filename
+ + "] not accessible in the VAADIN directory or access to it is forbidden.");
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
return;
}
@@ -1090,10 +1092,10 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
}
} catch (Exception e) {
// Failed to find out last modified timestamp. Continue without it.
- logger.log(
- Level.FINEST,
- "Failed to find out last modified timestamp. Continuing without it.",
- e);
+ getLogger()
+ .log(Level.FINEST,
+ "Failed to find out last modified timestamp. Continuing without it.",
+ e);
} finally {
if (connection instanceof URLConnection) {
try {
@@ -1105,7 +1107,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
is.close();
}
} catch (IOException e) {
- logger.log(Level.INFO,
+ getLogger().log(Level.INFO,
"Error closing URLConnection input stream", e);
}
}
@@ -1130,7 +1132,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
* parameter in web.xml
*/
response.setHeader("Cache-Control",
- "max-age: " + String.valueOf(resourceCacheTime));
+ "max-age= " + String.valueOf(resourceCacheTime));
}
// Write the resource to the client.
@@ -1173,12 +1175,14 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
// loader sees it.
if (!resourceUrl.getPath().contains("!/VAADIN/")) {
- logger.info("Blocked attempt to access a JAR entry not starting with /VAADIN/: "
- + resourceUrl);
+ getLogger().info(
+ "Blocked attempt to access a JAR entry not starting with /VAADIN/: "
+ + resourceUrl);
return false;
}
- logger.fine("Accepted access to a JAR entry using a class loader: "
- + resourceUrl);
+ getLogger().fine(
+ "Accepted access to a JAR entry using a class loader: "
+ + resourceUrl);
return true;
} else {
// Some servers such as GlassFish extract files from JARs (file:)
@@ -1188,11 +1192,13 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
// "/../"
if (!resourceUrl.getPath().contains("/VAADIN/")
|| resourceUrl.getPath().contains("/../")) {
- logger.info("Blocked attempt to access file: " + resourceUrl);
+ getLogger().info(
+ "Blocked attempt to access file: " + resourceUrl);
return false;
}
- logger.fine("Accepted access to a file using a class loader: "
- + resourceUrl);
+ getLogger().fine(
+ "Accepted access to a file using a class loader: "
+ + resourceUrl);
return true;
}
}
@@ -1733,4 +1739,8 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
c > 96 && c < 123 // a-z
;
}
+
+ private static final Logger getLogger() {
+ return Logger.getLogger(AbstractApplicationServlet.class.getName());
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
index 494ca7e28e..e04857f800 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
@@ -92,9 +92,6 @@ public abstract class AbstractCommunicationManager implements Serializable {
private static final String DASHDASH = "--";
- private static final Logger logger = Logger
- .getLogger(AbstractCommunicationManager.class.getName());
-
private static final RequestHandler APP_RESOURCE_HANDLER = new ApplicationResourceHandler();
private static final RequestHandler UNSUPPORTED_BROWSER_HANDLER = new UnsupportedBrowserHandler();
@@ -539,7 +536,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
if (root == null) {
// This should not happen, no windows exists but
// application is still open.
- logger.warning("Could not get root for application");
+ getLogger().warning("Could not get root for application");
return;
}
} else {
@@ -562,7 +559,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
// FIXME: Handle exception
// Not critical, but something is still wrong; print
// stacktrace
- logger.log(Level.WARNING,
+ getLogger().log(Level.WARNING,
"getSystemMessages() failed - continuing", e2);
}
if (ci != null) {
@@ -604,8 +601,9 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
if (!Version.getFullVersion().equals(widgetsetVersion)) {
- logger.warning(String.format(Constants.WIDGETSET_MISMATCH_INFO,
- Version.getFullVersion(), widgetsetVersion));
+ getLogger().warning(
+ String.format(Constants.WIDGETSET_MISMATCH_INFO,
+ Version.getFullVersion(), widgetsetVersion));
}
}
@@ -638,7 +636,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
printHighlightedComponentHierarchy(sb, component);
}
- logger.info(sb.toString());
+ getLogger().info(sb.toString());
}
protected void printHighlightedComponentHierarchy(StringBuilder sb,
@@ -767,7 +765,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
// Paints components
DirtyConnectorTracker rootConnectorTracker = root
.getDirtyConnectorTracker();
- logger.log(Level.FINE, "* Creating response to client");
+ getLogger().log(Level.FINE, "* Creating response to client");
if (repaintAll) {
getClientCache(root).clear();
rootConnectorTracker.markAllConnectorsDirty();
@@ -780,8 +778,10 @@ public abstract class AbstractCommunicationManager implements Serializable {
dirtyVisibleConnectors
.addAll(getDirtyVisibleConnectors(rootConnectorTracker));
- logger.log(Level.FINE, "Found " + dirtyVisibleConnectors.size()
- + " dirty connectors to paint");
+ getLogger().log(
+ Level.FINE,
+ "Found " + dirtyVisibleConnectors.size()
+ + " dirty connectors to paint");
for (ClientConnector connector : dirtyVisibleConnectors) {
if (connector instanceof Component) {
((Component) connector).updateState();
@@ -841,7 +841,8 @@ public abstract class AbstractCommunicationManager implements Serializable {
try {
referenceState = stateType.newInstance();
} catch (Exception e) {
- logger.log(Level.WARNING,
+ getLogger().log(
+ Level.WARNING,
"Error creating reference object for state of type "
+ stateType.getName());
}
@@ -1006,16 +1007,16 @@ public abstract class AbstractCommunicationManager implements Serializable {
(Class[]) null);
ci = (Application.SystemMessages) m.invoke(null, (Object[]) null);
} catch (NoSuchMethodException e) {
- logger.log(Level.WARNING,
+ getLogger().log(Level.WARNING,
"getSystemMessages() failed - continuing", e);
} catch (IllegalArgumentException e) {
- logger.log(Level.WARNING,
+ getLogger().log(Level.WARNING,
"getSystemMessages() failed - continuing", e);
} catch (IllegalAccessException e) {
- logger.log(Level.WARNING,
+ getLogger().log(Level.WARNING,
"getSystemMessages() failed - continuing", e);
} catch (InvocationTargetException e) {
- logger.log(Level.WARNING,
+ getLogger().log(Level.WARNING,
"getSystemMessages() failed - continuing", e);
}
@@ -1054,8 +1055,8 @@ public abstract class AbstractCommunicationManager implements Serializable {
is = getThemeResourceAsStream(root, getTheme(root), resource);
} catch (final Exception e) {
// FIXME: Handle exception
- logger.log(Level.FINER, "Failed to get theme resource stream.",
- e);
+ getLogger().log(Level.FINER,
+ "Failed to get theme resource stream.", e);
}
if (is != null) {
@@ -1074,13 +1075,13 @@ public abstract class AbstractCommunicationManager implements Serializable {
r.close();
} catch (final java.io.IOException e) {
// FIXME: Handle exception
- logger.log(Level.INFO, "Resource transfer failed", e);
+ getLogger().log(Level.INFO, "Resource transfer failed", e);
}
outWriter.print("\""
+ JsonPaintTarget.escapeJSON(layout.toString()) + "\"");
} else {
// FIXME: Handle exception
- logger.severe("CustomLayout not found: " + resource);
+ getLogger().severe("CustomLayout not found: " + resource);
}
}
outWriter.print("}");
@@ -1171,8 +1172,9 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
sortByHierarchy((List) legacyComponents);
for (Vaadin6Component c : legacyComponents) {
- logger.fine("Painting Vaadin6Component " + c.getClass().getName()
- + "@" + Integer.toHexString(c.hashCode()));
+ getLogger().fine(
+ "Painting Vaadin6Component " + c.getClass().getName() + "@"
+ + Integer.toHexString(c.hashCode()));
paintTarget.startTag("change");
final String pid = c.getConnectorId();
paintTarget.addAttribute("pid", pid);
@@ -1187,6 +1189,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
// containers rely on that their updateFromUIDL method has been called
// before children start calling e.g. updateCaption
Collections.sort(paintables, new Comparator<Component>() {
+
public int compare(Component c1, Component c2) {
int depth1 = 0;
while (c1.getParent() != null) {
@@ -1472,6 +1475,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
enabledConnectors.add(connector);
}
}
+
for (int i = 0; i < invocations.size(); i++) {
MethodInvocation invocation = invocations.get(i);
@@ -1479,7 +1483,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
invocation.getConnectorId());
if (connector == null) {
- logger.log(
+ getLogger().log(
Level.WARNING,
"RPC call to " + invocation.getInterfaceName()
+ "." + invocation.getMethodName()
@@ -1517,7 +1521,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
msg += ", caption=" + caption;
}
}
- logger.warning(msg);
+ getLogger().warning(msg);
continue;
}
@@ -1545,14 +1549,13 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
handleChangeVariablesError(app, errorComponent, e,
changes);
-
}
}
}
-
} catch (JSONException e) {
- logger.warning("Unable to parse RPC call from the client: "
- + e.getMessage());
+ getLogger().warning(
+ "Unable to parse RPC call from the client: "
+ + e.getMessage());
// TODO or return success = false?
throw new RuntimeException(e);
}
@@ -1895,8 +1898,9 @@ public abstract class AbstractCommunicationManager implements Serializable {
DateFormat dateFormat = DateFormat.getDateTimeInstance(
DateFormat.SHORT, DateFormat.SHORT, l);
if (!(dateFormat instanceof SimpleDateFormat)) {
- logger.warning("Unable to get default date pattern for locale "
- + l.toString());
+ getLogger().warning(
+ "Unable to get default date pattern for locale "
+ + l.toString());
dateFormat = new SimpleDateFormat();
}
final String df = ((SimpleDateFormat) dateFormat).toPattern();
@@ -2095,7 +2099,8 @@ public abstract class AbstractCommunicationManager implements Serializable {
if (id == null) {
id = nextTypeKey++;
typeToKey.put(class1, id);
- logger.log(Level.FINE, "Mapping " + class1.getName() + " to " + id);
+ getLogger().log(Level.FINE,
+ "Mapping " + class1.getName() + " to " + id);
}
return id.toString();
}
@@ -2232,7 +2237,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
writeUidlResponse(request, true, pWriter, root, false);
pWriter.print("}");
String initialUIDL = sWriter.toString();
- logger.log(Level.FINE, "Initial UIDL:" + initialUIDL);
+ getLogger().log(Level.FINE, "Initial UIDL:" + initialUIDL);
return initialUIDL;
}
@@ -2386,4 +2391,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
}
+ private static final Logger getLogger() {
+ return Logger.getLogger(AbstractCommunicationManager.class.getName());
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java b/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java
index c0ae0afc26..bf4ea860a8 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java
@@ -32,9 +32,6 @@ import com.vaadin.terminal.ApplicationResource;
public abstract class AbstractWebApplicationContext implements
ApplicationContext, HttpSessionBindingListener, Serializable {
- private static final Logger logger = Logger
- .getLogger(AbstractWebApplicationContext.class.getName());
-
protected Collection<TransactionListener> listeners = Collections
.synchronizedList(new LinkedList<TransactionListener>());
@@ -145,7 +142,7 @@ public abstract class AbstractWebApplicationContext implements
// remove same application here. Possible if you got e.g. session
// lifetime 1 min but socket write may take longer than 1 min.
// FIXME: Handle exception
- logger.log(Level.SEVERE,
+ getLogger().log(Level.SEVERE,
"Could not remove application, leaking memory.", e);
}
}
@@ -252,4 +249,8 @@ public abstract class AbstractWebApplicationContext implements
return lastRequestTime;
}
+ private Logger getLogger() {
+ return Logger.getLogger(AbstractWebApplicationContext.class.getName());
+ }
+
} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/server/ClientConnector.java b/src/com/vaadin/terminal/gwt/server/ClientConnector.java
index 359e112738..dfdd58879d 100644
--- a/src/com/vaadin/terminal/gwt/server/ClientConnector.java
+++ b/src/com/vaadin/terminal/gwt/server/ClientConnector.java
@@ -3,7 +3,7 @@
*/
package com.vaadin.terminal.gwt.server;
-import java.util.Iterator;
+import java.util.Collection;
import java.util.List;
import com.vaadin.terminal.AbstractClientConnector;
@@ -12,7 +12,6 @@ import com.vaadin.terminal.gwt.client.Connector;
import com.vaadin.terminal.gwt.client.communication.SharedState;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
-import com.vaadin.ui.Root;
/**
* Interface implemented by all connectors that are capable of communicating
@@ -30,8 +29,6 @@ public interface ClientConnector extends Connector, RpcTarget {
*
* @return an unmodifiable ordered list of pending server to client method
* calls (not null)
- *
- * @since 7.0
*/
public List<ClientMethodInvocation> retrievePendingRpcCalls();
@@ -61,7 +58,7 @@ public interface ClientConnector extends Connector, RpcTarget {
* Causes a repaint of this connector, and all connectors below it.
*
* This should only be used in special cases, e.g when the state of a
- * descendant depends on the state of a ancestor.
+ * descendant depends on the state of an ancestor.
*/
public void requestRepaintAll();
@@ -69,18 +66,18 @@ public interface ClientConnector extends Connector, RpcTarget {
* Sets the parent connector of the connector.
*
* <p>
- * This method automatically calls {@link #attach()} if the parent becomes
- * attached to the application, regardless of whether it was attached
- * previously. Conversely, if the parent is {@code null} and the connector
- * is attached to the application, {@link #detach()} is called for the
- * connector.
+ * This method automatically calls {@link #attach()} if the connector
+ * becomes attached to the application, regardless of whether it was
+ * attached previously. Conversely, if the parent is {@code null} and the
+ * connector is attached to the application, {@link #detach()} is called for
+ * the connector.
* </p>
* <p>
* This method is rarely called directly. One of the
* {@link ComponentContainer#addComponent(Component)} or
- * {@link AbstractClientConnector#addFeature(Feature)} methods is normally
- * used for adding connectors to a container and it will call this method
- * implicitly.
+ * {@link AbstractClientConnector#addExtension(Extension)} methods are
+ * normally used for adding connectors to a parent and they will call this
+ * method implicitly.
* </p>
*
* <p>
@@ -103,15 +100,13 @@ public interface ClientConnector extends Connector, RpcTarget {
* The caller of this method is {@link #setParent(ClientConnector)} if the
* parent is itself already attached to the application. If not, the parent
* will call the {@link #attach()} for all its children when it is attached
- * to the application. This method is always called before the connector is
- * painted for the first time.
+ * to the application. This method is always called before the connector's
+ * data is sent to the client-side for the first time.
* </p>
*
* <p>
* The attachment logic is implemented in {@link AbstractClientConnector}.
* </p>
- *
- * @see #getApplication()
*/
public void attach();
@@ -119,25 +114,26 @@ public interface ClientConnector extends Connector, RpcTarget {
* Notifies the component that it is detached from the application.
*
* <p>
- * The {@link #getApplication()} and {@link #getRoot()} methods might return
- * <code>null</code> after this method is called.
- * </p>
- *
- * <p>
- * This method must call {@link Root#componentDetached(Component)} to let
- * the Root know that a new Component has been attached.
- * </p>
- * *
- * <p>
- * The caller of this method is {@link #setParent(Component)} if the parent
- * is in the application. When the parent is detached from the application
- * it is its response to call {@link #detach()} for all the children and to
- * detach itself from the terminal.
+ * The caller of this method is {@link #setParent(ClientConnector)} if the
+ * parent is in the application. When the parent is detached from the
+ * application it is its response to call {@link #detach()} for all the
+ * children and to detach itself from the terminal.
* </p>
*/
public void detach();
- public Iterator<Extension> getExtensionIterator();
+ /**
+ * Get a read-only collection of all extensions attached to this connector.
+ *
+ * @return a collection of extensions
+ */
+ public Collection<Extension> getExtensions();
+ /**
+ * Remove an extension from this connector.
+ *
+ * @param extension
+ * the extension to remove.
+ */
public void removeExtension(Extension extension);
}
diff --git a/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java b/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java
index 335067ca7a..171d440796 100644
--- a/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java
+++ b/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java
@@ -34,9 +34,6 @@ import com.vaadin.ui.Window;
@SuppressWarnings({ "serial", "deprecation" })
public class ComponentSizeValidator implements Serializable {
- private final static Logger logger = Logger
- .getLogger(ComponentSizeValidator.class.getName());
-
private final static int LAYERS_SHOWN = 4;
/**
@@ -134,7 +131,7 @@ public class ComponentSizeValidator implements Serializable {
return parentCanDefineHeight(component);
} catch (Exception e) {
- logger.log(Level.FINER,
+ getLogger().log(Level.FINER,
"An exception occurred while validating sizes.", e);
return true;
}
@@ -154,7 +151,7 @@ public class ComponentSizeValidator implements Serializable {
return parentCanDefineWidth(component);
} catch (Exception e) {
- logger.log(Level.FINER,
+ getLogger().log(Level.FINER,
"An exception occurred while validating sizes.", e);
return true;
}
@@ -653,11 +650,15 @@ public class ComponentSizeValidator implements Serializable {
return;
} catch (Exception e) {
// TODO Auto-generated catch block
- logger.log(Level.FINER,
+ getLogger().log(Level.FINER,
"An exception occurred while validating sizes.", e);
}
}
}
+ private static Logger getLogger() {
+ return Logger.getLogger(ComponentSizeValidator.class.getName());
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/server/DragAndDropService.java b/src/com/vaadin/terminal/gwt/server/DragAndDropService.java
index 68fb87a986..0e8d1c0152 100644
--- a/src/com/vaadin/terminal/gwt/server/DragAndDropService.java
+++ b/src/com/vaadin/terminal/gwt/server/DragAndDropService.java
@@ -4,7 +4,8 @@
package com.vaadin.terminal.gwt.server;
import java.io.PrintWriter;
-import java.util.Iterator;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
@@ -28,9 +29,6 @@ import com.vaadin.ui.Component;
public class DragAndDropService implements VariableOwner, ClientConnector {
- private static final Logger logger = Logger
- .getLogger(DragAndDropService.class.getName());
-
private int lastVisitId;
private boolean lastVisitAccepted = false;
@@ -50,8 +48,9 @@ public class DragAndDropService implements VariableOwner, ClientConnector {
// Validate drop handler owner
if (!(owner instanceof DropTarget)) {
- logger.severe("DropHandler owner " + owner
- + " must implement DropTarget");
+ getLogger()
+ .severe("DropHandler owner " + owner
+ + " must implement DropTarget");
return;
}
// owner cannot be null here
@@ -81,8 +80,9 @@ public class DragAndDropService implements VariableOwner, ClientConnector {
DropHandler dropHandler = (dropTarget).getDropHandler();
if (dropHandler == null) {
// No dropHandler returned so no drop can be performed.
- logger.fine("DropTarget.getDropHandler() returned null for owner: "
- + dropTarget);
+ getLogger().fine(
+ "DropTarget.getDropHandler() returned null for owner: "
+ + dropTarget);
return;
}
@@ -275,13 +275,16 @@ public class DragAndDropService implements VariableOwner, ClientConnector {
}
- public Iterator<Extension> getExtensionIterator() {
+ public Collection<Extension> getExtensions() {
// TODO Auto-generated method stub
- return null;
+ return Collections.emptySet();
}
public void removeExtension(Extension extension) {
// TODO Auto-generated method stub
+ }
+ private Logger getLogger() {
+ return Logger.getLogger(DragAndDropService.class.getName());
}
}
diff --git a/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java
index 485c98f036..a6032fa98d 100644
--- a/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java
+++ b/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java
@@ -94,9 +94,6 @@ import com.vaadin.service.ApplicationContext;
*/
public class GAEApplicationServlet extends ApplicationServlet {
- private static final Logger logger = Logger
- .getLogger(GAEApplicationServlet.class.getName());
-
// memcache mutex is MUTEX_BASE + sessio id
private static final String MUTEX_BASE = "_vmutex";
@@ -209,8 +206,9 @@ public class GAEApplicationServlet extends ApplicationServlet {
try {
Thread.sleep(RETRY_AFTER_MILLISECONDS);
} catch (InterruptedException e) {
- logger.finer("Thread.sleep() interrupted while waiting for lock. Trying again. "
- + e);
+ getLogger().finer(
+ "Thread.sleep() interrupted while waiting for lock. Trying again. "
+ + e);
}
}
@@ -252,16 +250,16 @@ public class GAEApplicationServlet extends ApplicationServlet {
ds.put(entity);
} catch (DeadlineExceededException e) {
- logger.warning("DeadlineExceeded for " + session.getId());
+ getLogger().warning("DeadlineExceeded for " + session.getId());
sendDeadlineExceededNotification(request, response);
} catch (NotSerializableException e) {
- logger.log(Level.SEVERE, "Not serializable!", e);
+ getLogger().log(Level.SEVERE, "Not serializable!", e);
// TODO this notification is usually not shown - should we redirect
// in some other way - can we?
sendNotSerializableNotification(request, response);
} catch (Exception e) {
- logger.log(Level.WARNING,
+ getLogger().log(Level.WARNING,
"An exception occurred while servicing request.", e);
sendCriticalErrorNotification(request, response);
@@ -308,12 +306,14 @@ public class GAEApplicationServlet extends ApplicationServlet {
session.setAttribute(WebApplicationContext.class.getName(),
applicationContext);
} catch (IOException e) {
- logger.log(Level.WARNING,
+ getLogger().log(
+ Level.WARNING,
"Could not de-serialize ApplicationContext for "
+ session.getId()
+ " A new one will be created. ", e);
} catch (ClassNotFoundException e) {
- logger.log(Level.WARNING,
+ getLogger().log(
+ Level.WARNING,
"Could not de-serialize ApplicationContext for "
+ session.getId()
+ " A new one will be created. ", e);
@@ -368,8 +368,9 @@ public class GAEApplicationServlet extends ApplicationServlet {
List<Entity> entities = pq.asList(Builder
.withLimit(CLEANUP_LIMIT));
if (entities != null) {
- logger.info("Vaadin cleanup deleting " + entities.size()
- + " expired Vaadin sessions.");
+ getLogger().info(
+ "Vaadin cleanup deleting " + entities.size()
+ + " expired Vaadin sessions.");
List<Key> keys = new ArrayList<Key>();
for (Entity e : entities) {
keys.add(e.getKey());
@@ -387,8 +388,9 @@ public class GAEApplicationServlet extends ApplicationServlet {
List<Entity> entities = pq.asList(Builder
.withLimit(CLEANUP_LIMIT));
if (entities != null) {
- logger.info("Vaadin cleanup deleting " + entities.size()
- + " expired appengine sessions.");
+ getLogger().info(
+ "Vaadin cleanup deleting " + entities.size()
+ + " expired appengine sessions.");
List<Key> keys = new ArrayList<Key>();
for (Entity e : entities) {
keys.add(e.getKey());
@@ -397,7 +399,11 @@ public class GAEApplicationServlet extends ApplicationServlet {
}
}
} catch (Exception e) {
- logger.log(Level.WARNING, "Exception while cleaning.", e);
+ getLogger().log(Level.WARNING, "Exception while cleaning.", e);
}
}
+
+ private static final Logger getLogger() {
+ return Logger.getLogger(GAEApplicationServlet.class.getName());
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java b/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java
index 1cde164618..70ab452e4e 100644
--- a/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java
+++ b/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java
@@ -43,9 +43,6 @@ import com.vaadin.ui.CustomLayout;
@SuppressWarnings("serial")
public class JsonPaintTarget implements PaintTarget {
- private static final Logger logger = Logger.getLogger(JsonPaintTarget.class
- .getName());
-
/* Document type declarations */
private final static String UIDL_ARG_NAME = "name";
@@ -162,6 +159,7 @@ public class JsonPaintTarget implements PaintTarget {
* @throws Paintexception
* if the paint operation failed.
*/
+
public void endTag(String tagName) throws PaintException {
// In case of null data output nothing:
if (tagName == null) {
@@ -328,6 +326,7 @@ public class JsonPaintTarget implements PaintTarget {
* if the paint operation failed.
*
*/
+
public void addText(String str) throws PaintException {
tag.addData("\"" + escapeJSON(str) + "\"");
}
@@ -468,8 +467,8 @@ public class JsonPaintTarget implements PaintTarget {
tag.addVariable(new StringVariable(owner, name, escapeJSON(value)));
}
- public void addVariable(VariableOwner owner, String name,
- Component value) throws PaintException {
+ public void addVariable(VariableOwner owner, String name, Component value)
+ throws PaintException {
tag.addVariable(new StringVariable(owner, name, value.getConnectorId()));
}
@@ -516,6 +515,7 @@ public class JsonPaintTarget implements PaintTarget {
* @throws PaintException
* if the paint operation failed.
*/
+
public void addUploadStreamVariable(VariableOwner owner, String name)
throws PaintException {
startTag("uploadstream");
@@ -535,6 +535,7 @@ public class JsonPaintTarget implements PaintTarget {
* @throws PaintException
* if the paint operation failed.
*/
+
public void addSection(String sectionTagName, String sectionData)
throws PaintException {
tag.addData("{\"" + sectionTagName + "\":\"" + escapeJSON(sectionData)
@@ -549,6 +550,7 @@ public class JsonPaintTarget implements PaintTarget {
* @throws PaintException
* if the paint operation failed.
*/
+
public void addUIDL(String xml) throws PaintException {
// Ensure that the target is open
@@ -582,6 +584,7 @@ public class JsonPaintTarget implements PaintTarget {
* @see com.vaadin.terminal.PaintTarget#addXMLSection(String, String,
* String)
*/
+
public void addXMLSection(String sectionTagName, String sectionData,
String namespace) throws PaintException {
@@ -646,12 +649,14 @@ public class JsonPaintTarget implements PaintTarget {
* @see com.vaadin.terminal.PaintTarget#startPaintable(com.vaadin.terminal
* .Paintable, java.lang.String)
*/
+
public PaintStatus startPaintable(Component connector, String tagName)
throws PaintException {
boolean topLevelPaintable = openPaintables.isEmpty();
- logger.fine("startPaintable for " + connector.getClass().getName()
- + "@" + Integer.toHexString(connector.hashCode()));
+ getLogger().fine(
+ "startPaintable for " + connector.getClass().getName() + "@"
+ + Integer.toHexString(connector.hashCode()));
startTag(tagName, true);
openPaintables.push(connector);
@@ -672,8 +677,9 @@ public class JsonPaintTarget implements PaintTarget {
}
public void endPaintable(Component paintable) throws PaintException {
- logger.fine("endPaintable for " + paintable.getClass().getName() + "@"
- + Integer.toHexString(paintable.hashCode()));
+ getLogger().fine(
+ "endPaintable for " + paintable.getClass().getName() + "@"
+ + Integer.toHexString(paintable.hashCode()));
ClientConnector openPaintable = openPaintables.peek();
if (paintable != openPaintable) {
@@ -692,6 +698,7 @@ public class JsonPaintTarget implements PaintTarget {
*
* @see com.vaadin.terminal.PaintTarget#addCharacterData(java.lang.String )
*/
+
public void addCharacterData(String text) throws PaintException {
if (text != null) {
tag.addData(text);
@@ -998,8 +1005,13 @@ public class JsonPaintTarget implements PaintTarget {
*
* @see com.vaadin.terminal.PaintTarget#isFullRepaint()
*/
+
public boolean isFullRepaint() {
return !cacheEnabled;
}
+ private static final Logger getLogger() {
+ return Logger.getLogger(JsonPaintTarget.class.getName());
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java b/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java
index 661da57af6..de4f918b75 100644
--- a/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java
+++ b/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java
@@ -48,9 +48,6 @@ import com.vaadin.ui.Root;
@SuppressWarnings("serial")
public class PortletApplicationContext2 extends AbstractWebApplicationContext {
- private static final Logger logger = Logger
- .getLogger(PortletApplicationContext2.class.getName());
-
protected Map<Application, Set<PortletListener>> portletListeners = new HashMap<Application, Set<PortletListener>>();
protected transient PortletSession session;
@@ -76,11 +73,11 @@ public class PortletApplicationContext2 extends AbstractWebApplicationContext {
return new File(url.getFile());
} catch (final Exception e) {
// FIXME: Handle exception
- logger.log(
- Level.INFO,
- "Cannot access base directory, possible security issue "
- + "with Application Server or Servlet Container",
- e);
+ getLogger()
+ .log(Level.INFO,
+ "Cannot access base directory, possible security issue "
+ + "with Application Server or Servlet Container",
+ e);
}
}
return null;
@@ -419,4 +416,8 @@ public class PortletApplicationContext2 extends AbstractWebApplicationContext {
"Portlet mode can only be changed from a portlet request");
}
}
+
+ private Logger getLogger() {
+ return Logger.getLogger(PortletApplicationContext2.class.getName());
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/server/WebBrowser.java b/src/com/vaadin/terminal/gwt/server/WebBrowser.java
index 358f6f38fb..38b5409594 100644
--- a/src/com/vaadin/terminal/gwt/server/WebBrowser.java
+++ b/src/com/vaadin/terminal/gwt/server/WebBrowser.java
@@ -23,8 +23,6 @@ public class WebBrowser implements Terminal {
private int screenHeight = 0;
private int screenWidth = 0;
- private int clientHeight = 0;
- private int clientWidth = 0;
private String browserApplication = null;
private Locale locale;
private String address;
@@ -43,6 +41,7 @@ public class WebBrowser implements Terminal {
*
* @return Always returns null.
*/
+
public String getDefaultTheme() {
return null;
}
@@ -52,6 +51,7 @@ public class WebBrowser implements Terminal {
*
* @see com.vaadin.terminal.Terminal#getScreenHeight()
*/
+
public int getScreenHeight() {
return screenHeight;
}
@@ -61,35 +61,12 @@ public class WebBrowser implements Terminal {
*
* @see com.vaadin.terminal.Terminal#getScreenWidth()
*/
+
public int getScreenWidth() {
return screenWidth;
}
/**
- * Gets the height of the client (browser window).
- * <p>
- * Note that the client size is only updated on a full repaint, not when the
- * browser window size changes
- *
- * @return The height of the client or 0 if unknown.
- */
- public int getClientHeight() {
- return clientHeight;
- }
-
- /**
- * Gets the width of the client (browser window)
- * <p>
- * Note that the client size is only updated on a full repaint, not when the
- * browser window size changes
- *
- * @return The width of the client or 0 if unknown.
- */
- public int getClientWidth() {
- return clientWidth;
- }
-
- /**
* Get the browser user-agent string.
*
* @return The raw browser userAgent string
@@ -367,10 +344,6 @@ public class WebBrowser implements Terminal {
* Screen width
* @param sh
* Screen height
- * @param cw
- * Client width
- * @param ch
- * Client height
* @param tzo
* TimeZone offset in minutes from GMT
* @param rtzo
@@ -383,9 +356,9 @@ public class WebBrowser implements Terminal {
* the current date in milliseconds since the epoch
* @param touchDevice
*/
- void updateClientSideDetails(String sw, String sh, String cw, String ch,
- String tzo, String rtzo, String dstSavings, String dstInEffect,
- String curDate, boolean touchDevice) {
+ void updateClientSideDetails(String sw, String sh, String tzo, String rtzo,
+ String dstSavings, String dstInEffect, String curDate,
+ boolean touchDevice) {
if (sw != null) {
try {
screenHeight = Integer.parseInt(sh);
@@ -394,14 +367,6 @@ public class WebBrowser implements Terminal {
screenHeight = screenWidth = 0;
}
}
- if (cw != null) {
- try {
- clientHeight = Integer.parseInt(ch);
- clientWidth = Integer.parseInt(cw);
- } catch (final NumberFormatException e) {
- clientHeight = clientWidth = 0;
- }
- }
if (tzo != null) {
try {
// browser->java conversion: min->ms, reverse sign
@@ -462,8 +427,7 @@ public class WebBrowser implements Terminal {
if (request.getParameter("sw") != null) {
updateClientSideDetails(request.getParameter("sw"),
- request.getParameter("sh"), request.getParameter("cw"),
- request.getParameter("ch"), request.getParameter("tzo"),
+ request.getParameter("sh"), request.getParameter("tzo"),
request.getParameter("rtzo"), request.getParameter("dstd"),
request.getParameter("dston"),
request.getParameter("curdate"),
diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/AcceptCriteriaFactoryGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/AcceptCriteriaFactoryGenerator.java
index d8d3c23e0c..459b6ddd30 100644
--- a/src/com/vaadin/terminal/gwt/widgetsetutils/AcceptCriteriaFactoryGenerator.java
+++ b/src/com/vaadin/terminal/gwt/widgetsetutils/AcceptCriteriaFactoryGenerator.java
@@ -4,7 +4,6 @@
package com.vaadin.terminal.gwt.widgetsetutils;
import java.io.PrintWriter;
-import java.util.Collection;
import java.util.Date;
import com.google.gwt.core.ext.Generator;
@@ -16,14 +15,13 @@ import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
-import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
-import com.vaadin.event.dd.acceptcriteria.ClientCriterion;
+import com.vaadin.terminal.gwt.client.ui.dd.AcceptCriterion;
import com.vaadin.terminal.gwt.client.ui.dd.VAcceptCriterion;
import com.vaadin.terminal.gwt.client.ui.dd.VAcceptCriterionFactory;
/**
* GWT generator to build {@link VAcceptCriterionFactory} implementation
- * dynamically based on {@link ClientCriterion} annotations available in
+ * dynamically based on {@link AcceptCriterion} annotations available in
* classpath.
*
*/
@@ -102,21 +100,23 @@ public class AcceptCriteriaFactoryGenerator extends Generator {
sourceWriter.println("name = name.intern();");
- Collection<Class<? extends AcceptCriterion>> clientSideVerifiableCriterion = ClassPathExplorer
- .getCriterion();
-
- for (Class<? extends AcceptCriterion> class1 : clientSideVerifiableCriterion) {
- logger.log(Type.INFO,
- "creating mapping for " + class1.getCanonicalName());
- String canonicalName = class1.getCanonicalName();
- Class<? extends VAcceptCriterion> clientClass = class1
- .getAnnotation(ClientCriterion.class).value();
- sourceWriter.print("if (\"");
- sourceWriter.print(canonicalName);
- sourceWriter.print("\" == name) return GWT.create(");
- sourceWriter.print(clientClass.getCanonicalName());
- sourceWriter.println(".class );");
- sourceWriter.print("else ");
+ JClassType criteriaType = context.getTypeOracle().findType(
+ VAcceptCriterion.class.getName());
+ for (JClassType clientClass : criteriaType.getSubtypes()) {
+ AcceptCriterion annotation = clientClass
+ .getAnnotation(AcceptCriterion.class);
+ if (annotation != null) {
+ String clientClassName = clientClass.getQualifiedSourceName();
+ String serverClassName = clientClass.getAnnotation(
+ AcceptCriterion.class).value();
+ logger.log(Type.INFO, "creating mapping for " + serverClassName);
+ sourceWriter.print("if (\"");
+ sourceWriter.print(serverClassName);
+ sourceWriter.print("\" == name) return GWT.create(");
+ sourceWriter.print(clientClassName);
+ sourceWriter.println(".class );");
+ sourceWriter.print("else ");
+ }
}
sourceWriter.println("return null;");
diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java b/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java
index 6a0aa0f4c2..1c5b736492 100644
--- a/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java
+++ b/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java
@@ -6,33 +6,23 @@ package com.vaadin.terminal.gwt.widgetsetutils;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintStream;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.Attributes;
-import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.logging.Level;
import java.util.logging.Logger;
-import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
-import com.vaadin.event.dd.acceptcriteria.ClientCriterion;
-import com.vaadin.terminal.gwt.server.ClientConnector;
-
/**
* Utility class to collect widgetset related information from classpath.
* Utility will seek all directories from classpaths, and jar files having
@@ -53,9 +43,6 @@ import com.vaadin.terminal.gwt.server.ClientConnector;
*/
public class ClassPathExplorer {
- private static Logger logger = Logger.getLogger(ClassPathExplorer.class
- .getName());
-
private static final String VAADIN_ADDON_VERSION_ATTRIBUTE = "Vaadin-Package-Version";
/**
@@ -92,46 +79,6 @@ public class ClassPathExplorer {
}
/**
- * Finds server side widgets with ClientWidget annotation on the class path
- * (entries that can contain widgets/widgetsets - see
- * getRawClasspathEntries()).
- *
- * As a side effect, also accept criteria are searched under the same class
- * path entries and added into the acceptCriterion collection.
- *
- * @return a collection of {@link ClientConnector} classes
- */
- public static void findAcceptCriteria() {
- logger.info("Searching for accept criteria..");
- long start = System.currentTimeMillis();
- Set<String> keySet = classpathLocations.keySet();
- for (String url : keySet) {
- logger.fine("Searching for accept criteria in "
- + classpathLocations.get(url));
- searchForPaintables(classpathLocations.get(url), url);
- }
- long end = System.currentTimeMillis();
-
- logger.info("Search took " + (end - start) + "ms");
-
- }
-
- /**
- * Finds all accept criteria having client side counterparts (classes with
- * the {@link ClientCriterion} annotation).
- *
- * @return Collection of AcceptCriterion classes
- */
- public static Collection<Class<? extends AcceptCriterion>> getCriterion() {
- if (acceptCriterion.isEmpty()) {
- // accept criterion are searched as a side effect, normally after
- // paintable detection
- findAcceptCriteria();
- }
- return acceptCriterion;
- }
-
- /**
* Finds the names and locations of widgetsets available on the class path.
*
* @return map from widgetset classname to widgetset location URL
@@ -154,6 +101,7 @@ public class ClassPathExplorer {
sb.append(widgetsets.get(ws));
sb.append("\n");
}
+ final Logger logger = getLogger();
logger.info(sb.toString());
logger.info("Search took " + (end - start) + "ms");
return widgetsets;
@@ -214,7 +162,7 @@ public class ClassPathExplorer {
} catch (MalformedURLException e) {
// should never happen as based on an existing URL,
// only changing end of file name/path part
- logger.log(Level.SEVERE,
+ getLogger().log(Level.SEVERE,
"Error locating the widgetset " + classname, e);
}
}
@@ -250,7 +198,7 @@ public class ClassPathExplorer {
}
}
} catch (IOException e) {
- logger.log(Level.WARNING, "Error parsing jar file", e);
+ getLogger().log(Level.WARNING, "Error parsing jar file", e);
}
}
@@ -278,7 +226,7 @@ public class ClassPathExplorer {
classpath = classpath.substring(0, classpath.length() - 1);
}
- logger.fine("Classpath: " + classpath);
+ getLogger().fine("Classpath: " + classpath);
String[] split = classpath.split(pathSep);
for (int i = 0; i < split.length; i++) {
@@ -312,6 +260,7 @@ public class ClassPathExplorer {
include(null, file, locations);
}
long end = System.currentTimeMillis();
+ Logger logger = getLogger();
if (logger.isLoggable(Level.FINE)) {
logger.fine("getClassPathLocations took " + (end - start) + "ms");
}
@@ -352,7 +301,7 @@ public class ClassPathExplorer {
url = new URL("jar:" + url.toExternalForm() + "!/");
JarURLConnection conn = (JarURLConnection) url
.openConnection();
- logger.fine(url.toString());
+ getLogger().fine(url.toString());
JarFile jarFile = conn.getJarFile();
Manifest manifest = jarFile.getManifest();
if (manifest != null) {
@@ -363,9 +312,11 @@ public class ClassPathExplorer {
}
}
} catch (MalformedURLException e) {
- logger.log(Level.FINEST, "Failed to inspect JAR file", e);
+ getLogger().log(Level.FINEST, "Failed to inspect JAR file",
+ e);
} catch (IOException e) {
- logger.log(Level.FINEST, "Failed to inspect JAR file", e);
+ getLogger().log(Level.FINEST, "Failed to inspect JAR file",
+ e);
}
return false;
@@ -445,151 +396,6 @@ public class ClassPathExplorer {
}
/**
- * Searches for all paintable classes and accept criteria under a location
- * based on {@link ClientCriterion} annotations.
- *
- * Note that client criteria are updated directly to the
- * {@link #acceptCriterion} field, whereas paintables are added to the
- * paintables map given as a parameter.
- *
- * @param location
- * @param locationString
- */
- private final static void searchForPaintables(URL location,
- String locationString) {
-
- // Get a File object for the package
- File directory = new File(location.getFile());
-
- if (directory.exists() && !directory.isHidden()) {
- // Get the list of the files contained in the directory
- String[] files = directory.list();
- for (int i = 0; i < files.length; i++) {
- // we are only interested in .class files
- if (files[i].endsWith(".class")) {
- // remove the .class extension
- String classname = files[i].substring(0,
- files[i].length() - 6);
- String packageName = locationString
- .substring(locationString.lastIndexOf("/") + 1);
- classname = packageName + "." + classname;
- tryToAdd(classname);
- }
- }
- } else {
- try {
- // check files in jar file, entries will list all directories
- // and files in jar
-
- URLConnection openConnection = location.openConnection();
-
- if (openConnection instanceof JarURLConnection) {
- JarURLConnection conn = (JarURLConnection) openConnection;
-
- JarFile jarFile = conn.getJarFile();
-
- // Only scan for paintables in Vaadin add-ons
- if (!isVaadinAddon(jarFile)) {
- return;
- }
-
- Enumeration<JarEntry> e = jarFile.entries();
- while (e.hasMoreElements()) {
- JarEntry entry = e.nextElement();
- String entryname = entry.getName();
- if (!entry.isDirectory()
- && entryname.endsWith(".class")) {
- String classname = entryname.substring(0,
- entryname.length() - 6);
- if (classname.startsWith("/")) {
- classname = classname.substring(1);
- }
- classname = classname.replace('/', '.');
- tryToAdd(classname);
- }
- }
- }
- } catch (IOException e) {
- logger.warning(e.toString());
- }
- }
-
- }
-
- /**
- * A print stream that ignores all output.
- *
- * This is used to hide error messages from static initializers of classes
- * being inspected.
- */
- private static PrintStream devnull = new PrintStream(new OutputStream() {
- @Override
- public void write(int b) throws IOException {
- // NOP
- }
- });
-
- /**
- * Collection of all {@link AcceptCriterion} classes, updated as a side
- * effect of {@link #searchForPaintables(URL, String, Collection)} based on
- * {@link ClientCriterion} annotations.
- */
- private static Set<Class<? extends AcceptCriterion>> acceptCriterion = new HashSet<Class<? extends AcceptCriterion>>();
-
- /**
- * Checks a class for the {@link ClientCriterion} annotations, and adds it
- * to the appropriate collection.
- *
- * @param fullclassName
- */
- @SuppressWarnings("unchecked")
- private static void tryToAdd(final String fullclassName) {
- PrintStream out = System.out;
- PrintStream err = System.err;
- Throwable errorToShow = null;
- Level logLevel = null;
- try {
- System.setErr(devnull);
- System.setOut(devnull);
-
- Class<?> c = Class.forName(fullclassName);
-
- if (c.getAnnotation(ClientCriterion.class) != null) {
- acceptCriterion.add((Class<? extends AcceptCriterion>) c);
- }
- } catch (UnsupportedClassVersionError e) {
- // Inform the user about this as the class might contain a Paintable
- // Typically happens when using an add-on that is compiled using a
- // newer Java version.
- logLevel = Level.INFO;
- errorToShow = e;
- } catch (ClassNotFoundException e) {
- // Don't show to avoid flooding the user with irrelevant messages
- logLevel = Level.FINE;
- errorToShow = e;
- } catch (LinkageError e) {
- // Don't show to avoid flooding the user with irrelevant messages
- logLevel = Level.FINE;
- errorToShow = e;
- } catch (Exception e) {
- // Don't show to avoid flooding the user with irrelevant messages
- logLevel = Level.FINE;
- errorToShow = e;
- } finally {
- System.setErr(err);
- System.setOut(out);
- }
-
- // Must be done here after stderr and stdout have been reset.
- if (errorToShow != null && logLevel != null) {
- logger.log(logLevel,
- "Failed to load class " + fullclassName + ". "
- + errorToShow.getClass().getName() + ": "
- + errorToShow.getMessage());
- }
- }
-
- /**
* Find and return the default source directory where to create new
* widgetsets.
*
@@ -601,6 +407,9 @@ public class ClassPathExplorer {
* @return URL
*/
public static URL getDefaultSourceDirectory() {
+
+ final Logger logger = getLogger();
+
if (logger.isLoggable(Level.FINE)) {
logger.fine("classpathLocations values:");
ArrayList<String> locations = new ArrayList<String>(
@@ -632,44 +441,21 @@ public class ClassPathExplorer {
}
/**
- * Checks if the given jarFile is a Vaadin add-on.
- *
- * @param jarFile
- * @return true if the file is an add-on, false otherwise
- * @throws IOException
- */
- private static boolean isVaadinAddon(JarFile jarFile) throws IOException {
- Manifest manifest = jarFile.getManifest();
- if (manifest == null) {
- return false;
- }
- Attributes mainAttributes = manifest.getMainAttributes();
- if (mainAttributes == null) {
- return false;
- }
-
- return (mainAttributes.getValue(VAADIN_ADDON_VERSION_ATTRIBUTE) != null);
- }
-
- /**
* Test method for helper tool
*/
public static void main(String[] args) {
- ClassPathExplorer.findAcceptCriteria();
- logger.info("Found client criteria:");
- for (Class<? extends AcceptCriterion> cls : acceptCriterion) {
- logger.info(cls.getCanonicalName());
- }
-
- logger.info("");
- logger.info("Searching available widgetsets...");
+ getLogger().info("Searching available widgetsets...");
Map<String, URL> availableWidgetSets = ClassPathExplorer
.getAvailableWidgetSets();
for (String string : availableWidgetSets.keySet()) {
- logger.info(string + " in " + availableWidgetSets.get(string));
+ getLogger().info(string + " in " + availableWidgetSets.get(string));
}
}
+ private static final Logger getLogger() {
+ return Logger.getLogger(ClassPathExplorer.class.getName());
+ }
+
}
diff --git a/src/com/vaadin/tools/WidgetsetCompiler.java b/src/com/vaadin/tools/WidgetsetCompiler.java
index 618313a8d8..407f0e2387 100644
--- a/src/com/vaadin/tools/WidgetsetCompiler.java
+++ b/src/com/vaadin/tools/WidgetsetCompiler.java
@@ -36,9 +36,6 @@ import com.vaadin.terminal.gwt.widgetsetutils.WidgetSetBuilder;
@Deprecated
public class WidgetsetCompiler {
- private static final Logger logger = Logger
- .getLogger(WidgetsetCompiler.class.getName());
-
/**
* @param args
* same arguments as for com.google.gwt.dev.Compiler
@@ -75,7 +72,7 @@ public class WidgetsetCompiler {
String[].class);
method.invoke(null, new Object[] { args });
} catch (Throwable thr) {
- logger.log(Level.SEVERE,
+ getLogger().log(Level.SEVERE,
"Widgetset compilation failed", thr);
}
}
@@ -85,7 +82,11 @@ public class WidgetsetCompiler {
runThread.join();
System.out.println("Widgetset compilation finished");
} catch (Throwable thr) {
- logger.log(Level.SEVERE, "Widgetset compilation failed", thr);
+ getLogger().log(Level.SEVERE, "Widgetset compilation failed", thr);
}
}
+
+ private static final Logger getLogger() {
+ return Logger.getLogger(WidgetsetCompiler.class.getName());
+ }
}
diff --git a/src/com/vaadin/ui/AbstractJavaScriptComponent.java b/src/com/vaadin/ui/AbstractJavaScriptComponent.java
new file mode 100644
index 0000000000..95c45f55f9
--- /dev/null
+++ b/src/com/vaadin/ui/AbstractJavaScriptComponent.java
@@ -0,0 +1,161 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.ui;
+
+import com.vaadin.terminal.JavaScriptCallbackHelper;
+import com.vaadin.terminal.gwt.client.ui.JavaScriptComponentState;
+import com.vaadin.terminal.gwt.client.ui.JavaScriptWidget;
+
+/**
+ * Base class for Components with all client-side logic implemented using
+ * JavaScript.
+ * <p>
+ * When a new JavaScript component is initialized in the browser, the framework
+ * will look for a globally defined JavaScript function that will initialize the
+ * component. The name of the initialization function is formed by replacing .
+ * with _ in the name of the server-side class. If no such function is defined,
+ * each super class is used in turn until a match is found. The framework will
+ * thus first attempt with <code>com_example_MyComponent</code> for the
+ * server-side
+ * <code>com.example.MyComponent extends AbstractJavaScriptComponent</code>
+ * class. If MyComponent instead extends <code>com.example.SuperComponent</code>
+ * , then <code>com_example_SuperComponent</code> will also be attempted if
+ * <code>com_example_MyComponent</code> has not been defined.
+ * <p>
+ * JavaScript components have a very simple GWT widget ({@link JavaScriptWidget}
+ * ) just consisting of a <code>div</code> element to which the JavaScript code
+ * should initialize its own user interface.
+ * <p>
+ * The initialization function will be called with <code>this</code> pointing to
+ * a connector wrapper object providing integration to Vaadin with the following
+ * functions:
+ * <ul>
+ * <li><code>getConnectorId()</code> - returns a string with the id of the
+ * connector.</li>
+ * <li><code>getParentId([connectorId])</code> - returns a string with the id of
+ * the connector's parent. If <code>connectorId</code> is provided, the id of
+ * the parent of the corresponding connector with the passed id is returned
+ * instead.</li>
+ * <li><code>getWidgetElement([connectorId])</code> - returns the DOM Element
+ * that is the root of a connector's widget. <code>null</code> is returned if
+ * the connector can not be found or if the connector doesn't have a widget. If
+ * <code>connectorId</code> is not provided, the connector id of the current
+ * connector will be used.</li>
+ * <li><code>getState()</code> - returns an object corresponding to the shared
+ * state defined on the server. The scheme for conversion between Java and
+ * JavaScript types is described bellow.</li>
+ * <li><code>registerRpc([name, ] rpcObject)</code> - registers the
+ * <code>rpcObject</code> as a RPC handler. <code>rpcObject</code> should be an
+ * object with field containing functions for all eligible RPC functions. If
+ * <code>name</code> is provided, the RPC handler will only used for RPC calls
+ * for the RPC interface with the same fully qualified Java name. If no
+ * <code>name</code> is provided, the RPC handler will be used for all incoming
+ * RPC invocations where the RPC method name is defined as a function field in
+ * the handler. The scheme for conversion between Java types in the RPC
+ * interface definition and the JavaScript values passed as arguments to the
+ * handler functions is described bellow.</li>
+ * <li><code>getRpcProxy([name])</code> - returns an RPC proxy object. If
+ * <code>name</code> is provided, the proxy object will contain functions for
+ * all methods in the RPC interface with the same fully qualified name, provided
+ * a RPC handler has been registered by the server-side code. If no
+ * <code>name</code> is provided, the returned RPC proxy object will contain
+ * functions for all methods in all RPC interfaces registered for the connector
+ * on the server. If the same method name is present in multiple registered RPC
+ * interfaces, the corresponding function in the RPC proxy object will throw an
+ * exception when called. The scheme for conversion between Java types in the
+ * RPC interface and the JavaScript values that should be passed to the
+ * functions is described bellow.</li>
+ * </ul>
+ * The connector wrapper also supports these special functions:
+ * <ul>
+ * <li><code>onStateChange</code> - If the JavaScript code assigns a function to
+ * the field, that function is called whenever the contents of the shared state
+ * is changed.</li>
+ * <li>Any field name corresponding to a call to
+ * {@link #registerCallback(String, JavaScriptCallback)} on the server will
+ * automatically be present as a function that triggers the registered callback
+ * on the server.</li>
+ * <li>Any field name referred to using
+ * {@link #invokeCallback(String, Object...)} on the server will be called if a
+ * function has been assigned to the field.</li>
+ * </ul>
+ * <p>
+ *
+ * Values in the Shared State and in RPC calls are converted between Java and
+ * JavaScript using the following conventions:
+ * <ul>
+ * <li>Primitive Java numbers (byte, char, int, long, float, double) and their
+ * boxed types (Byte, Character, Integer, Long, Float, Double) are represented
+ * by JavaScript numbers.</li>
+ * <li>The primitive Java boolean and the boxed Boolean are represented by
+ * JavaScript booleans.</li>
+ * <li>Java Strings are represented by JavaScript strings.</li>
+ * <li>List, Set and all arrays in Java are represented by JavaScript arrays.</li>
+ * <li>Map<String, ?> in Java is represented by JavaScript object with fields
+ * corresponding to the map keys.</li>
+ * <li>Any other Java Map is represented by a JavaScript array containing two
+ * arrays, the first contains the keys and the second contains the values in the
+ * same order.</li>
+ * <li>A Java Bean is represented by a JavaScript object with fields
+ * corresponding to the bean's properties.</li>
+ * <li>A Java Connector is represented by a JavaScript string containing the
+ * connector's id.</li>
+ * <li>A pluggable serialization mechanism is provided for types not described
+ * here. Please refer to the documentation for specific types for serialization
+ * information.</li>
+ * </ul>
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class AbstractJavaScriptComponent extends AbstractComponent {
+ private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper(
+ this);
+
+ @Override
+ protected <T> void registerRpc(T implementation, Class<T> rpcInterfaceType) {
+ super.registerRpc(implementation, rpcInterfaceType);
+ callbackHelper.registerRpc(rpcInterfaceType);
+ }
+
+ /**
+ * Register a {@link JavaScriptCallback} that can be called from the
+ * JavaScript using the provided name. A JavaScript function with the
+ * provided name will be added to the connector wrapper object (initially
+ * available as <code>this</code>). Calling that JavaScript function will
+ * cause the call method in the registered {@link JavaScriptCallback} to be
+ * invoked with the same arguments.
+ *
+ * @param functionName
+ * the name that should be used for client-side callback
+ * @param javaScriptCallback
+ * the callback object that will be invoked when the JavaScript
+ * function is called
+ */
+ protected void registerCallback(String functionName,
+ JavaScriptCallback javaScriptCallback) {
+ callbackHelper.registerCallback(functionName, javaScriptCallback);
+ }
+
+ /**
+ * Invoke a named function that the connector JavaScript has added to the
+ * JavaScript connector wrapper object. The arguments should only contain
+ * data types that can be represented in JavaScript, including primitive
+ * boxing types, arrays, String, List, Set, Map, Connector and JavaBeans.
+ *
+ * @param name
+ * the name of the function
+ * @param arguments
+ * function arguments
+ */
+ protected void invokeCallback(String name, Object... arguments) {
+ callbackHelper.invokeCallback(name, arguments);
+ }
+
+ @Override
+ public JavaScriptComponentState getState() {
+ return (JavaScriptComponentState) super.getState();
+ }
+}
diff --git a/src/com/vaadin/ui/AbstractJavascriptComponent.java b/src/com/vaadin/ui/AbstractJavascriptComponent.java
deleted file mode 100644
index 0a26c10239..0000000000
--- a/src/com/vaadin/ui/AbstractJavascriptComponent.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.ui;
-
-import com.vaadin.terminal.JavascriptRpcHelper;
-
-public class AbstractJavascriptComponent extends AbstractComponent {
- private JavascriptRpcHelper rpcHelper = new JavascriptRpcHelper(this);
-
- protected void registerCallback(String functionName,
- JavascriptCallback javascriptCallback) {
- rpcHelper.registerCallback(functionName, javascriptCallback);
- }
-
- protected void invokeCallback(String name, Object... arguments) {
- rpcHelper.invokeCallback(name, arguments);
- }
-}
diff --git a/src/com/vaadin/ui/AbstractSelect.java b/src/com/vaadin/ui/AbstractSelect.java
index e586810b2d..6a927251af 100644
--- a/src/com/vaadin/ui/AbstractSelect.java
+++ b/src/com/vaadin/ui/AbstractSelect.java
@@ -24,7 +24,6 @@ import com.vaadin.event.Transferable;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropTarget;
import com.vaadin.event.dd.TargetDetailsImpl;
-import com.vaadin.event.dd.acceptcriteria.ClientCriterion;
import com.vaadin.event.dd.acceptcriteria.ClientSideCriterion;
import com.vaadin.event.dd.acceptcriteria.ContainsDataFlavor;
import com.vaadin.event.dd.acceptcriteria.TargetDetailIs;
@@ -33,8 +32,6 @@ import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.Vaadin6Component;
-import com.vaadin.terminal.gwt.client.ui.dd.VIsOverId;
-import com.vaadin.terminal.gwt.client.ui.dd.VItemIdIs;
import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation;
import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
@@ -1800,7 +1797,6 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
*
* @since 6.3
*/
- @ClientCriterion(VIsOverId.class)
public static class TargetItemIs extends AbstractItemSetCriterion {
/**
@@ -1867,7 +1863,6 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
*
* @since 6.3
*/
- @ClientCriterion(VItemIdIs.class)
public static class AcceptItem extends AbstractItemSetCriterion {
/**
diff --git a/src/com/vaadin/ui/AbstractSplitPanel.java b/src/com/vaadin/ui/AbstractSplitPanel.java
index 5205952621..876d39f2ae 100644
--- a/src/com/vaadin/ui/AbstractSplitPanel.java
+++ b/src/com/vaadin/ui/AbstractSplitPanel.java
@@ -22,7 +22,7 @@ import com.vaadin.tools.ReflectTools;
* AbstractSplitPanel.
*
* <code>AbstractSplitPanel</code> is base class for a component container that
- * can contain two components. The comopnents are split by a divider element.
+ * can contain two components. The components are split by a divider element.
*
* @author Vaadin Ltd.
* @version
@@ -31,7 +31,10 @@ import com.vaadin.tools.ReflectTools;
*/
public abstract class AbstractSplitPanel extends AbstractComponentContainer {
+ // TODO use Unit in AbstractSplitPanelState and remove these
private Unit posUnit;
+ private Unit posMinUnit;
+ private Unit posMaxUnit;
private AbstractSplitPanelRpc rpc = new AbstractSplitPanelRpc() {
@@ -41,13 +44,14 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
}
public void setSplitterPosition(float position) {
- getState().getSplitterState().setPosition(position);
+ getSplitterState().setPosition(position);
}
};
public AbstractSplitPanel() {
registerRpc(rpc);
setSplitPosition(50, Unit.PERCENTAGE, false);
+ setSplitPositionLimits(0, Unit.PERCENTAGE, 100, Unit.PERCENTAGE);
}
/**
@@ -101,6 +105,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
* @param c
* the component to be added.
*/
+
@Override
public void addComponent(Component c) {
if (getFirstComponent() == null) {
@@ -188,6 +193,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
* @param c
* the component to be removed.
*/
+
@Override
public void removeComponent(Component c) {
super.removeComponent(c);
@@ -204,6 +210,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
*
* @see com.vaadin.ui.ComponentContainer#getComponentIterator()
*/
+
public Iterator<Component> getComponentIterator() {
return new ComponentIterator();
}
@@ -214,6 +221,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
*
* @return the number of contained components (zero, one or two)
*/
+
public int getComponentCount() {
int count = 0;
if (getFirstComponent() != null) {
@@ -226,6 +234,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
}
/* Documented in superclass */
+
public void replaceComponent(Component oldComponent, Component newComponent) {
if (oldComponent == getFirstComponent()) {
setFirstComponent(newComponent);
@@ -297,7 +306,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
if (unit != Unit.PERCENTAGE) {
pos = Math.round(pos);
}
- SplitterState splitterState = getState().getSplitterState();
+ SplitterState splitterState = getSplitterState();
splitterState.setPosition(pos);
splitterState.setPositionUnit(unit.getSymbol());
splitterState.setPositionReversed(reverse);
@@ -313,7 +322,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
* @return position of the splitter
*/
public float getSplitPosition() {
- return getState().getSplitterState().getPosition();
+ return getSplitterState().getPosition();
}
/**
@@ -326,6 +335,110 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
}
/**
+ * Sets the minimum split position to the given position and unit. If the
+ * split position is reversed, maximum and minimum are also reversed.
+ *
+ * @param pos
+ * the minimum position of the split
+ * @param unit
+ * the unit (from {@link Sizeable}) in which the size is given.
+ * Allowed units are UNITS_PERCENTAGE and UNITS_PIXELS
+ */
+ public void setMinSplitPosition(int pos, Unit unit) {
+ setSplitPositionLimits(pos, unit, getSplitterState().getMaxPosition(),
+ posMaxUnit);
+ }
+
+ /**
+ * Returns the current minimum position of the splitter, in
+ * {@link #getMinSplitPositionUnit()} units.
+ *
+ * @return the minimum position of the splitter
+ */
+ public float getMinSplitPosition() {
+ return getSplitterState().getMinPosition();
+ }
+
+ /**
+ * Returns the unit of the minimum position of the splitter.
+ *
+ * @return the unit of the minimum position of the splitter
+ */
+ public Unit getMinSplitPositionUnit() {
+ return posMinUnit;
+ }
+
+ /**
+ * Sets the maximum split position to the given position and unit. If the
+ * split position is reversed, maximum and minimum are also reversed.
+ *
+ * @param pos
+ * the maximum position of the split
+ * @param unit
+ * the unit (from {@link Sizeable}) in which the size is given.
+ * Allowed units are UNITS_PERCENTAGE and UNITS_PIXELS
+ */
+ public void setMaxSplitPosition(float pos, Unit unit) {
+ setSplitPositionLimits(getSplitterState().getMinPosition(), posMinUnit,
+ pos, unit);
+ }
+
+ /**
+ * Returns the current maximum position of the splitter, in
+ * {@link #getMaxSplitPositionUnit()} units.
+ *
+ * @return the maximum position of the splitter
+ */
+ public float getMaxSplitPosition() {
+ return getSplitterState().getMaxPosition();
+ }
+
+ /**
+ * Returns the unit of the maximum position of the splitter
+ *
+ * @return the unit of the maximum position of the splitter
+ */
+ public Unit getMaxSplitPositionUnit() {
+ return posMaxUnit;
+ }
+
+ /**
+ * Sets the maximum and minimum position of the splitter. If the split
+ * position is reversed, maximum and minimum are also reversed.
+ *
+ * @param minPos
+ * the new minimum position
+ * @param minPosUnit
+ * the unit (from {@link Sizeable}) in which the minimum position
+ * is given.
+ * @param maxPos
+ * the new maximum position
+ * @param maxPosUnit
+ * the unit (from {@link Sizeable}) in which the maximum position
+ * is given.
+ */
+ private void setSplitPositionLimits(float minPos, Unit minPosUnit,
+ float maxPos, Unit maxPosUnit) {
+ if ((minPosUnit != Unit.PERCENTAGE && minPosUnit != Unit.PIXELS)
+ || (maxPosUnit != Unit.PERCENTAGE && maxPosUnit != Unit.PIXELS)) {
+ throw new IllegalArgumentException(
+ "Only percentage and pixel units are allowed");
+ }
+
+ SplitterState state = getSplitterState();
+
+ state.setMinPosition(minPos);
+ state.setMinPositionUnit(minPosUnit.getSymbol());
+ posMinUnit = minPosUnit;
+
+ state.setMaxPosition(maxPos);
+ state.setMaxPositionUnit(maxPosUnit.getSymbol());
+ posMaxUnit = maxPosUnit;
+
+ requestRepaint();
+ }
+
+ /**
* Lock the SplitPanels position, disabling the user from dragging the split
* handle.
*
@@ -333,7 +446,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
* Set <code>true</code> if locked, <code>false</code> otherwise.
*/
public void setLocked(boolean locked) {
- getState().getSplitterState().setLocked(locked);
+ getSplitterState().setLocked(locked);
requestRepaint();
}
@@ -344,7 +457,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
* @return <code>true</code> if locked, <code>false</code> otherwise.
*/
public boolean isLocked() {
- return getState().getSplitterState().isLocked();
+ return getSplitterState().isLocked();
}
/**
@@ -394,4 +507,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
return (AbstractSplitPanelState) super.getState();
}
+ private SplitterState getSplitterState() {
+ return getState().getSplitterState();
+ }
}
diff --git a/src/com/vaadin/ui/Button.java b/src/com/vaadin/ui/Button.java
index 876fe593e2..8e504d828b 100644
--- a/src/com/vaadin/ui/Button.java
+++ b/src/com/vaadin/ui/Button.java
@@ -38,6 +38,7 @@ public class Button extends AbstractComponent implements
Action.ShortcutNotifier {
private ButtonServerRpc rpc = new ButtonServerRpc() {
+
public void click(MouseEventDetails mouseEventDetails) {
fireClick(mouseEventDetails);
}
@@ -50,6 +51,7 @@ public class Button extends AbstractComponent implements
};
FocusAndBlurServerRpcImpl focusBlurRpc = new FocusAndBlurServerRpcImpl(this) {
+
@Override
protected void fireEvent(Event event) {
Button.this.fireEvent(event);
diff --git a/src/com/vaadin/ui/HelloWorldExtension.java b/src/com/vaadin/ui/HelloWorldExtension.java
index 6d9ce9bcf1..e705954f2e 100644
--- a/src/com/vaadin/ui/HelloWorldExtension.java
+++ b/src/com/vaadin/ui/HelloWorldExtension.java
@@ -13,7 +13,7 @@ public class HelloWorldExtension extends AbstractExtension {
public HelloWorldExtension() {
registerRpc(new HelloWorldRpc() {
public void onMessageSent(String message) {
- getRoot().showNotification(message);
+ Notification.show(message);
}
});
}
diff --git a/src/com/vaadin/ui/JavaScript.java b/src/com/vaadin/ui/JavaScript.java
new file mode 100644
index 0000000000..d256717711
--- /dev/null
+++ b/src/com/vaadin/ui/JavaScript.java
@@ -0,0 +1,146 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.ui;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.vaadin.external.json.JSONArray;
+import com.vaadin.external.json.JSONException;
+import com.vaadin.terminal.AbstractExtension;
+import com.vaadin.terminal.Page;
+import com.vaadin.terminal.gwt.client.communication.ServerRpc;
+import com.vaadin.terminal.gwt.client.extensions.javascriptmanager.ExecuteJavaScriptRpc;
+import com.vaadin.terminal.gwt.client.extensions.javascriptmanager.JavaScriptManagerState;
+
+/**
+ * Provides access to JavaScript functionality in the web browser. To get an
+ * instance of JavaScript, either use Page.getJavaScript() or
+ * JavaScript.getCurrent() as a shorthand for getting the JavaScript object
+ * corresponding to the current Page.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class JavaScript extends AbstractExtension {
+ private Map<String, JavaScriptCallback> callbacks = new HashMap<String, JavaScriptCallback>();
+
+ // Can not be defined in client package as this JSONArray is not available
+ // in GWT
+ public interface JavaScriptCallbackRpc extends ServerRpc {
+ public void call(String name, JSONArray arguments);
+ }
+
+ /**
+ * Creates a new JavaScript object. You should typically not this, but
+ * instead use the JavaScript object already associated with your Page
+ * object.
+ */
+ public JavaScript() {
+ registerRpc(new JavaScriptCallbackRpc() {
+ public void call(String name, JSONArray arguments) {
+ JavaScriptCallback callback = callbacks.get(name);
+ // TODO handle situation if name is not registered
+ try {
+ callback.call(arguments);
+ } catch (JSONException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ });
+ }
+
+ @Override
+ public JavaScriptManagerState getState() {
+ return (JavaScriptManagerState) super.getState();
+ }
+
+ /**
+ * Add a new function to the global JavaScript namespace (i.e. the window
+ * object). The <code>call</code> method in the passed
+ * {@link JavaScriptCallback} object will be invoked with the same
+ * parameters whenever the JavaScript function is called in the browser.
+ *
+ * A callback added with the name <code>"myCallback"</code> can thus be
+ * invoked with the following JavaScript code:
+ * <code>window.myCallback(argument1, argument2)</code>.
+ *
+ * If the name parameter contains dots, simple objects are created on demand
+ * to allow calling the function using the same name (e.g.
+ * <code>window.myObject.myFunction</code>).
+ *
+ * @param name
+ * the name that the callback function should get in the global
+ * JavaScript namespace.
+ * @param callback
+ * the JavaScriptCallback that will be invoked if the JavaScript
+ * function is called.
+ */
+ public void addCallback(String name, JavaScriptCallback callback) {
+ callbacks.put(name, callback);
+ if (getState().getNames().add(name)) {
+ requestRepaint();
+ }
+ }
+
+ /**
+ * Removes a JavaScripCallback from the browser's global JavaScript
+ * namespace.
+ *
+ * If the name contains dots and intermediate were created by
+ * {@link #addCallback(String, JavaScriptCallback)}addCallback, these
+ * objects will not be removed when the callback is removed.
+ *
+ * @param name
+ * the name of the callback to remove
+ */
+ public void removeCallback(String name) {
+ callbacks.remove(name);
+ if (getState().getNames().remove(name)) {
+ requestRepaint();
+ }
+ }
+
+ /**
+ * Executes the given JavaScript code in the browser.
+ *
+ * @param script
+ * The JavaScript code to run.
+ */
+ public void execute(String script) {
+ getRpcProxy(ExecuteJavaScriptRpc.class).executeJavaScript(script);
+ }
+
+ /**
+ * Get the JavaScript object for the current Page, or null if there is no
+ * current page.
+ *
+ * @see Page#getCurrent()
+ *
+ * @return the JavaScript object corresponding to the current Page, or
+ * <code>null</code> if there is no current page.
+ */
+ public static JavaScript getCurrent() {
+ Page page = Page.getCurrent();
+ if (page == null) {
+ return null;
+ }
+ return page.getJavaScript();
+ }
+
+ /**
+ * JavaScript is not designed to be removed.
+ *
+ * @throws UnsupportedOperationException
+ * when invoked
+ */
+ @Override
+ public void removeFromTarget() {
+ throw new UnsupportedOperationException(
+ "JavaScript is not designed to be removed.");
+ }
+
+}
diff --git a/src/com/vaadin/ui/JavaScriptCallback.java b/src/com/vaadin/ui/JavaScriptCallback.java
new file mode 100644
index 0000000000..49f7695e89
--- /dev/null
+++ b/src/com/vaadin/ui/JavaScriptCallback.java
@@ -0,0 +1,41 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.ui;
+
+import java.io.Serializable;
+
+import com.vaadin.external.json.JSONArray;
+import com.vaadin.external.json.JSONException;
+import com.vaadin.terminal.AbstractJavaScriptExtension;
+
+/**
+ * Defines a method that is called by a client-side JavaScript function. When
+ * the corresponding JavaScript function is called, the {@link #call(JSONArray)}
+ * method is invoked.
+ *
+ * @see JavaScript#addCallback(String, JavaScriptCallback)
+ * @see AbstractJavaScriptComponent#registerCallback(String, JavaScriptCallback)
+ * @see AbstractJavaScriptExtension#registerCallback(String, JavaScriptCallback)
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public interface JavaScriptCallback extends Serializable {
+ /**
+ * Invoked whenever the corresponding JavaScript function is called in the
+ * browser.
+ * <p>
+ * Because of the asynchronous nature of the communication between client
+ * and server, no return value can be sent back to the browser.
+ *
+ * @param arguments
+ * an array with JSON representations of the arguments with which
+ * the JavaScript function was called.
+ * @throws JSONException
+ * if the arguments can not be interpreted
+ */
+ public void call(JSONArray arguments) throws JSONException;
+}
diff --git a/src/com/vaadin/ui/JavascriptCallback.java b/src/com/vaadin/ui/JavascriptCallback.java
deleted file mode 100644
index 89700b3faf..0000000000
--- a/src/com/vaadin/ui/JavascriptCallback.java
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.ui;
-
-import java.io.Serializable;
-
-import com.vaadin.external.json.JSONArray;
-import com.vaadin.external.json.JSONException;
-
-public interface JavascriptCallback extends Serializable {
- public void call(JSONArray arguments) throws JSONException;
-}
diff --git a/src/com/vaadin/ui/JavascriptManager.java b/src/com/vaadin/ui/JavascriptManager.java
deleted file mode 100644
index 72295dce2b..0000000000
--- a/src/com/vaadin/ui/JavascriptManager.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.ui;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import com.vaadin.external.json.JSONArray;
-import com.vaadin.external.json.JSONException;
-import com.vaadin.terminal.AbstractExtension;
-import com.vaadin.terminal.gwt.client.communication.ServerRpc;
-import com.vaadin.terminal.gwt.client.extensions.javascriptmanager.JavascriptManagerState;
-
-public class JavascriptManager extends AbstractExtension {
- private Map<String, JavascriptCallback> callbacks = new HashMap<String, JavascriptCallback>();
-
- // Can not be defined in client package as this JSONArray is not available
- // in GWT
- public interface JavascriptCallbackRpc extends ServerRpc {
- public void call(String name, JSONArray arguments);
- }
-
- public JavascriptManager() {
- registerRpc(new JavascriptCallbackRpc() {
- public void call(String name, JSONArray arguments) {
- JavascriptCallback callback = callbacks.get(name);
- // TODO handle situation if name is not registered
- try {
- callback.call(arguments);
- } catch (JSONException e) {
- throw new IllegalArgumentException(e);
- }
- }
- });
- }
-
- @Override
- public JavascriptManagerState getState() {
- return (JavascriptManagerState) super.getState();
- }
-
- public void addCallback(String name, JavascriptCallback javascriptCallback) {
- callbacks.put(name, javascriptCallback);
- if (getState().getNames().add(name)) {
- requestRepaint();
- }
- }
-
- public void removeCallback(String name) {
- callbacks.remove(name);
- if (getState().getNames().remove(name)) {
- requestRepaint();
- }
- }
-
-}
diff --git a/src/com/vaadin/ui/Link.java b/src/com/vaadin/ui/Link.java
index ed5ffbba3a..db0dc58e6b 100644
--- a/src/com/vaadin/ui/Link.java
+++ b/src/com/vaadin/ui/Link.java
@@ -6,6 +6,7 @@ package com.vaadin.ui;
import java.util.Map;
+import com.vaadin.terminal.Page;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
@@ -23,13 +24,13 @@ import com.vaadin.terminal.Vaadin6Component;
public class Link extends AbstractComponent implements Vaadin6Component {
/* Target window border type constant: No window border */
- public static final int TARGET_BORDER_NONE = Root.BORDER_NONE;
+ public static final int TARGET_BORDER_NONE = Page.BORDER_NONE;
/* Target window border type constant: Minimal window border */
- public static final int TARGET_BORDER_MINIMAL = Root.BORDER_MINIMAL;
+ public static final int TARGET_BORDER_MINIMAL = Page.BORDER_MINIMAL;
/* Target window border type constant: Default window border */
- public static final int TARGET_BORDER_DEFAULT = Root.BORDER_DEFAULT;
+ public static final int TARGET_BORDER_DEFAULT = Page.BORDER_DEFAULT;
private Resource resource = null;
diff --git a/src/com/vaadin/ui/Notification.java b/src/com/vaadin/ui/Notification.java
index bb1f874635..075ab50196 100644
--- a/src/com/vaadin/ui/Notification.java
+++ b/src/com/vaadin/ui/Notification.java
@@ -6,6 +6,7 @@ package com.vaadin.ui;
import java.io.Serializable;
+import com.vaadin.terminal.Page;
import com.vaadin.terminal.Resource;
/**
@@ -318,4 +319,118 @@ public class Notification implements Serializable {
public boolean isHtmlContentAllowed() {
return htmlContentAllowed;
}
+
+ public void show() {
+ Page.getCurrent().showNotification(this);
+ }
+
+ /**
+ * Shows a notification message on the middle of the current page. The
+ * message automatically disappears ("humanized message").
+ *
+ * Care should be taken to to avoid XSS vulnerabilities as the caption is
+ * rendered as html.
+ *
+ * @see #showNotification(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The message
+ */
+ public static void show(String caption) {
+ new Notification(caption).show();
+ }
+
+ /**
+ * Shows a notification message the current page. The position and behavior
+ * of the message depends on the type, which is one of the basic types
+ * defined in {@link Notification}, for instance
+ * Notification.TYPE_WARNING_MESSAGE.
+ *
+ * Care should be taken to to avoid XSS vulnerabilities as the caption is
+ * rendered as html.
+ *
+ * @see #showNotification(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The message
+ * @param type
+ * The message type
+ */
+ public static void show(String caption, int type) {
+ new Notification(caption, type).show();
+ }
+
+ /**
+ * Shows a notification consisting of a bigger caption and a smaller
+ * description on the middle of the current page. The message automatically
+ * disappears ("humanized message").
+ *
+ * Care should be taken to to avoid XSS vulnerabilities as the caption and
+ * description are rendered as html.
+ *
+ * @see #showNotification(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The caption of the message
+ * @param description
+ * The message description
+ *
+ */
+ public static void show(String caption, String description) {
+ new Notification(caption, description).show();
+ }
+
+ /**
+ * Shows a notification consisting of a bigger caption and a smaller
+ * description. The position and behavior of the message depends on the
+ * type, which is one of the basic types defined in {@link Notification},
+ * for instance Notification.TYPE_WARNING_MESSAGE.
+ *
+ * Care should be taken to to avoid XSS vulnerabilities as the caption and
+ * description are rendered as html.
+ *
+ * @see #showNotification(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The caption of the message
+ * @param description
+ * The message description
+ * @param type
+ * The message type
+ */
+ public static void show(String caption, String description, int type) {
+
+ new Notification(caption, description, type).show();
+ }
+
+ /**
+ * Shows a notification consisting of a bigger caption and a smaller
+ * description. The position and behavior of the message depends on the
+ * type, which is one of the basic types defined in {@link Notification},
+ * for instance Notification.TYPE_WARNING_MESSAGE.
+ *
+ * Care should be taken to avoid XSS vulnerabilities if html content is
+ * allowed.
+ *
+ * @see #showNotification(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The message caption
+ * @param description
+ * The message description
+ * @param type
+ * The type of message
+ * @param htmlContentAllowed
+ * Whether html in the caption and description should be
+ * displayed as html or as plain text
+ */
+ public static void show(String caption, String description, int type,
+ boolean htmlContentAllowed) {
+ new Notification(caption, description, type, htmlContentAllowed).show();
+ }
} \ No newline at end of file
diff --git a/src/com/vaadin/ui/Root.java b/src/com/vaadin/ui/Root.java
index 9814084cbc..50ad99571e 100644
--- a/src/com/vaadin/ui/Root.java
+++ b/src/com/vaadin/ui/Root.java
@@ -4,8 +4,6 @@
package com.vaadin.ui;
-import java.io.Serializable;
-import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
@@ -13,8 +11,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
import java.util.Map;
import com.vaadin.Application;
@@ -24,6 +20,9 @@ import com.vaadin.event.Action.Handler;
import com.vaadin.event.ActionManager;
import com.vaadin.event.MouseEvents.ClickEvent;
import com.vaadin.event.MouseEvents.ClickListener;
+import com.vaadin.terminal.Page;
+import com.vaadin.terminal.Page.BrowserWindowResizeEvent;
+import com.vaadin.terminal.Page.BrowserWindowResizeListener;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
@@ -31,11 +30,9 @@ import com.vaadin.terminal.Vaadin6Component;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.terminal.WrappedRequest.BrowserDetails;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.ui.notification.VNotification;
import com.vaadin.terminal.gwt.client.ui.root.RootServerRpc;
import com.vaadin.terminal.gwt.client.ui.root.RootState;
import com.vaadin.terminal.gwt.client.ui.root.VRoot;
-import com.vaadin.tools.ReflectTools;
import com.vaadin.ui.Window.CloseListener;
/**
@@ -79,121 +76,6 @@ public abstract class Root extends AbstractComponentContainer implements
Action.Container, Action.Notifier, Vaadin6Component {
/**
- * Listener that gets notified when the size of the browser window
- * containing the root has changed.
- *
- * @see Root#addListener(BrowserWindowResizeListener)
- */
- public interface BrowserWindowResizeListener extends Serializable {
- /**
- * Invoked when the browser window containing a Root has been resized.
- *
- * @param event
- * a browser window resize event
- */
- public void browserWindowResized(BrowserWindowResizeEvent event);
- }
-
- /**
- * Event that is fired when a browser window containing a root is resized.
- */
- public class BrowserWindowResizeEvent extends Component.Event {
-
- private final int width;
- private final int height;
-
- /**
- * Creates a new event
- *
- * @param source
- * the root for which the browser window has been resized
- * @param width
- * the new width of the browser window
- * @param height
- * the new height of the browser window
- */
- public BrowserWindowResizeEvent(Root source, int width, int height) {
- super(source);
- this.width = width;
- this.height = height;
- }
-
- @Override
- public Root getSource() {
- return (Root) super.getSource();
- }
-
- /**
- * Gets the new browser window height
- *
- * @return an integer with the new pixel height of the browser window
- */
- public int getHeight() {
- return height;
- }
-
- /**
- * Gets the new browser window width
- *
- * @return an integer with the new pixel width of the browser window
- */
- public int getWidth() {
- return width;
- }
- }
-
- private static final Method BROWSWER_RESIZE_METHOD = ReflectTools
- .findMethod(BrowserWindowResizeListener.class,
- "browserWindowResized", BrowserWindowResizeEvent.class);
-
- /**
- * Listener that listens changes in URI fragment.
- */
- public interface FragmentChangedListener extends Serializable {
- public void fragmentChanged(FragmentChangedEvent event);
- }
-
- /**
- * Event fired when uri fragment changes.
- */
- public class FragmentChangedEvent extends Component.Event {
-
- /**
- * The new uri fragment
- */
- private final String fragment;
-
- /**
- * Creates a new instance of UriFragmentReader change event.
- *
- * @param source
- * the Source of the event.
- */
- public FragmentChangedEvent(Root source, String fragment) {
- super(source);
- this.fragment = fragment;
- }
-
- /**
- * Gets the root in which the fragment has changed.
- *
- * @return the root in which the fragment has changed
- */
- public Root getRoot() {
- return (Root) getComponent();
- }
-
- /**
- * Get the new fragment
- *
- * @return the new fragment
- */
- public String getFragment() {
- return fragment;
- }
- }
-
- /**
* Helper class to emulate the main window from Vaadin 6 using roots. This
* class should be used in the same way as Window used as a browser level
* window in Vaadin 6 with {@link com.vaadin.Application.LegacyApplication}
@@ -312,55 +194,337 @@ public abstract class Root extends AbstractComponentContainer implements
"Internal problem getting window URL, please report");
}
}
- }
- private static final Method FRAGMENT_CHANGED_METHOD;
-
- static {
- try {
- FRAGMENT_CHANGED_METHOD = FragmentChangedListener.class
- .getDeclaredMethod("fragmentChanged",
- new Class[] { FragmentChangedEvent.class });
- } catch (final java.lang.NoSuchMethodException e) {
- // This should never happen
- throw new java.lang.RuntimeException(
- "Internal error finding methods in FragmentChangedListener");
+ /**
+ * Opens the given resource in this root. The contents of this Root is
+ * replaced by the {@code Resource}.
+ *
+ * @param resource
+ * the resource to show in this root
+ *
+ * @deprecated As of 7.0, use getPage().open instead
+ */
+ @Deprecated
+ public void open(Resource resource) {
+ getPage().open(resource);
}
- }
- /**
- * A border style used for opening resources in a window without a border.
- */
- public static final int BORDER_NONE = 0;
+ /* ********************************************************************* */
- /**
- * A border style used for opening resources in a window with a minimal
- * border.
- */
- public static final int BORDER_MINIMAL = 1;
+ /**
+ * Opens the given resource in a window with the given name.
+ * <p>
+ * The supplied {@code windowName} is used as the target name in a
+ * window.open call in the client. This means that special values such
+ * as "_blank", "_self", "_top", "_parent" have special meaning. An
+ * empty or <code>null</code> window name is also a special case.
+ * </p>
+ * <p>
+ * "", null and "_self" as {@code windowName} all causes the resource to
+ * be opened in the current window, replacing any old contents. For
+ * downloadable content you should avoid "_self" as "_self" causes the
+ * client to skip rendering of any other changes as it considers them
+ * irrelevant (the page will be replaced by the resource). This can
+ * speed up the opening of a resource, but it might also put the client
+ * side into an inconsistent state if the window content is not
+ * completely replaced e.g., if the resource is downloaded instead of
+ * displayed in the browser.
+ * </p>
+ * <p>
+ * "_blank" as {@code windowName} causes the resource to always be
+ * opened in a new window or tab (depends on the browser and browser
+ * settings).
+ * </p>
+ * <p>
+ * "_top" and "_parent" as {@code windowName} works as specified by the
+ * HTML standard.
+ * </p>
+ * <p>
+ * Any other {@code windowName} will open the resource in a window with
+ * that name, either by opening a new window/tab in the browser or by
+ * replacing the contents of an existing window with that name.
+ * </p>
+ *
+ * @param resource
+ * the resource.
+ * @param windowName
+ * the name of the window.
+ * @deprecated As of 7.0, use getPage().open instead
+ */
+ @Deprecated
+ public void open(Resource resource, String windowName) {
+ getPage().open(resource, windowName);
+ }
- /**
- * A border style that indicates that the default border style should be
- * used when opening resources.
- */
- public static final int BORDER_DEFAULT = 2;
+ /**
+ * Opens the given resource in a window with the given size, border and
+ * name. For more information on the meaning of {@code windowName}, see
+ * {@link #open(Resource, String)}.
+ *
+ * @param resource
+ * the resource.
+ * @param windowName
+ * the name of the window.
+ * @param width
+ * the width of the window in pixels
+ * @param height
+ * the height of the window in pixels
+ * @param border
+ * the border style of the window. See {@link #BORDER_NONE
+ * Window.BORDER_* constants}
+ * @deprecated As of 7.0, use getPage().open instead
+ */
+ @Deprecated
+ public void open(Resource resource, String windowName, int width,
+ int height, int border) {
+ getPage().open(resource, windowName, width, height, border);
+ }
- /**
- * The application to which this root belongs
- */
- private Application application;
+ /**
+ * Adds a new {@link BrowserWindowResizeListener} to this root. The
+ * listener will be notified whenever the browser window within which
+ * this root resides is resized.
+ *
+ * @param resizeListener
+ * the listener to add
+ *
+ * @see BrowserWindowResizeListener#browserWindowResized(BrowserWindowResizeEvent)
+ * @see #setResizeLazy(boolean)
+ *
+ * @deprecated As of 7.0, use the similarly named api in Page instead
+ */
+ @Deprecated
+ public void addListener(BrowserWindowResizeListener resizeListener) {
+ getPage().addListener(resizeListener);
+ }
- /**
- * A list of notifications that are waiting to be sent to the client.
- * Cleared (set to null) when the notifications have been sent.
- */
- private List<Notification> notifications;
+ /**
+ * Removes a {@link BrowserWindowResizeListener} from this root. The
+ * listener will no longer be notified when the browser window is
+ * resized.
+ *
+ * @param resizeListener
+ * the listener to remove
+ * @deprecated As of 7.0, use the similarly named api in Page instead
+ */
+ @Deprecated
+ public void removeListener(BrowserWindowResizeListener resizeListener) {
+ getPage().removeListener(resizeListener);
+ }
+
+ /**
+ * Gets the last known height of the browser window in which this root
+ * resides.
+ *
+ * @return the browser window height in pixels
+ * @deprecated As of 7.0, use the similarly named api in Page instead
+ */
+ @Deprecated
+ public int getBrowserWindowHeight() {
+ return getPage().getBrowserWindowHeight();
+ }
+
+ /**
+ * Gets the last known width of the browser window in which this root
+ * resides.
+ *
+ * @return the browser window width in pixels
+ *
+ * @deprecated As of 7.0, use the similarly named api in Page instead
+ */
+ @Deprecated
+ public int getBrowserWindowWidth() {
+ return getPage().getBrowserWindowWidth();
+ }
+
+ /**
+ * Shows a notification message on the middle of the root. The message
+ * automatically disappears ("humanized message").
+ *
+ * Care should be taken to to avoid XSS vulnerabilities as the caption
+ * is rendered as html.
+ *
+ * @see #showNotification(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The message
+ *
+ * @deprecated As of 7.0, use Notification.show instead
+ */
+ @Deprecated
+ public void showNotification(String caption) {
+ getPage().showNotification(new Notification(caption));
+ }
+
+ /**
+ * Shows a notification message the root. The position and behavior of
+ * the message depends on the type, which is one of the basic types
+ * defined in {@link Notification}, for instance
+ * Notification.TYPE_WARNING_MESSAGE.
+ *
+ * Care should be taken to to avoid XSS vulnerabilities as the caption
+ * is rendered as html.
+ *
+ * @see #showNotification(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The message
+ * @param type
+ * The message type
+ *
+ * @deprecated As of 7.0, use Notification.show instead
+ */
+ @Deprecated
+ public void showNotification(String caption, int type) {
+ getPage().showNotification(new Notification(caption, type));
+ }
+
+ /**
+ * Shows a notification consisting of a bigger caption and a smaller
+ * description on the middle of the root. The message automatically
+ * disappears ("humanized message").
+ *
+ * Care should be taken to to avoid XSS vulnerabilities as the caption
+ * and description are rendered as html.
+ *
+ * @see #showNotification(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The caption of the message
+ * @param description
+ * The message description
+ *
+ * @deprecated As of 7.0, use Notification.show instead
+ */
+ @Deprecated
+ public void showNotification(String caption, String description) {
+ getPage().showNotification(new Notification(caption, description));
+ }
+
+ /**
+ * Shows a notification consisting of a bigger caption and a smaller
+ * description. The position and behavior of the message depends on the
+ * type, which is one of the basic types defined in {@link Notification}
+ * , for instance Notification.TYPE_WARNING_MESSAGE.
+ *
+ * Care should be taken to to avoid XSS vulnerabilities as the caption
+ * and description are rendered as html.
+ *
+ * @see #showNotification(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The caption of the message
+ * @param description
+ * The message description
+ * @param type
+ * The message type
+ *
+ * @deprecated As of 7.0, use Notification.show instead
+ */
+ @Deprecated
+ public void showNotification(String caption, String description,
+ int type) {
+ getPage().showNotification(
+ new Notification(caption, description, type));
+ }
+
+ /**
+ * Shows a notification consisting of a bigger caption and a smaller
+ * description. The position and behavior of the message depends on the
+ * type, which is one of the basic types defined in {@link Notification}
+ * , for instance Notification.TYPE_WARNING_MESSAGE.
+ *
+ * Care should be taken to avoid XSS vulnerabilities if html content is
+ * allowed.
+ *
+ * @see #showNotification(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The message caption
+ * @param description
+ * The message description
+ * @param type
+ * The type of message
+ * @param htmlContentAllowed
+ * Whether html in the caption and description should be
+ * displayed as html or as plain text
+ *
+ * @deprecated As of 7.0, use Notification.show instead
+ */
+ @Deprecated
+ public void showNotification(String caption, String description,
+ int type, boolean htmlContentAllowed) {
+ getPage().showNotification(
+ new Notification(caption, description, type,
+ htmlContentAllowed));
+ }
+
+ /**
+ * Shows a notification message.
+ *
+ * @see Notification
+ * @see #showNotification(String)
+ * @see #showNotification(String, int)
+ * @see #showNotification(String, String)
+ * @see #showNotification(String, String, int)
+ *
+ * @param notification
+ * The notification message to show
+ *
+ * @deprecated As of 7.0, use Notification.show instead
+ */
+ @Deprecated
+ public void showNotification(Notification notification) {
+ getPage().showNotification(notification);
+ }
+
+ /**
+ * Executes JavaScript in this window.
+ *
+ * <p>
+ * This method allows one to inject javascript from the server to
+ * client. A client implementation is not required to implement this
+ * functionality, but currently all web-based clients do implement this.
+ * </p>
+ *
+ * <p>
+ * Executing javascript this way often leads to cross-browser
+ * compatibility issues and regressions that are hard to resolve. Use of
+ * this method should be avoided and instead it is recommended to create
+ * new widgets with GWT. For more info on creating own, reusable
+ * client-side widgets in Java, read the corresponding chapter in Book
+ * of Vaadin.
+ * </p>
+ *
+ * @param script
+ * JavaScript snippet that will be executed.
+ *
+ * @deprecated as of 7.0, use JavaScript.getCurrent().execute(String)
+ * instead
+ */
+ @Deprecated
+ public void executeJavaScript(String script) {
+ getPage().getJavaScript().execute(script);
+ }
+
+ @Override
+ public void setCaption(String caption) {
+ // Override to provide backwards compatibility
+ getState().setCaption(caption);
+ getPage().setTitle(caption);
+ }
+
+ }
/**
- * A list of javascript commands that are waiting to be sent to the client.
- * Cleared (set to null) when the commands have been sent.
+ * The application to which this root belongs
*/
- private List<String> jsExecQueue = null;
+ private Application application;
/**
* List of windows in this root.
@@ -368,12 +532,6 @@ public abstract class Root extends AbstractComponentContainer implements
private final LinkedHashSet<Window> windows = new LinkedHashSet<Window>();
/**
- * Resources to be opened automatically on next repaint. The list is
- * automatically cleared when it has been sent to the client.
- */
- private final LinkedList<OpenResource> openList = new LinkedList<OpenResource>();
-
- /**
* The component that should be scrolled into view after the next repaint.
* Null if nothing should be scrolled into view.
*/
@@ -399,16 +557,13 @@ public abstract class Root extends AbstractComponentContainer implements
*/
private static final ThreadLocal<Root> currentRoot = new ThreadLocal<Root>();
- private int browserWindowWidth = -1;
- private int browserWindowHeight = -1;
-
/** Identifies the click event */
private static final String CLICK_EVENT_ID = VRoot.CLICK_EVENT_ID;
private DirtyConnectorTracker dirtyConnectorTracker = new DirtyConnectorTracker(
this);
- private JavascriptManager javascriptManager;
+ private Page page = new Page(this);
private RootServerRpc rpc = new RootServerRpc() {
public void click(MouseEventDetails mouseDetails) {
@@ -504,68 +659,7 @@ public abstract class Root extends AbstractComponentContainer implements
}
public void paintContent(PaintTarget target) throws PaintException {
- // Open requested resource
- synchronized (openList) {
- if (!openList.isEmpty()) {
- for (final Iterator<OpenResource> i = openList.iterator(); i
- .hasNext();) {
- (i.next()).paintContent(target);
- }
- openList.clear();
- }
- }
-
- // Paint notifications
- if (notifications != null) {
- target.startTag("notifications");
- for (final Iterator<Notification> it = notifications.iterator(); it
- .hasNext();) {
- final Notification n = it.next();
- target.startTag("notification");
- if (n.getCaption() != null) {
- target.addAttribute(
- VNotification.ATTRIBUTE_NOTIFICATION_CAPTION,
- n.getCaption());
- }
- if (n.getDescription() != null) {
- target.addAttribute(
- VNotification.ATTRIBUTE_NOTIFICATION_MESSAGE,
- n.getDescription());
- }
- if (n.getIcon() != null) {
- target.addAttribute(
- VNotification.ATTRIBUTE_NOTIFICATION_ICON,
- n.getIcon());
- }
- if (!n.isHtmlContentAllowed()) {
- target.addAttribute(
- VRoot.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED, true);
- }
- target.addAttribute(
- VNotification.ATTRIBUTE_NOTIFICATION_POSITION,
- n.getPosition());
- target.addAttribute(VNotification.ATTRIBUTE_NOTIFICATION_DELAY,
- n.getDelayMsec());
- if (n.getStyleName() != null) {
- target.addAttribute(
- VNotification.ATTRIBUTE_NOTIFICATION_STYLE,
- n.getStyleName());
- }
- target.endTag("notification");
- }
- target.endTag("notifications");
- notifications = null;
- }
-
- // Add executable javascripts if needed
- if (jsExecQueue != null) {
- for (String script : jsExecQueue) {
- target.startTag("execJS");
- target.addAttribute("script", script);
- target.endTag("execJS");
- }
- jsExecQueue = null;
- }
+ page.paintContent(target);
if (scrollIntoView != null) {
target.addAttribute("scrollTo", scrollIntoView);
@@ -586,10 +680,6 @@ public abstract class Root extends AbstractComponentContainer implements
actionManager.paintActions(null, target);
}
- if (fragment != null) {
- target.addAttribute(VRoot.FRAGMENT_VARIABLE, fragment);
- }
-
if (isResizeLazy()) {
target.addAttribute(VRoot.RESIZE_LAZY, true);
}
@@ -620,23 +710,14 @@ public abstract class Root extends AbstractComponentContainer implements
if (variables.containsKey(VRoot.FRAGMENT_VARIABLE)) {
String fragment = (String) variables.get(VRoot.FRAGMENT_VARIABLE);
- setFragment(fragment, true);
+ getPage().setFragment(fragment, true);
}
- boolean sendResizeEvent = false;
- if (variables.containsKey("height")) {
- browserWindowHeight = ((Integer) variables.get("height"))
- .intValue();
- sendResizeEvent = true;
- }
- if (variables.containsKey("width")) {
- browserWindowWidth = ((Integer) variables.get("width")).intValue();
- sendResizeEvent = true;
- }
- if (sendResizeEvent) {
- fireEvent(new BrowserWindowResizeEvent(this, browserWindowWidth,
- browserWindowHeight));
+ if (variables.containsKey("height") || variables.containsKey("width")) {
+ getPage().setBrowserWindowSize((Integer) variables.get("width"),
+ (Integer) variables.get("height"));
}
+
}
/*
@@ -817,11 +898,6 @@ public abstract class Root extends AbstractComponentContainer implements
*/
private Focusable pendingFocus;
- /**
- * The current URI fragment.
- */
- private String fragment;
-
private boolean resizeLazy = false;
/**
@@ -843,175 +919,6 @@ public abstract class Root extends AbstractComponentContainer implements
}
/**
- * Shows a notification message on the middle of the root. The message
- * automatically disappears ("humanized message").
- *
- * Care should be taken to to avoid XSS vulnerabilities as the caption is
- * rendered as html.
- *
- * @see #showNotification(Notification)
- * @see Notification
- *
- * @param caption
- * The message
- */
- public void showNotification(String caption) {
- addNotification(new Notification(caption));
- }
-
- /**
- * Shows a notification message the root. The position and behavior of the
- * message depends on the type, which is one of the basic types defined in
- * {@link Notification}, for instance Notification.TYPE_WARNING_MESSAGE.
- *
- * Care should be taken to to avoid XSS vulnerabilities as the caption is
- * rendered as html.
- *
- * @see #showNotification(Notification)
- * @see Notification
- *
- * @param caption
- * The message
- * @param type
- * The message type
- */
- public void showNotification(String caption, int type) {
- addNotification(new Notification(caption, type));
- }
-
- /**
- * Shows a notification consisting of a bigger caption and a smaller
- * description on the middle of the root. The message automatically
- * disappears ("humanized message").
- *
- * Care should be taken to to avoid XSS vulnerabilities as the caption and
- * description are rendered as html.
- *
- * @see #showNotification(Notification)
- * @see Notification
- *
- * @param caption
- * The caption of the message
- * @param description
- * The message description
- *
- */
- public void showNotification(String caption, String description) {
- addNotification(new Notification(caption, description));
- }
-
- /**
- * Shows a notification consisting of a bigger caption and a smaller
- * description. The position and behavior of the message depends on the
- * type, which is one of the basic types defined in {@link Notification},
- * for instance Notification.TYPE_WARNING_MESSAGE.
- *
- * Care should be taken to to avoid XSS vulnerabilities as the caption and
- * description are rendered as html.
- *
- * @see #showNotification(Notification)
- * @see Notification
- *
- * @param caption
- * The caption of the message
- * @param description
- * The message description
- * @param type
- * The message type
- */
- public void showNotification(String caption, String description, int type) {
- addNotification(new Notification(caption, description, type));
- }
-
- /**
- * Shows a notification consisting of a bigger caption and a smaller
- * description. The position and behavior of the message depends on the
- * type, which is one of the basic types defined in {@link Notification},
- * for instance Notification.TYPE_WARNING_MESSAGE.
- *
- * Care should be taken to avoid XSS vulnerabilities if html content is
- * allowed.
- *
- * @see #showNotification(Notification)
- * @see Notification
- *
- * @param caption
- * The message caption
- * @param description
- * The message description
- * @param type
- * The type of message
- * @param htmlContentAllowed
- * Whether html in the caption and description should be
- * displayed as html or as plain text
- */
- public void showNotification(String caption, String description, int type,
- boolean htmlContentAllowed) {
- addNotification(new Notification(caption, description, type,
- htmlContentAllowed));
- }
-
- /**
- * Shows a notification message.
- *
- * @see Notification
- * @see #showNotification(String)
- * @see #showNotification(String, int)
- * @see #showNotification(String, String)
- * @see #showNotification(String, String, int)
- *
- * @param notification
- * The notification message to show
- */
- public void showNotification(Notification notification) {
- addNotification(notification);
- }
-
- /**
- * Internal helper method to actually add a notification.
- *
- * @param notification
- * the notification to add
- */
- private void addNotification(Notification notification) {
- if (notifications == null) {
- notifications = new LinkedList<Notification>();
- }
- notifications.add(notification);
- requestRepaint();
- }
-
- /**
- * Executes JavaScript in this root.
- *
- * <p>
- * This method allows one to inject javascript from the server to client. A
- * client implementation is not required to implement this functionality,
- * but currently all web-based clients do implement this.
- * </p>
- *
- * <p>
- * Executing javascript this way often leads to cross-browser compatibility
- * issues and regressions that are hard to resolve. Use of this method
- * should be avoided and instead it is recommended to create new widgets
- * with GWT. For more info on creating own, reusable client-side widgets in
- * Java, read the corresponding chapter in Book of Vaadin.
- * </p>
- *
- * @param script
- * JavaScript snippet that will be executed.
- */
- public void executeJavaScript(String script) {
- if (jsExecQueue == null) {
- jsExecQueue = new ArrayList<String>();
- }
-
- jsExecQueue.add(script);
-
- requestRepaint();
- }
-
- /**
* Scrolls any component between the component and root to a suitable
* position so the component is visible to the user. The given component
* must belong to this root.
@@ -1125,10 +1032,7 @@ public abstract class Root extends AbstractComponentContainer implements
* the initialization request
*/
public void doInit(WrappedRequest request) {
- BrowserDetails browserDetails = request.getBrowserDetails();
- if (browserDetails != null) {
- fragment = browserDetails.getUriFragment();
- }
+ getPage().init(request);
// Call the init overridden by the application developer
init(request);
@@ -1187,186 +1091,6 @@ public abstract class Root extends AbstractComponentContainer implements
return currentRoot.get();
}
- /**
- * Opens the given resource in this root. The contents of this Root is
- * replaced by the {@code Resource}.
- *
- * @param resource
- * the resource to show in this root
- */
- public void open(Resource resource) {
- synchronized (openList) {
- if (!openList.contains(resource)) {
- openList.add(new OpenResource(resource, null, -1, -1,
- BORDER_DEFAULT));
- }
- }
- requestRepaint();
- }
-
- /* ********************************************************************* */
-
- /**
- * Opens the given resource in a window with the given name.
- * <p>
- * The supplied {@code windowName} is used as the target name in a
- * window.open call in the client. This means that special values such as
- * "_blank", "_self", "_top", "_parent" have special meaning. An empty or
- * <code>null</code> window name is also a special case.
- * </p>
- * <p>
- * "", null and "_self" as {@code windowName} all causes the resource to be
- * opened in the current window, replacing any old contents. For
- * downloadable content you should avoid "_self" as "_self" causes the
- * client to skip rendering of any other changes as it considers them
- * irrelevant (the page will be replaced by the resource). This can speed up
- * the opening of a resource, but it might also put the client side into an
- * inconsistent state if the window content is not completely replaced e.g.,
- * if the resource is downloaded instead of displayed in the browser.
- * </p>
- * <p>
- * "_blank" as {@code windowName} causes the resource to always be opened in
- * a new window or tab (depends on the browser and browser settings).
- * </p>
- * <p>
- * "_top" and "_parent" as {@code windowName} works as specified by the HTML
- * standard.
- * </p>
- * <p>
- * Any other {@code windowName} will open the resource in a window with that
- * name, either by opening a new window/tab in the browser or by replacing
- * the contents of an existing window with that name.
- * </p>
- *
- * @param resource
- * the resource.
- * @param windowName
- * the name of the window.
- */
- public void open(Resource resource, String windowName) {
- synchronized (openList) {
- if (!openList.contains(resource)) {
- openList.add(new OpenResource(resource, windowName, -1, -1,
- BORDER_DEFAULT));
- }
- }
- requestRepaint();
- }
-
- /**
- * Opens the given resource in a window with the given size, border and
- * name. For more information on the meaning of {@code windowName}, see
- * {@link #open(Resource, String)}.
- *
- * @param resource
- * the resource.
- * @param windowName
- * the name of the window.
- * @param width
- * the width of the window in pixels
- * @param height
- * the height of the window in pixels
- * @param border
- * the border style of the window. See {@link #BORDER_NONE
- * Window.BORDER_* constants}
- */
- public void open(Resource resource, String windowName, int width,
- int height, int border) {
- synchronized (openList) {
- if (!openList.contains(resource)) {
- openList.add(new OpenResource(resource, windowName, width,
- height, border));
- }
- }
- requestRepaint();
- }
-
- /**
- * Private class for storing properties related to opening resources.
- */
- private class OpenResource implements Serializable {
-
- /**
- * The resource to open
- */
- private final Resource resource;
-
- /**
- * The name of the target window
- */
- private final String name;
-
- /**
- * The width of the target window
- */
- private final int width;
-
- /**
- * The height of the target window
- */
- private final int height;
-
- /**
- * The border style of the target window
- */
- private final int border;
-
- /**
- * Creates a new open resource.
- *
- * @param resource
- * The resource to open
- * @param name
- * The name of the target window
- * @param width
- * The width of the target window
- * @param height
- * The height of the target window
- * @param border
- * The border style of the target window
- */
- private OpenResource(Resource resource, String name, int width,
- int height, int border) {
- this.resource = resource;
- this.name = name;
- this.width = width;
- this.height = height;
- this.border = border;
- }
-
- /**
- * Paints the open request. Should be painted inside the window.
- *
- * @param target
- * the paint target
- * @throws PaintException
- * if the paint operation fails
- */
- private void paintContent(PaintTarget target) throws PaintException {
- target.startTag("open");
- target.addAttribute("src", resource);
- if (name != null && name.length() > 0) {
- target.addAttribute("name", name);
- }
- if (width >= 0) {
- target.addAttribute("width", width);
- }
- if (height >= 0) {
- target.addAttribute("height", height);
- }
- switch (border) {
- case BORDER_MINIMAL:
- target.addAttribute("border", "minimal");
- break;
- case BORDER_NONE:
- target.addAttribute("border", "none");
- break;
- }
-
- target.endTag("open");
- }
- }
-
public void setScrollTop(int scrollTop) {
throw new RuntimeException("Not yet implemented");
}
@@ -1454,110 +1178,6 @@ public abstract class Root extends AbstractComponentContainer implements
removeListener(CLICK_EVENT_ID, ClickEvent.class, listener);
}
- public void addListener(FragmentChangedListener listener) {
- addListener(FragmentChangedEvent.class, listener,
- FRAGMENT_CHANGED_METHOD);
- }
-
- public void removeListener(FragmentChangedListener listener) {
- removeListener(FragmentChangedEvent.class, listener,
- FRAGMENT_CHANGED_METHOD);
- }
-
- /**
- * Sets URI fragment. Optionally fires a {@link FragmentChangedEvent}
- *
- * @param newFragment
- * id of the new fragment
- * @param fireEvent
- * true to fire event
- * @see FragmentChangedEvent
- * @see FragmentChangedListener
- */
- public void setFragment(String newFragment, boolean fireEvents) {
- if (newFragment == null) {
- throw new NullPointerException("The fragment may not be null");
- }
- if (!newFragment.equals(fragment)) {
- fragment = newFragment;
- if (fireEvents) {
- fireEvent(new FragmentChangedEvent(this, newFragment));
- }
- requestRepaint();
- }
- }
-
- /**
- * Sets URI fragment. This method fires a {@link FragmentChangedEvent}
- *
- * @param newFragment
- * id of the new fragment
- * @see FragmentChangedEvent
- * @see FragmentChangedListener
- */
- public void setFragment(String newFragment) {
- setFragment(newFragment, true);
- }
-
- /**
- * Gets currently set URI fragment.
- * <p>
- * To listen changes in fragment, hook a {@link FragmentChangedListener}.
- *
- * @return the current fragment in browser uri or null if not known
- */
- public String getFragment() {
- return fragment;
- }
-
- /**
- * Adds a new {@link BrowserWindowResizeListener} to this root. The listener
- * will be notified whenever the browser window within which this root
- * resides is resized.
- *
- * @param resizeListener
- * the listener to add
- *
- * @see BrowserWindowResizeListener#browserWindowResized(BrowserWindowResizeEvent)
- * @see #setResizeLazy(boolean)
- */
- public void addListener(BrowserWindowResizeListener resizeListener) {
- addListener(BrowserWindowResizeEvent.class, resizeListener,
- BROWSWER_RESIZE_METHOD);
- }
-
- /**
- * Removes a {@link BrowserWindowResizeListener} from this root. The
- * listener will no longer be notified when the browser window is resized.
- *
- * @param resizeListener
- * the listener to remove
- */
- public void removeListener(BrowserWindowResizeListener resizeListener) {
- removeListener(BrowserWindowResizeEvent.class, resizeListener,
- BROWSWER_RESIZE_METHOD);
- }
-
- /**
- * Gets the last known height of the browser window in which this root
- * resides.
- *
- * @return the browser window height in pixels
- */
- public int getBrowserWindowHeight() {
- return browserWindowHeight;
- }
-
- /**
- * Gets the last known width of the browser window in which this root
- * resides.
- *
- * @return the browser window width in pixels
- */
- public int getBrowserWindowWidth() {
- return browserWindowWidth;
- }
-
/**
* Notifies the child components and windows that the root is attached to
* the application.
@@ -1592,14 +1212,21 @@ public abstract class Root extends AbstractComponentContainer implements
return dirtyConnectorTracker;
}
- public JavascriptManager getJavascriptManager() {
- if (javascriptManager == null) {
- // Create and attach on first use
- javascriptManager = new JavascriptManager();
- addExtension(javascriptManager);
- }
+ public Page getPage() {
+ return page;
+ }
- return javascriptManager;
+ /**
+ * Setting the caption of a Root is not supported. To set the title of the
+ * HTML page, use Page.setTitle
+ *
+ * @deprecated as of 7.0.0, use {@link Page#setTitle(String)}
+ */
+ @Override
+ @Deprecated
+ public void setCaption(String caption) {
+ throw new IllegalStateException(
+ "You can not set the title of a Root. To set the title of the HTML page, use Page.setTitle");
}
}
diff --git a/src/com/vaadin/ui/TabSheet.java b/src/com/vaadin/ui/TabSheet.java
index 23dee15359..061809de67 100644
--- a/src/com/vaadin/ui/TabSheet.java
+++ b/src/com/vaadin/ui/TabSheet.java
@@ -108,6 +108,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
setWidth(100, UNITS_PERCENTAGE);
setImmediate(true);
setCloseHandler(new CloseHandler() {
+
public void onTabClose(TabSheet tabsheet, Component c) {
tabsheet.removeComponent(c);
}
@@ -120,6 +121,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
*
* @return the unmodifiable Iterator of the tab content components
*/
+
public Iterator<Component> getComponentIterator() {
return Collections.unmodifiableList(components).iterator();
}
@@ -130,6 +132,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
*
* @return the number of contained components
*/
+
public int getComponentCount() {
return components.size();
}
@@ -143,6 +146,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
* @param c
* the component to be removed.
*/
+
@Override
public void removeComponent(Component c) {
if (c != null && components.contains(c)) {
@@ -193,6 +197,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
* @param c
* the component to be added.
*/
+
@Override
public void addComponent(Component c) {
addTab(c);
@@ -334,6 +339,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
* @param source
* the container components are removed from.
*/
+
@Override
public void moveComponentsFrom(ComponentContainer source) {
for (final Iterator<Component> i = source.getComponentIterator(); i
@@ -359,6 +365,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
* @throws PaintException
* if the paint operation failed.
*/
+
public void paintContent(PaintTarget target) throws PaintException {
if (areTabsHidden()) {
@@ -683,6 +690,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
}
// inherits javadoc
+
public void changeVariables(Object source, Map<String, Object> variables) {
if (variables.containsKey("selected")) {
setSelectedTab(keyMapper.get((String) variables.get("selected")));
@@ -719,6 +727,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
*
* {@inheritDoc}
*/
+
public void replaceComponent(Component oldComponent, Component newComponent) {
if (selected == oldComponent) {
@@ -729,25 +738,6 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
Tab newTab = tabs.get(newComponent);
Tab oldTab = tabs.get(oldComponent);
- // Gets the captions
- String oldCaption = null;
- Resource oldIcon = null;
- String newCaption = null;
- Resource newIcon = null;
-
- if (oldTab != null) {
- oldCaption = oldTab.getCaption();
- oldIcon = oldTab.getIcon();
- }
-
- if (newTab != null) {
- newCaption = newTab.getCaption();
- newIcon = newTab.getIcon();
- } else {
- newCaption = newComponent.getCaption();
- newIcon = newComponent.getIcon();
- }
-
// Gets the locations
int oldLocation = -1;
int newLocation = -1;
@@ -769,35 +759,21 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
addComponent(newComponent);
} else if (newLocation == -1) {
removeComponent(oldComponent);
- keyMapper.remove(oldComponent);
- newTab = addTab(newComponent);
- components.remove(newComponent);
- components.add(oldLocation, newComponent);
- newTab.setCaption(oldCaption);
- newTab.setIcon(oldIcon);
+ newTab = addTab(newComponent, oldLocation);
+ // Copy all relevant metadata to the new tab (#8793)
+ // TODO Should reuse the old tab instance instead?
+ copyTabMetadata(oldTab, newTab);
} else {
- if (oldLocation > newLocation) {
- components.remove(oldComponent);
- components.add(newLocation, oldComponent);
- components.remove(newComponent);
- components.add(oldLocation, newComponent);
- } else {
- components.remove(newComponent);
- components.add(oldLocation, newComponent);
- components.remove(oldComponent);
- components.add(newLocation, oldComponent);
- }
+ components.set(oldLocation, newComponent);
+ components.set(newLocation, oldComponent);
- if (newTab != null) {
- // This should always be true
- newTab.setCaption(oldCaption);
- newTab.setIcon(oldIcon);
- }
- if (oldTab != null) {
- // This should always be true
- oldTab.setCaption(newCaption);
- oldTab.setIcon(newIcon);
- }
+ // Tab associations are not changed, but metadata is swapped between
+ // the instances
+ // TODO Should reassociate the instances instead?
+ Tab tmp = new TabSheetTabImpl(null, null);
+ copyTabMetadata(newTab, tmp);
+ copyTabMetadata(oldTab, newTab);
+ copyTabMetadata(tmp, oldTab);
requestRepaint();
}
@@ -1106,6 +1082,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
/**
* Returns the tab caption. Can never be null.
*/
+
public String getCaption() {
return caption;
}
@@ -1300,4 +1277,23 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
public boolean isComponentVisible(Component childComponent) {
return childComponent == getSelectedTab();
}
+
+ /**
+ * Copies properties from one Tab to another.
+ *
+ * @param from
+ * The tab whose data to copy.
+ * @param to
+ * The tab to which copy the data.
+ */
+ private static void copyTabMetadata(Tab from, Tab to) {
+ to.setCaption(from.getCaption());
+ to.setIcon(from.getIcon());
+ to.setDescription(from.getDescription());
+ to.setVisible(from.isVisible());
+ to.setEnabled(from.isEnabled());
+ to.setClosable(from.isClosable());
+ to.setStyleName(from.getStyleName());
+ to.setComponentError(from.getComponentError());
+ }
}
diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java
index fc736bfa93..5d4f919704 100644
--- a/src/com/vaadin/ui/Table.java
+++ b/src/com/vaadin/ui/Table.java
@@ -39,7 +39,6 @@ import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DragSource;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.DropTarget;
-import com.vaadin.event.dd.acceptcriteria.ClientCriterion;
import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion;
import com.vaadin.terminal.KeyMapper;
import com.vaadin.terminal.LegacyPaint;
@@ -47,7 +46,6 @@ import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.ui.dd.VLazyInitItemIdentifiers;
import com.vaadin.terminal.gwt.client.ui.table.VScrollTable;
/**
@@ -78,8 +76,7 @@ public class Table extends AbstractSelect implements Action.Container,
Container.Ordered, Container.Sortable, ItemClickNotifier, DragSource,
DropTarget, HasComponents {
- private static final Logger logger = Logger
- .getLogger(Table.class.getName());
+ private transient Logger logger = null;
/**
* Modes that Table support as drag sourse.
@@ -331,7 +328,8 @@ public class Table extends AbstractSelect implements Action.Container,
private static final double CACHE_RATE_DEFAULT = 2;
private static final String ROW_HEADER_COLUMN_KEY = "0";
- private static final Object ROW_HEADER_FAKE_PROPERTY_ID = new Object();
+ private static final Object ROW_HEADER_FAKE_PROPERTY_ID = new UniqueSerializable() {
+ };
/* Private table extensions to Select */
@@ -356,6 +354,11 @@ public class Table extends AbstractSelect implements Action.Container,
private LinkedList<Object> visibleColumns = new LinkedList<Object>();
/**
+ * Holds noncollapsible columns.
+ */
+ private HashSet<Object> noncollapsibleColumns = new HashSet<Object>();
+
+ /**
* Holds propertyIds of currently collapsed columns.
*/
private final HashSet<Object> collapsedColumns = new HashSet<Object>();
@@ -1248,6 +1251,9 @@ public class Table extends AbstractSelect implements Action.Container,
if (!isColumnCollapsingAllowed()) {
throw new IllegalStateException("Column collapsing not allowed!");
}
+ if (collapsed && noncollapsibleColumns.contains(propertyId)) {
+ throw new IllegalStateException("The column is noncollapsible!");
+ }
if (collapsed) {
collapsedColumns.add(propertyId);
@@ -1287,6 +1293,41 @@ public class Table extends AbstractSelect implements Action.Container,
}
/**
+ * Sets whether the given column is collapsible. Note that collapsible
+ * columns can only be actually collapsed (via UI or with
+ * {@link #setColumnCollapsed(Object, boolean) setColumnCollapsed()}) if
+ * {@link #isColumnCollapsingAllowed()} is true. By default all columns are
+ * collapsible.
+ *
+ * @param propertyId
+ * the propertyID identifying the column.
+ * @param collapsible
+ * true if the column should be collapsible, false otherwise.
+ */
+ public void setColumnCollapsible(Object propertyId, boolean collapsible) {
+ if (collapsible) {
+ noncollapsibleColumns.remove(propertyId);
+ } else {
+ noncollapsibleColumns.add(propertyId);
+ collapsedColumns.remove(propertyId);
+ }
+ refreshRowCache();
+ }
+
+ /**
+ * Checks if the given column is collapsible. Note that even if this method
+ * returns <code>true</code>, the column can only be actually collapsed (via
+ * UI or with {@link #setColumnCollapsed(Object, boolean)
+ * setColumnCollapsed()}) if {@link #isColumnCollapsingAllowed()} is also
+ * true.
+ *
+ * @return true if the column can be collapsed; false otherwise.
+ */
+ public boolean isColumnCollapsible(Object propertyId) {
+ return !noncollapsibleColumns.contains(propertyId);
+ }
+
+ /**
* Checks if column reordering is allowed.
*
* @return true if columns can be reordered; false otherwise.
@@ -1569,6 +1610,13 @@ public class Table extends AbstractSelect implements Action.Container,
}
} else {
// initial load
+
+ // #8805 send one extra row in the beginning in case a partial
+ // row is shown on the UI
+ if (firstIndex > 0) {
+ firstIndex = firstIndex - 1;
+ rows = rows + 1;
+ }
firstToBeRenderedInClient = firstIndex;
}
if (totalRows > 0) {
@@ -1597,6 +1645,7 @@ public class Table extends AbstractSelect implements Action.Container,
* this method has been called. See {@link #refreshRowCache()} for forcing
* an update of the contents.
*/
+
@Override
public void requestRepaint() {
// Overridden only for javadoc
@@ -1714,8 +1763,9 @@ public class Table extends AbstractSelect implements Action.Container,
* @return
*/
private Object[][] getVisibleCellsInsertIntoCache(int firstIndex, int rows) {
- logger.finest("Insert " + rows + " rows at index " + firstIndex
- + " to existing page buffer requested");
+ getLogger().finest(
+ "Insert " + rows + " rows at index " + firstIndex
+ + " to existing page buffer requested");
// Page buffer must not become larger than pageLength*cacheRate before
// or after the current page
@@ -1818,11 +1868,14 @@ public class Table extends AbstractSelect implements Action.Container,
}
}
pageBuffer = newPageBuffer;
- logger.finest("Page Buffer now contains "
- + pageBuffer[CELL_ITEMID].length + " rows ("
- + pageBufferFirstIndex + "-"
- + (pageBufferFirstIndex + pageBuffer[CELL_ITEMID].length - 1)
- + ")");
+ getLogger().finest(
+ "Page Buffer now contains "
+ + pageBuffer[CELL_ITEMID].length
+ + " rows ("
+ + pageBufferFirstIndex
+ + "-"
+ + (pageBufferFirstIndex
+ + pageBuffer[CELL_ITEMID].length - 1) + ")");
return cells;
}
@@ -1839,8 +1892,9 @@ public class Table extends AbstractSelect implements Action.Container,
*/
private Object[][] getVisibleCellsNoCache(int firstIndex, int rows,
boolean replaceListeners) {
- logger.finest("Render visible cells for rows " + firstIndex + "-"
- + (firstIndex + rows - 1));
+ getLogger().finest(
+ "Render visible cells for rows " + firstIndex + "-"
+ + (firstIndex + rows - 1));
final Object[] colids = getVisibleColumns();
final int cols = colids.length;
@@ -2022,8 +2076,9 @@ public class Table extends AbstractSelect implements Action.Container,
}
protected void registerComponent(Component component) {
- logger.finest("Registered " + component.getClass().getSimpleName()
- + ": " + component.getCaption());
+ getLogger().finest(
+ "Registered " + component.getClass().getSimpleName() + ": "
+ + component.getCaption());
if (component.getParent() != this) {
component.setParent(this);
}
@@ -2054,8 +2109,9 @@ public class Table extends AbstractSelect implements Action.Container,
* @param count
*/
private void unregisterComponentsAndPropertiesInRows(int firstIx, int count) {
- logger.finest("Unregistering components in rows " + firstIx + "-"
- + (firstIx + count - 1));
+ getLogger().finest(
+ "Unregistering components in rows " + firstIx + "-"
+ + (firstIx + count - 1));
Object[] colids = getVisibleColumns();
if (pageBuffer != null && pageBuffer[CELL_ITEMID].length > 0) {
int bufSize = pageBuffer[CELL_ITEMID].length;
@@ -2135,8 +2191,9 @@ public class Table extends AbstractSelect implements Action.Container,
* a set of components that should be unregistered.
*/
protected void unregisterComponent(Component component) {
- logger.finest("Unregistered " + component.getClass().getSimpleName()
- + ": " + component.getCaption());
+ getLogger().finest(
+ "Unregistered " + component.getClass().getSimpleName() + ": "
+ + component.getCaption());
component.setParent(null);
/*
* Also remove property data sources to unregister listeners keeping the
@@ -2446,6 +2503,7 @@ public class Table extends AbstractSelect implements Action.Container,
* @see com.vaadin.ui.Select#changeVariables(java.lang.Object,
* java.util.Map)
*/
+
@Override
public void changeVariables(Object source, Map<String, Object> variables) {
@@ -2505,7 +2563,7 @@ public class Table extends AbstractSelect implements Action.Container,
.get("lastToBeRendered")).intValue();
} catch (Exception e) {
// FIXME: Handle exception
- logger.log(Level.FINER,
+ getLogger().log(Level.FINER,
"Could not parse the first and/or last rows.", e);
}
@@ -2525,8 +2583,9 @@ public class Table extends AbstractSelect implements Action.Container,
}
}
}
- logger.finest("Client wants rows " + reqFirstRowToPaint + "-"
- + (reqFirstRowToPaint + reqRowsToPaint - 1));
+ getLogger().finest(
+ "Client wants rows " + reqFirstRowToPaint + "-"
+ + (reqFirstRowToPaint + reqRowsToPaint - 1));
clientNeedsContentRefresh = true;
}
@@ -2572,7 +2631,7 @@ public class Table extends AbstractSelect implements Action.Container,
}
} catch (final Exception e) {
// FIXME: Handle exception
- logger.log(Level.FINER,
+ getLogger().log(Level.FINER,
"Could not determine column collapsing state", e);
}
clientNeedsContentRefresh = true;
@@ -2594,7 +2653,7 @@ public class Table extends AbstractSelect implements Action.Container,
}
} catch (final Exception e) {
// FIXME: Handle exception
- logger.log(Level.FINER,
+ getLogger().log(Level.FINER,
"Could not determine column reordering state", e);
}
clientNeedsContentRefresh = true;
@@ -2767,6 +2826,7 @@ public class Table extends AbstractSelect implements Action.Container,
* @see com.vaadin.ui.AbstractSelect#paintContent(com.vaadin.
* terminal.PaintTarget)
*/
+
@Override
public void paintContent(PaintTarget target) throws PaintException {
/*
@@ -2884,8 +2944,9 @@ public class Table extends AbstractSelect implements Action.Container,
target.startTag("prows");
if (!shouldHideAddedRows()) {
- logger.finest("Paint rows for add. Index: " + firstIx + ", count: "
- + count + ".");
+ getLogger().finest(
+ "Paint rows for add. Index: " + firstIx + ", count: "
+ + count + ".");
// Partial row additions bypass the normal caching mechanism.
Object[][] cells = getVisibleCellsInsertIntoCache(firstIx, count);
@@ -2908,8 +2969,9 @@ public class Table extends AbstractSelect implements Action.Container,
indexInRowbuffer, itemId);
}
} else {
- logger.finest("Paint rows for remove. Index: " + firstIx
- + ", count: " + count + ".");
+ getLogger().finest(
+ "Paint rows for remove. Index: " + firstIx + ", count: "
+ + count + ".");
removeRowsFromCacheAndFillBottom(firstIx, count);
target.addAttribute("hide", true);
}
@@ -3108,7 +3170,17 @@ public class Table extends AbstractSelect implements Action.Container,
}
}
target.addVariable(this, "collapsedcolumns", collapsedKeys);
+
+ final String[] noncollapsibleKeys = new String[noncollapsibleColumns
+ .size()];
+ nextColumn = 0;
+ for (Object colId : noncollapsibleColumns) {
+ noncollapsibleKeys[nextColumn++] = columnIdMap.key(colId);
+ }
+ target.addVariable(this, "noncollapsiblecolumns",
+ noncollapsibleKeys);
}
+
}
private void paintActions(PaintTarget target, final Set<Action> actionSet)
@@ -3613,6 +3685,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.event.Action.Container#addActionHandler(Action.Handler)
*/
+
public void addActionHandler(Action.Handler actionHandler) {
if (actionHandler != null) {
@@ -3639,6 +3712,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.event.Action.Container#removeActionHandler(Action.Handler)
*/
+
public void removeActionHandler(Action.Handler actionHandler) {
if (actionHandlers != null && actionHandlers.contains(actionHandler)) {
@@ -3678,6 +3752,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Property.ValueChangeListener#valueChange(Property.ValueChangeEvent)
*/
+
@Override
public void valueChange(Property.ValueChangeEvent event) {
if (event.getProperty() == this
@@ -3708,6 +3783,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.ui.Component#attach()
*/
+
@Override
public void attach() {
super.attach();
@@ -3720,6 +3796,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.ui.Component#detach()
*/
+
@Override
public void detach() {
super.detach();
@@ -3730,6 +3807,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container#removeAllItems()
*/
+
@Override
public boolean removeAllItems() {
currentPageFirstItemId = null;
@@ -3742,6 +3820,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container#removeItem(Object)
*/
+
@Override
public boolean removeItem(Object itemId) {
final Object nextItemId = nextItemId(itemId);
@@ -3760,6 +3839,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container#removeContainerProperty(Object)
*/
+
@Override
public boolean removeContainerProperty(Object propertyId)
throws UnsupportedOperationException {
@@ -3786,6 +3866,7 @@ public class Table extends AbstractSelect implements Action.Container,
* @see com.vaadin.data.Container#addContainerProperty(Object, Class,
* Object)
*/
+
@Override
public boolean addContainerProperty(Object propertyId, Class<?> type,
Object defaultValue) throws UnsupportedOperationException {
@@ -3941,6 +4022,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.ui.Select#getVisibleItemIds()
*/
+
@Override
public Collection<?> getVisibleItemIds() {
@@ -3964,6 +4046,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.ItemSetChangeListener#containerItemSetChange(com.vaadin.data.Container.ItemSetChangeEvent)
*/
+
@Override
public void containerItemSetChange(Container.ItemSetChangeEvent event) {
super.containerItemSetChange(event);
@@ -3980,6 +4063,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.PropertySetChangeListener#containerPropertySetChange(com.vaadin.data.Container.PropertySetChangeEvent)
*/
+
@Override
public void containerPropertySetChange(
Container.PropertySetChangeEvent event) {
@@ -4023,6 +4107,7 @@ public class Table extends AbstractSelect implements Action.Container,
* if set to true.
* @see com.vaadin.ui.Select#setNewItemsAllowed(boolean)
*/
+
@Override
public void setNewItemsAllowed(boolean allowNewOptions)
throws UnsupportedOperationException {
@@ -4036,6 +4121,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#nextItemId(java.lang.Object)
*/
+
public Object nextItemId(Object itemId) {
return ((Container.Ordered) items).nextItemId(itemId);
}
@@ -4046,6 +4132,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#prevItemId(java.lang.Object)
*/
+
public Object prevItemId(Object itemId) {
return ((Container.Ordered) items).prevItemId(itemId);
}
@@ -4055,6 +4142,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#firstItemId()
*/
+
public Object firstItemId() {
return ((Container.Ordered) items).firstItemId();
}
@@ -4064,6 +4152,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#lastItemId()
*/
+
public Object lastItemId() {
return ((Container.Ordered) items).lastItemId();
}
@@ -4074,6 +4163,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#isFirstId(java.lang.Object)
*/
+
public boolean isFirstId(Object itemId) {
return ((Container.Ordered) items).isFirstId(itemId);
}
@@ -4084,6 +4174,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#isLastId(java.lang.Object)
*/
+
public boolean isLastId(Object itemId) {
return ((Container.Ordered) items).isLastId(itemId);
}
@@ -4093,6 +4184,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object)
*/
+
public Object addItemAfter(Object previousItemId)
throws UnsupportedOperationException {
Object itemId = ((Container.Ordered) items)
@@ -4109,6 +4201,7 @@ public class Table extends AbstractSelect implements Action.Container,
* @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object,
* java.lang.Object)
*/
+
public Item addItemAfter(Object previousItemId, Object newItemId)
throws UnsupportedOperationException {
Item item = ((Container.Ordered) items).addItemAfter(previousItemId,
@@ -4201,6 +4294,7 @@ public class Table extends AbstractSelect implements Action.Container,
* boolean[])
*
*/
+
public void sort(Object[] propertyId, boolean[] ascending)
throws UnsupportedOperationException {
final Container c = getContainerDataSource();
@@ -4236,6 +4330,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Sortable#getSortableContainerPropertyIds()
*/
+
public Collection<?> getSortableContainerPropertyIds() {
final Container c = getContainerDataSource();
if (c instanceof Container.Sortable && !isSortDisabled()) {
@@ -4436,6 +4531,7 @@ public class Table extends AbstractSelect implements Action.Container,
}
// Identical to AbstractCompoenentContainer.setEnabled();
+
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
@@ -4560,7 +4656,6 @@ public class Table extends AbstractSelect implements Action.Container,
* initialized from server and no subsequent requests requests are needed
* during that drag and drop operation.
*/
- @ClientCriterion(VLazyInitItemIdentifiers.class)
public static abstract class TableDropCriterion extends ServerSideCriterion {
private Table table;
@@ -4574,6 +4669,7 @@ public class Table extends AbstractSelect implements Action.Container,
* com.vaadin.event.dd.acceptcriteria.ServerSideCriterion#getIdentifier
* ()
*/
+
@Override
protected String getIdentifier() {
return TableDropCriterion.class.getCanonicalName();
@@ -4605,6 +4701,7 @@ public class Table extends AbstractSelect implements Action.Container,
* com.vaadin.event.dd.acceptcriteria.AcceptCriterion#paintResponse(
* com.vaadin.terminal.PaintTarget)
*/
+
@Override
public void paintResponse(PaintTarget target) throws PaintException {
/*
@@ -5276,4 +5373,11 @@ public class Table extends AbstractSelect implements Action.Container,
public boolean isComponentVisible(Component childComponent) {
return true;
}
+
+ private final Logger getLogger() {
+ if (logger == null) {
+ logger = Logger.getLogger(Table.class.getName());
+ }
+ return logger;
+ }
}
diff --git a/src/com/vaadin/ui/Tree.java b/src/com/vaadin/ui/Tree.java
index db738fee58..dacb3a2027 100644
--- a/src/com/vaadin/ui/Tree.java
+++ b/src/com/vaadin/ui/Tree.java
@@ -34,7 +34,6 @@ import com.vaadin.event.dd.DragSource;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.DropTarget;
import com.vaadin.event.dd.TargetDetails;
-import com.vaadin.event.dd.acceptcriteria.ClientCriterion;
import com.vaadin.event.dd.acceptcriteria.ClientSideCriterion;
import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion;
import com.vaadin.event.dd.acceptcriteria.TargetDetailIs;
@@ -43,8 +42,6 @@ import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.ui.dd.VLazyInitItemIdentifiers;
-import com.vaadin.terminal.gwt.client.ui.dd.VTargetInSubtree;
import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation;
import com.vaadin.terminal.gwt.client.ui.tree.TreeConnector;
import com.vaadin.terminal.gwt.client.ui.tree.VTree;
@@ -1396,7 +1393,6 @@ public class Tree extends AbstractSelect implements Container.Hierarchical,
* initialized from server and no subsequent requests requests are needed
* during that drag and drop operation.
*/
- @ClientCriterion(VLazyInitItemIdentifiers.class)
public static abstract class TreeDropCriterion extends ServerSideCriterion {
private Tree tree;
@@ -1513,7 +1509,6 @@ public class Tree extends AbstractSelect implements Container.Hierarchical,
* <p>
* The root items is also consider to be valid target.
*/
- @ClientCriterion(VTargetInSubtree.class)
public class TargetInSubtree extends ClientSideCriterion {
private Object rootId;
diff --git a/src/com/vaadin/ui/TreeTable.java b/src/com/vaadin/ui/TreeTable.java
index 9607add2c9..3294f6fab0 100644
--- a/src/com/vaadin/ui/TreeTable.java
+++ b/src/com/vaadin/ui/TreeTable.java
@@ -49,9 +49,6 @@ import com.vaadin.ui.Tree.ExpandListener;
@SuppressWarnings({ "serial" })
public class TreeTable extends Table implements Hierarchical {
- private static final Logger logger = Logger.getLogger(TreeTable.class
- .getName());
-
private interface ContainerStrategy extends Serializable {
public int size();
@@ -84,6 +81,7 @@ public class TreeTable extends Table implements Hierarchical {
* Consider adding getDepth to {@link Collapsible}, might help
* scalability with some container implementations.
*/
+
public int getDepth(Object itemId) {
int depth = 0;
Hierarchical hierarchicalContainer = getContainerDataSource();
@@ -222,9 +220,9 @@ public class TreeTable extends Table implements Hierarchical {
boolean removed = openItems.remove(itemId);
if (!removed) {
openItems.add(itemId);
- logger.finest("Item " + itemId + " is now expanded");
+ getLogger().finest("Item " + itemId + " is now expanded");
} else {
- logger.finest("Item " + itemId + " is now collapsed");
+ getLogger().finest("Item " + itemId + " is now collapsed");
}
clearPreorderCache();
}
@@ -789,4 +787,8 @@ public class TreeTable extends Table implements Hierarchical {
requestRepaint();
}
+ private static final Logger getLogger() {
+ return Logger.getLogger(TreeTable.class.getName());
+ }
+
}
diff --git a/src/com/vaadin/ui/UniqueSerializable.java b/src/com/vaadin/ui/UniqueSerializable.java
new file mode 100644
index 0000000000..828b285538
--- /dev/null
+++ b/src/com/vaadin/ui/UniqueSerializable.java
@@ -0,0 +1,30 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.ui;
+
+import java.io.Serializable;
+
+/**
+ * A base class for generating an unique object that is serializable.
+ * <p>
+ * This class is abstract but has no abstract methods to force users to create
+ * an anonymous inner class. Otherwise each instance will not be unique.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0
+ *
+ */
+public abstract class UniqueSerializable implements Serializable {
+
+ @Override
+ public int hashCode() {
+ return getClass().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return getClass() == obj.getClass();
+ }
+}
diff --git a/src/com/vaadin/ui/Window.java b/src/com/vaadin/ui/Window.java
index 3c17baf414..02556c9961 100644
--- a/src/com/vaadin/ui/Window.java
+++ b/src/com/vaadin/ui/Window.java
@@ -24,6 +24,7 @@ import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Vaadin6Component;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
+import com.vaadin.terminal.gwt.client.ui.root.VRoot;
import com.vaadin.terminal.gwt.client.ui.window.WindowServerRpc;
import com.vaadin.terminal.gwt.client.ui.window.WindowState;
@@ -83,6 +84,10 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
}
};
+ private int browserWindowWidth = -1;
+
+ private int browserWindowHeight = -1;
+
/**
* Creates a new unnamed window with a default layout.
*/
@@ -119,6 +124,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
*
* @see com.vaadin.ui.Panel#addComponent(com.vaadin.ui.Component)
*/
+
@Override
public void addComponent(Component c) {
if (c instanceof Window) {
@@ -136,6 +142,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
*
* @see com.vaadin.ui.Panel#paintContent(com.vaadin.terminal.PaintTarget)
*/
+
@Override
public synchronized void paintContent(PaintTarget target)
throws PaintException {
@@ -153,6 +160,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
*
* @see com.vaadin.ui.Panel#changeVariables(java.lang.Object, java.util.Map)
*/
+
@Override
public void changeVariables(Object source, Map<String, Object> variables) {
@@ -161,15 +169,29 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
// size is handled in super class, but resize events only in windows ->
// so detect if size change occurs before super.changeVariables()
if (variables.containsKey("height")
- && (getHeightUnits() != UNITS_PIXELS || (Integer) variables
+ && (getHeightUnits() != Unit.PIXELS || (Integer) variables
.get("height") != getHeight())) {
sizeHasChanged = true;
}
if (variables.containsKey("width")
- && (getWidthUnits() != UNITS_PIXELS || (Integer) variables
+ && (getWidthUnits() != Unit.PIXELS || (Integer) variables
.get("width") != getWidth())) {
sizeHasChanged = true;
}
+ Integer browserHeightVar = (Integer) variables
+ .get(VRoot.BROWSER_HEIGHT_VAR);
+ if (browserHeightVar != null
+ && browserHeightVar.intValue() != browserWindowHeight) {
+ browserWindowHeight = browserHeightVar.intValue();
+ sizeHasChanged = true;
+ }
+ Integer browserWidthVar = (Integer) variables
+ .get(VRoot.BROWSER_WIDTH_VAR);
+ if (browserWidthVar != null
+ && browserWidthVar.intValue() != browserWindowWidth) {
+ browserWindowWidth = browserWidthVar.intValue();
+ sizeHasChanged = true;
+ }
super.changeVariables(source, variables);
@@ -604,8 +626,13 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
}
/**
- * Request to center this window on the screen. <b>Note:</b> affects
- * sub-windows only.
+ * Sets this window to be centered relative to its parent window. Affects
+ * sub-windows only. If the window is resized as a result of the size of its
+ * content changing, it will keep itself centered as long as its position is
+ * not explicitly changed programmatically or by the user.
+ * <p>
+ * <b>NOTE:</b> This method has several issues as currently implemented.
+ * Please refer to http://dev.vaadin.com/ticket/8971 for details.
*/
public void center() {
getState().setCentered(true);
@@ -788,6 +815,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
*
* @see com.vaadin.event.FieldEvents.FocusNotifier#addListener(com.vaadin.event.FieldEvents.FocusListener)
*/
+
public void addListener(FocusListener listener) {
addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener,
FocusListener.focusMethod);
@@ -804,6 +832,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
*
* @see com.vaadin.event.FieldEvents.BlurNotifier#addListener(com.vaadin.event.FieldEvents.BlurListener)
*/
+
public void addListener(BlurListener listener) {
addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener,
BlurListener.blurMethod);
@@ -819,6 +848,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
* If the window is a sub-window focusing will cause the sub-window to be
* brought on top of other sub-windows on gain keyboard focus.
*/
+
@Override
public void focus() {
/*
@@ -834,5 +864,4 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
public WindowState getState() {
return (WindowState) super.getState();
}
-
}
diff --git a/src/com/vaadin/ui/themes/ChameleonTheme.java b/src/com/vaadin/ui/themes/ChameleonTheme.java
index bfb9686018..5ae8cd4e57 100644
--- a/src/com/vaadin/ui/themes/ChameleonTheme.java
+++ b/src/com/vaadin/ui/themes/ChameleonTheme.java
@@ -5,7 +5,7 @@ package com.vaadin.ui.themes;
public class ChameleonTheme extends BaseTheme {
- public static final String THEME_NAME = "Chameleon";
+ public static final String THEME_NAME = "chameleon";
/***************************************************************************
* Label styles