diff options
Diffstat (limited to 'src')
53 files changed, 1881 insertions, 642 deletions
diff --git a/src/com/vaadin/Application.java b/src/com/vaadin/Application.java index 4da1d52c00..58ad4da684 100644 --- a/src/com/vaadin/Application.java +++ b/src/com/vaadin/Application.java @@ -1066,12 +1066,14 @@ public class Application implements Terminal.ErrorListener, Serializable { * the change event. * @see com.vaadin.terminal.Terminal.ErrorListener#terminalError(com.vaadin.terminal.Terminal.ErrorEvent) */ + @Override 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 +1092,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); } /** @@ -1809,6 +1811,7 @@ public class Application implements Terminal.ErrorListener, Serializable { this.throwable = throwable; } + @Override public Throwable getThrowable() { return throwable; } @@ -2416,4 +2419,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/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..a2a76ec6cf 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,23 +106,29 @@ 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); } }; + @Override public String getName() { return name; } + @Override public Class<?> getPropertyType() { return propertyType; } + @Override public Property<?> createProperty(Object bean) { return new MethodProperty<Object>(propertyType, bean, readMethod, 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..66f5737683 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} */ + @Override 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) */ + @Override 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) */ + @Override 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() */ + @Override 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) */ + @Override 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} */ + @Override 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) */ + @Override 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() */ + @Override 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) */ + @Override 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() */ + @Override 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} */ + @Override public void addContainerFilter(Filter filter) throws UnsupportedFilterException { // filter.setCaseSensitive(!ignoreCase); @@ -510,6 +519,7 @@ public class SQLContainer implements Container, Container.Filterable, /** * {@inheritDoc} */ + @Override public void removeContainerFilter(Filter filter) { filters.remove(filter); } @@ -549,6 +559,7 @@ public class SQLContainer implements Container, Container.Filterable, /** * {@inheritDoc} */ + @Override 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) */ + @Override 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) */ + @Override 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) */ + @Override 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) */ + @Override 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() */ + @Override 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() */ + @Override 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) */ + @Override 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) */ + @Override 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[]) */ + @Override 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() */ + @Override 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) */ + @Override 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) */ + @Override 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) */ + @Override 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) */ + @Override 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) */ + @Override 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) */ + @Override 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) */ + @Override 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) */ + @Override 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) */ + @Override public void removeListener(Container.ItemSetChangeListener listener) { if (itemSetChangeListeners != null) { itemSetChangeListeners.remove(listener); @@ -1442,6 +1477,7 @@ public class SQLContainer implements Container, Container.Filterable, super(source); } + @Override public Container getContainer() { return (Container) getSource(); } @@ -1577,7 +1613,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 +1677,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/SourceIs.java b/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java index 0d29e9a327..62bf64f76c 100644 --- a/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java +++ b/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java @@ -25,8 +25,6 @@ import com.vaadin.ui.Component; @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 +41,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/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/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..aee2b13e0e 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() { + @Override public void execute() { ApplicationConfiguration appConf = getConfigFromDOM(applicationId); ApplicationConnection a = GWT @@ -551,6 +553,7 @@ public class ApplicationConfiguration implements EntryPoint { private static DeferredWidgetLoader deferredWidgetLoader; + @Override public void onModuleLoad() { // Prepare VConsole for debugging @@ -568,6 +571,7 @@ public class ApplicationConfiguration implements EntryPoint { * GWT hosted mode. */ GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { + @Override public void onUncaughtException(Throwable e) { /* * Note in case of null console (without ?debug) we eat @@ -602,12 +606,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 +625,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 1349af465d..f0470c8ee8 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -371,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. * @@ -852,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(); } } }); 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/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/ui/AbstractClickEventHandler.java b/src/com/vaadin/terminal/gwt/client/ui/AbstractClickEventHandler.java index 31204aa0c6..2802277281 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() { + @Override + public void onPreviewNativeEvent(NativePreviewEvent event) { + if (event.getTypeInt() == Event.ONMOUSEUP) { + mouseUpEventPreviewRegistration.removeHandler(); + + // Event's reported target not always correct if event + // capture is in use + Element elementUnderMouse = Util.getElementUnderMouse(event + .getNativeEvent()); + if (lastMouseDownTarget != null + && elementUnderMouse.cast() == lastMouseDownTarget) { + mouseUpPreviewMatched = true; + } else { + System.out.println("Ignoring mouseup from " + + elementUnderMouse + " when mousedown was on " + + lastMouseDownTarget); + } + } + } + }; + public AbstractClickEventHandler(ComponentConnector connector, String clickEventIdentifier) { this.connector = connector; @@ -36,7 +83,9 @@ 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, + MouseUpEvent.getType()); mouseUpHandlerRegistration = registerHandler(this, MouseUpEvent.getType()); contextMenuHandlerRegistration = registerHandler(this, @@ -45,14 +94,16 @@ public abstract class AbstractClickEventHandler implements DoubleClickHandler, DoubleClickEvent.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; + contextMenuHandlerRegistration = null; doubleClickHandlerRegistration = null; } @@ -93,6 +144,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. */ + @Override public void onContextMenu(ContextMenuEvent event) { if (hasEventListener() && shouldFireEvent(event)) { // Prevent showing the browser's context menu when there is a right @@ -101,18 +153,35 @@ public abstract class AbstractClickEventHandler implements DoubleClickHandler, } } - /** - * Event handler for mouse up. This is used to detect all single click - * events. - */ + @Override + public void onMouseDown(MouseDownEvent event) { + /* + * When getting a mousedown event, we must detect where the + * corresponding mouseup event if it's on a different part of the page. + */ + lastMouseDownTarget = event.getNativeEvent().getEventTarget(); + mouseUpPreviewMatched = false; + mouseUpEventPreviewRegistration = Event + .addNativePreviewHandler(mouseUpPreviewHandler); + } + + @Override public void onMouseUp(MouseUpEvent event) { - // 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) { // "Click" with left, right or middle button fireClick(event.getNativeEvent()); } + mouseUpPreviewMatched = false; + lastMouseDownTarget = null; } /** @@ -140,6 +209,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. */ + @Override public void onDoubleClick(DoubleClickEvent event) { if (hasEventListener() && shouldFireEvent(event)) { fireClick(event.getNativeEvent()); 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/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..d9320787e8 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(); } @@ -428,6 +434,7 @@ public class VAccordion extends VTabsheetBase { } } + @Override public void onClick(ClickEvent event) { onSelectTab(this); } @@ -488,6 +495,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..584be55bce 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; @@ -284,6 +286,7 @@ public class VButton extends FocusWidget implements ClickHandler { * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event * .dom.client.ClickEvent) */ + @Override public void onClick(ClickEvent event) { if (BrowserInfo.get().isSafari()) { VButton.this.setFocus(true); 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..08985cc471 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 */ + @Override 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. */ + @Override public String getReplacementString() { return caption; } @@ -147,6 +150,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, /** * Executes a selection of this item. */ + @Override public void execute() { onSuggestionSelected(this); } @@ -449,6 +453,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * com.google.gwt.user.client.ui.PopupPanel$PositionCallback#setPosition * (int, int) */ + @Override public void setPosition(int offsetWidth, int offsetHeight) { int top = -1; @@ -585,6 +590,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, private VLazyExecutor delayedImageLoadExecutioner = new VLazyExecutor( 100, new ScheduledCommand() { + @Override public void execute() { if (suggestionPopup.isVisible() && suggestionPopup.isAttached()) { @@ -742,6 +748,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, private static final String SUBPART_PREFIX = "item"; + @Override public Element getSubPartElement(String subPart) { int index = Integer.parseInt(subPart.substring(SUBPART_PREFIX .length())); @@ -751,6 +758,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, return item.getElement(); } + @Override public String getSubPartName(Element subElement) { if (!getElement().isOrHasChild(subElement)) { return null; @@ -773,6 +781,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, return null; } + @Override public void onLoad(LoadEvent event) { // Handle icon onload events to ensure shadow is resized // correctly @@ -951,6 +960,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, public VFilterSelect() { selectedItemIcon.setStyleName("v-icon"); selectedItemIcon.addLoadHandler(new LoadHandler() { + @Override public void onLoad(LoadEvent event) { if (BrowserInfo.get().isIE8()) { // IE8 needs some help to discover it should reposition the @@ -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) */ + @Override 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 */ + @Override 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 */ + @Override 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) */ + @Override public void onFocus(FocusEvent event) { /* @@ -1511,6 +1525,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * .dom.client.BlurEvent) */ + @Override public void onBlur(BlurEvent event) { if (BrowserInfo.get().isIE() && preventNextBlurEventInIE) { @@ -1567,6 +1582,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, * * @see com.vaadin.terminal.gwt.client.Focusable#focus() */ + @Override public void focus() { focused = true; if (prompting && !readonly) { @@ -1674,4 +1690,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/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/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/VPanel.java b/src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java index e2d3d443a0..16637450dd 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 final TouchScrollHandler touchScrollHandler; public VPanel() { super(); @@ -74,11 +73,12 @@ 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"); + + touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this, + contentNode); } /** @@ -100,6 +100,7 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner, * * @see com.vaadin.terminal.gwt.client.Focusable#focus() */ + @Override public void focus() { setFocus(true); @@ -174,14 +175,7 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner, } } - protected TouchScrollDelegate getTouchScrollDelegate() { - if (touchScrollDelegate == null) { - touchScrollDelegate = new TouchScrollDelegate(contentNode); - } - return touchScrollDelegate; - - } - + @Override public ShortcutActionHandler getShortcutActionHandler() { return shortcutHandler; } 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 85e6f7f91a..ab562f5216 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,7 @@ 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.VLazyExecutor; import com.vaadin.terminal.gwt.client.ui.textfield.VTextField; @@ -37,21 +39,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 +76,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; @@ -96,6 +119,7 @@ public class VRoot extends SimplePanel implements ResizeHandler, * whenever the value changes. */ private final ValueChangeHandler<String> historyChangeHandler = new ValueChangeHandler<String>() { + @Override public void onValueChange(ValueChangeEvent<String> event) { String newFragment = event.getValue(); @@ -110,9 +134,9 @@ public class VRoot extends SimplePanel implements ResizeHandler, private VLazyExecutor delayedResizeExecutor = new VLazyExecutor(200, new ScheduledCommand() { + @Override public void execute() { - windowSizeMaybeChanged(Window.getClientWidth(), - Window.getClientHeight()); + performSizeCheck(); } }); @@ -124,6 +148,27 @@ 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); + TouchScrollDelegate.enableTouchScrolling(this, getElement()); + } + + /** + * Start to periodically monitor for parent element resizes if embedded + * application (e.g. portlet). + */ + 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 +187,94 @@ 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. + * + * 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 newWidth + * @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(); @@ -199,6 +306,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); @@ -236,14 +354,19 @@ public class VRoot extends SimplePanel implements ResizeHandler, * com.google.gwt.event.logical.shared.ResizeHandler#onResize(com.google * .gwt.event.logical.shared.ResizeEvent) */ + @Override 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 @@ -259,8 +382,7 @@ public class VRoot extends SimplePanel implements ResizeHandler, if (lazy) { delayedResizeExecutor.trigger(); } else { - windowSizeMaybeChanged(Window.getClientWidth(), - Window.getClientHeight()); + performSizeCheck(); } } @@ -268,8 +390,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) @@ -277,6 +410,7 @@ public class VRoot extends SimplePanel implements ResizeHandler, $wnd.location = url; }-*/; + @Override public void onWindowClosing(Window.ClosingEvent event) { // Change focus on this window in order to ensure that all state is // collected from textfields @@ -296,10 +430,12 @@ public class VRoot extends SimplePanel implements ResizeHandler, } }-*/; + @Override public ShortcutActionHandler getShortcutActionHandler() { return actionHandler; } + @Override public void focus() { getElement().focus(); } 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..330214d500 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; @@ -77,6 +78,7 @@ public class VSlider extends SimpleFocusablePanel implements Field, private VLazyExecutor delayedValueUpdater = new VLazyExecutor(100, new ScheduledCommand() { + @Override public void execute() { updateValueToServer(); acceleration = 1; @@ -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() { + @Override 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) { @@ -405,6 +422,7 @@ public class VSlider extends SimpleFocusablePanel implements Field, } } + @Override public void iLayout() { if (vertical) { setHeight(); 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..b5cedc42d4 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java @@ -41,6 +41,7 @@ public abstract class AbstractSplitPanelConnector extends getWidget().addHandler(new SplitterMoveHandler() { + @Override public void splitterMoved(SplitterMoveEvent event) { String position = getWidget().getSplitterPosition(); float pos = 0; @@ -61,6 +62,7 @@ public abstract class AbstractSplitPanelConnector extends }, SplitterMoveEvent.TYPE); } + @Override public void updateCaption(ComponentConnector component) { // TODO Implement caption handling } @@ -127,6 +129,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(); @@ -138,6 +146,7 @@ public abstract class AbstractSplitPanelConnector extends } + @Override public void layout() { VAbstractSplitPanel splitPanel = getWidget(); splitPanel.setSplitPosition(splitPanel.position); 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..e112fac304 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java @@ -31,6 +31,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; @@ -87,12 +88,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 final TouchScrollHandler touchScrollHandler; + protected Element scrolledContainer; protected int origScrollTop; - private TouchScrollDelegate touchScrollDelegate; - public VAbstractSplitPanel() { this(ORIENTATION_HORIZONTAL); } @@ -116,24 +121,27 @@ public class VAbstractSplitPanel extends ComplexPanel { setOrientation(orientation); sinkEvents(Event.MOUSEEVENTS); + touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this, + firstContainer, secondContainer); + addDomHandler(new TouchCancelHandler() { + @Override public void onTouchCancel(TouchCancelEvent event) { // TODO When does this actually happen?? VConsole.log("TOUCH CANCEL"); } }, TouchCancelEvent.getType()); addDomHandler(new TouchStartHandler() { + @Override public void onTouchStart(TouchStartEvent event) { Node target = event.getTouches().get(0).getTarget().cast(); if (splitter.isOrHasChild(target)) { onMouseDown(Event.as(event.getNativeEvent())); - } else { - getTouchScrollDelegate().onTouchStart(event); } } - }, TouchStartEvent.getType()); addDomHandler(new TouchMoveHandler() { + @Override public void onTouchMove(TouchMoveEvent event) { if (resizing) { onMouseMove(Event.as(event.getNativeEvent())); @@ -141,6 +149,7 @@ public class VAbstractSplitPanel extends ComplexPanel { } }, TouchMoveEvent.getType()); addDomHandler(new TouchEndHandler() { + @Override public void onTouchEnd(TouchEndEvent event) { if (resizing) { onMouseUp(Event.as(event.getNativeEvent())); @@ -150,14 +159,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 +173,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 +189,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 +226,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 +467,6 @@ public class VAbstractSplitPanel extends ComplexPanel { } break; } - } void setFirstWidget(Widget w) { @@ -481,16 +572,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 +605,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 +732,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) { 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..e390643d9d 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 */ @@ -321,6 +325,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, final FocusableScrollPanel scrollBodyPanel = new FocusableScrollPanel(true); private KeyPressHandler navKeyPressHandler = new KeyPressHandler() { + @Override public void onKeyPress(KeyPressEvent keyPressEvent) { // This is used for Firefox only, since Firefox auto-repeat // works correctly only if we use a key press handler, other @@ -358,6 +363,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, private KeyUpHandler navKeyUpHandler = new KeyUpHandler() { + @Override public void onKeyUp(KeyUpEvent keyUpEvent) { NativeEvent event = keyUpEvent.getNativeEvent(); int keyCode = event.getKeyCode(); @@ -385,6 +391,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, private KeyDownHandler navKeyDownHandler = new KeyDownHandler() { + @Override public void onKeyDown(KeyDownEvent keyDownEvent) { NativeEvent event = keyDownEvent.getNativeEvent(); // This is not used for Firefox @@ -489,12 +496,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 +516,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() { + @Override public void onContextMenu(ContextMenuEvent event) { handleBodyContextMenu(event); } @@ -536,22 +539,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>() { + @Override 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 +890,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 +1846,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() { + @Override public void execute() { scrollBodyPanel .setScrollPosition(measureRowHeightOffset(firstvisible)); @@ -1888,6 +1883,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, */ scrollBody.reLayoutComponents(); Scheduler.get().scheduleDeferred(new Command() { + @Override public void execute() { Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement()); } @@ -2218,6 +2214,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, setWidth(tdWidth + "px"); } else { Scheduler.get().scheduleDeferred(new Command() { + @Override public void execute() { int tdWidth = width + scrollBody.getCellExtraWidth(); @@ -2814,6 +2811,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, final int newWidth = width; Scheduler.get().scheduleDeferred( new ScheduledCommand() { + @Override 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() { + @Override public void execute() { triggerLazyColumnAdjustment(true); } @@ -2952,6 +2951,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, visibleCells.add(newIndex, hCell); } + @Override public Iterator<Widget> iterator() { return visibleCells.iterator(); } @@ -3029,6 +3029,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 +3041,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 +3067,27 @@ 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 */ + @Override public Action[] getActions() { Object[] cols; if (columnReordering && columnOrder != null) { @@ -3115,15 +3130,20 @@ 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; } + @Override public ApplicationConnection getClient() { return client; } + @Override public String getPaintableId() { return paintableId; } @@ -3200,6 +3220,10 @@ public class VScrollTable extends FlowPanel implements HasWidgets, * The text in the footer */ public void setText(String footerText) { + if (footerText == null || footerText.equals("")) { + footerText = " "; + } + DOM.setInnerHTML(captionContainer, footerText); } @@ -3295,6 +3319,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, setWidth(tdWidth + "px"); } else { Scheduler.get().scheduleDeferred(new Command() { + @Override public void execute() { int borderWidths = 1; int tdWidth = width @@ -3557,6 +3582,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, * * @see com.google.gwt.user.client.ui.HasWidgets#iterator() */ + @Override public Iterator<Widget> iterator() { return visibleCells.iterator(); } @@ -3835,7 +3861,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); @@ -4095,6 +4121,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, renderedRows.add(actualIx, row); } + @Override public Iterator<Widget> iterator() { return renderedRows.iterator(); } @@ -4388,7 +4415,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 +4422,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; @@ -4692,6 +4720,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, childWidgets.add(w); } + @Override public Iterator<Widget> iterator() { return childWidgets.iterator(); } @@ -4785,12 +4814,125 @@ 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 @@ -5066,9 +5207,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } break; case Event.ONMOUSEOUT: - if (targetCellOrRowFound) { - mDown = false; - } break; default: break; @@ -5098,7 +5236,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 +5427,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, * * @see com.vaadin.terminal.gwt.client.ui.IActionOwner#getActions () */ + @Override public Action[] getActions() { if (actionKeys == null) { return new Action[] {}; @@ -5312,10 +5450,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets, return actions; } + @Override public ApplicationConnection getClient() { return client; } + @Override public String getPaintableId() { return paintableId; } @@ -5366,6 +5506,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, // widths. Scheduler.get().scheduleDeferred(new ScheduledCommand() { + @Override public void execute() { if (showRowHeaders) { setCellWidth(0, tHead.getHeaderCell(0).getWidth()); @@ -5682,7 +5823,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 +5836,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } scrollBody.reLayoutComponents(); Scheduler.get().scheduleDeferred(new Command() { + @Override public void execute() { Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement()); } @@ -5804,15 +5946,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() { + @Override + public void execute() { + Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement()); + } + }); } + triggerLazyColumnAdjustment(false); + /* * setting height may affect wheter the component has scrollbars -> * needs scrolling or not @@ -5833,6 +5986,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, if (initializedAndAttached) { if (visible) { Scheduler.get().scheduleDeferred(new Command() { + @Override public void execute() { scrollBodyPanel .setScrollPosition(measureRowHeightOffset(firstRowInViewPort)); @@ -5866,6 +6020,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, * This method has logic which rows needs to be requested from server when * user scrolls */ + @Override public void onScroll(ScrollEvent event) { scrollLeft = scrollBodyPanel.getElement().getScrollLeft(); scrollTop = scrollBodyPanel.getScrollPosition(); @@ -5894,6 +6049,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, // correct // value available soon. Scheduler.get().scheduleDeferred(new Command() { + @Override public void execute() { onScroll(null); } @@ -5974,6 +6130,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, return (int) Math.ceil(scrollTop / scrollBody.getRowHeight()); } + @Override public VScrollTableDropHandler getDropHandler() { return dropHandler; } @@ -6053,6 +6210,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, deEmphasis(); final TableDDDetails newDetails = dropDetails; VAcceptCallback cb = new VAcceptCallback() { + @Override public void accepted(VDragEvent event) { if (newDetails.equals(dropDetails)) { dragAccepted(event); @@ -6129,6 +6287,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, return ConnectorMap.get(client).getConnector(VScrollTable.this); } + @Override public ApplicationConnection getApplicationConnection() { return client; } @@ -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) */ + @Override 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) */ + @Override 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() */ + @Override public void focus() { if (isFocusable()) { scrollBodyPanel.focus(); @@ -6630,6 +6792,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, public void lazyRevertFocusToRow(final VScrollTableRow currentlyFocusedRow) { Scheduler.get().scheduleFinally(new ScheduledCommand() { + @Override public void execute() { if (currentlyFocusedRow != null) { setRowFocus(currentlyFocusedRow); @@ -6642,6 +6805,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, }); } + @Override public Action[] getActions() { if (bodyActionKeys == null) { return new Action[] {}; @@ -6657,10 +6821,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets, return actions; } + @Override public ApplicationConnection getClient() { return client; } + @Override public String getPaintableId() { return paintableId; } 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..b63fe483ce 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java +++ b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java @@ -212,14 +212,17 @@ public class VTabsheet extends VTabsheetBase implements Focusable, tabCaption.setWidth(tabCaption.getRequiredWidth() + "px"); } + @Override public HandlerRegistration addFocusHandler(FocusHandler handler) { return addDomHandler(handler, FocusEvent.getType()); } + @Override public HandlerRegistration addBlurHandler(BlurHandler handler) { return addDomHandler(handler, BlurEvent.getType()); } + @Override public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) { return addDomHandler(handler, KeyDownEvent.getType()); } @@ -331,6 +334,11 @@ public class VTabsheet extends VTabsheetBase implements Focusable, } return width; } + + public Element getCloseButton() { + return closeButton; + } + } static class TabBar extends ComplexPanel implements ClickHandler, @@ -357,6 +365,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, setElement(el); } + @Override public void onClose(VCloseEvent event) { Tab tab = event.getTab(); if (!tab.isEnabledOnServer()) { @@ -392,8 +401,16 @@ public class VTabsheet extends VTabsheetBase implements Focusable, return t; } + @Override 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 +1038,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, final Style style = scroller.getStyle(); style.setProperty("whiteSpace", "normal"); Scheduler.get().scheduleDeferred(new Command() { + @Override public void execute() { style.setProperty("whiteSpace", ""); } @@ -1105,6 +1123,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, } } + @Override public void onBlur(BlurEvent event) { if (focusedTab != null && event.getSource() instanceof Tab) { focusedTab = null; @@ -1114,6 +1133,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, } } + @Override public void onFocus(FocusEvent event) { if (focusedTab == null && event.getSource() instanceof Tab) { focusedTab = (Tab) event.getSource(); @@ -1123,6 +1143,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, } } + @Override public void focus() { tb.getTab(activeTabIndex).focus(); } @@ -1131,6 +1152,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, tb.getTab(activeTabIndex).blur(); } + @Override public void onKeyDown(KeyDownEvent event) { if (event.getSource() instanceof Tab) { int keycode = event.getNativeEvent().getKeyCode(); 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..294240b069 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. @@ -145,6 +146,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner, private VLazyExecutor delayedContentsSizeUpdater = new VLazyExecutor(200, new ScheduledCommand() { + @Override public void execute() { updateContentsSize(); } @@ -264,8 +266,10 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner, if (!orderingDefered) { orderingDefered = true; Scheduler.get().scheduleFinally(new Command() { + @Override public void execute() { doServerSideOrdering(); + VNotification.bringNotificationsToFront(); } }); } @@ -275,6 +279,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner, orderingDefered = false; VWindow[] array = windowOrder.toArray(new VWindow[windowOrder.size()]); Arrays.sort(array, new Comparator<VWindow>() { + @Override public int compare(VWindow o1, VWindow o2) { /* * Order by modality, then by bringtofront sequence. @@ -852,10 +857,12 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner, true); } + @Override public ShortcutActionHandler getShortcutActionHandler() { return shortcutHandler; } + @Override public void onScroll(ScrollEvent event) { client.updateVariable(id, "scrollTop", contentPanel.getScrollPosition(), false); @@ -864,6 +871,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner, } + @Override public void onKeyDown(KeyDownEvent event) { if (shortcutHandler != null) { shortcutHandler @@ -872,18 +880,21 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner, } } + @Override public void onBlur(BlurEvent event) { if (client.hasEventListeners(this, EventId.BLUR)) { client.updateVariable(id, EventId.BLUR, "", true); } } + @Override public void onFocus(FocusEvent event) { if (client.hasEventListeners(this, EventId.FOCUS)) { client.updateVariable(id, EventId.FOCUS, "", true); } } + @Override public void focus() { contentPanel.focus(); } diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java index 5b2be308a3..1eb6134128 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 { @@ -178,6 +175,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet this.portlet = portlet; } + @Override public void criticalNotification(WrappedRequest request, WrappedResponse response, String cap, String msg, String details, String outOfSyncURL) throws IOException { @@ -203,6 +201,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 +213,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet private boolean productionMode = false; private DeploymentConfiguration deploymentConfiguration = new DeploymentConfiguration() { + @Override public String getConfiguredWidgetset(WrappedRequest request) { String widgetset = getApplicationOrSystemProperty( @@ -233,6 +234,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet return widgetset; } + @Override public String getConfiguredTheme(WrappedRequest request) { // is the default theme defined by the portal? @@ -247,12 +249,14 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet return themeName; } + @Override public String getApplicationOrSystemProperty(String propertyName, String defaultValue) { return AbstractApplicationPortlet.this .getApplicationOrSystemProperty(propertyName, defaultValue); } + @Override public boolean isStandalone(WrappedRequest request) { return false; } @@ -271,6 +275,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 (/). */ + @Override public String getStaticFileLocation(WrappedRequest request) { String staticFileLocation = WrappedPortletRequest.cast(request) .getPortalProperty( @@ -288,6 +293,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } } + @Override public ClassLoader getClassLoader() { // Custom class loaders not currently supported in portlets (see // #8574) @@ -329,7 +335,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 +351,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 +671,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 +697,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 +738,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 +804,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)); } @@ -1060,6 +1070,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet this.throwable = throwable; } + @Override public Throwable getThrowable() { return throwable; } @@ -1141,4 +1152,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..86274869e9 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java @@ -74,6 +74,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements this.servlet = servlet; } + @Override public void criticalNotification(WrappedRequest request, WrappedResponse response, String cap, String msg, String details, String outOfSyncURL) throws IOException { @@ -87,9 +88,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 +97,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements private int resourceCacheTime = 3600; private DeploymentConfiguration deploymentConfiguration = new DeploymentConfiguration() { + @Override public String getStaticFileLocation(WrappedRequest request) { HttpServletRequest servletRequest = WrappedHttpServletRequest .cast(request); @@ -106,27 +105,32 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements .getStaticFilesLocation(servletRequest); } + @Override public String getConfiguredWidgetset(WrappedRequest request) { return getApplicationOrSystemProperty( AbstractApplicationServlet.PARAMETER_WIDGETSET, AbstractApplicationServlet.DEFAULT_WIDGETSET); } + @Override public String getConfiguredTheme(WrappedRequest request) { // Use the default return AbstractApplicationServlet.getDefaultTheme(); } + @Override public String getApplicationOrSystemProperty(String propertyName, String defaultValue) { return AbstractApplicationServlet.this .getApplicationOrSystemProperty(propertyName, defaultValue); } + @Override public boolean isStandalone(WrappedRequest request) { return true; } + @Override public ClassLoader getClassLoader() { try { return AbstractApplicationServlet.this.getClassLoader(); @@ -186,7 +190,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 +204,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 +218,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); } } @@ -478,9 +482,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 +801,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 +1059,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 +1071,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 +1097,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 +1112,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); } } @@ -1173,12 +1180,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 +1197,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; } } @@ -1672,6 +1683,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements this.throwable = throwable; } + @Override public Throwable getThrowable() { return throwable; } @@ -1733,4 +1745,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..86bbb4e80b 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>() { + @Override public int compare(Component c1, Component c2) { int depth1 = 0; while (c1.getParent() != null) { @@ -1273,14 +1276,17 @@ public abstract class AbstractCommunicationManager implements Serializable { private static class NullIterator<E> implements Iterator<E> { + @Override public boolean hasNext() { return false; } + @Override public E next() { return null; } + @Override public void remove() { } @@ -1472,6 +1478,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 +1486,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 +1524,7 @@ public abstract class AbstractCommunicationManager implements Serializable { msg += ", caption=" + caption; } } - logger.warning(msg); + getLogger().warning(msg); continue; } @@ -1545,14 +1552,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); } @@ -1726,6 +1732,7 @@ public abstract class AbstractCommunicationManager implements Serializable { this.throwable = throwable; } + @Override public Throwable getThrowable() { return throwable; } @@ -1895,8 +1902,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 +2103,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 +2241,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 +2395,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/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 819be7e671..d04ecb8380 100644 --- a/src/com/vaadin/terminal/gwt/server/DragAndDropService.java +++ b/src/com/vaadin/terminal/gwt/server/DragAndDropService.java @@ -29,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; @@ -46,13 +43,15 @@ public class DragAndDropService implements VariableOwner, ClientConnector { this.manager = manager; } + @Override public void changeVariables(Object source, Map<String, Object> variables) { Object owner = variables.get("dhowner"); // 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 @@ -82,8 +81,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; } @@ -182,10 +182,12 @@ public class DragAndDropService implements VariableOwner, ClientConnector { return transferable; } + @Override public boolean isEnabled() { return isConnectorEnabled(); } + @Override public boolean isImmediate() { return true; } @@ -219,70 +221,87 @@ public class DragAndDropService implements VariableOwner, ClientConnector { return false; } + @Override public SharedState getState() { // TODO Auto-generated method stub return null; } + @Override public String getConnectorId() { return VDragAndDropManager.DD_SERVICE; } + @Override public boolean isConnectorEnabled() { // Drag'n'drop can't be disabled return true; } + @Override public List<ClientMethodInvocation> retrievePendingRpcCalls() { return null; } + @Override public RpcManager getRpcManager(Class<?> rpcInterface) { // TODO Use rpc for drag'n'drop return null; } + @Override public Class<? extends SharedState> getStateType() { return SharedState.class; } + @Override public void requestRepaint() { // TODO Auto-generated method stub } + @Override public ClientConnector getParent() { // TODO Auto-generated method stub return null; } + @Override public void requestRepaintAll() { // TODO Auto-generated method stub } + @Override public void setParent(ClientConnector parent) { // TODO Auto-generated method stub } + @Override public void attach() { // TODO Auto-generated method stub } + @Override public void detach() { // TODO Auto-generated method stub } + @Override public Collection<Extension> getExtensions() { // TODO Auto-generated method stub return Collections.emptySet(); } + @Override 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..a9f84e62b6 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"; @@ -107,6 +104,7 @@ public class JsonPaintTarget implements PaintTarget { cacheEnabled = cachingRequired; } + @Override public void startTag(String tagName) throws PaintException { startTag(tagName, false); } @@ -162,6 +160,7 @@ public class JsonPaintTarget implements PaintTarget { * @throws Paintexception * if the paint operation failed. */ + @Override public void endTag(String tagName) throws PaintException { // In case of null data output nothing: if (tagName == null) { @@ -328,14 +327,17 @@ public class JsonPaintTarget implements PaintTarget { * if the paint operation failed. * */ + @Override public void addText(String str) throws PaintException { tag.addData("\"" + escapeJSON(str) + "\""); } + @Override public void addAttribute(String name, boolean value) throws PaintException { tag.addAttribute("\"" + name + "\":" + (value ? "true" : "false")); } + @Override @SuppressWarnings("deprecation") public void addAttribute(String name, Resource value) throws PaintException { @@ -365,22 +367,27 @@ public class JsonPaintTarget implements PaintTarget { } + @Override public void addAttribute(String name, int value) throws PaintException { tag.addAttribute("\"" + name + "\":" + String.valueOf(value)); } + @Override public void addAttribute(String name, long value) throws PaintException { tag.addAttribute("\"" + name + "\":" + String.valueOf(value)); } + @Override public void addAttribute(String name, float value) throws PaintException { tag.addAttribute("\"" + name + "\":" + String.valueOf(value)); } + @Override public void addAttribute(String name, double value) throws PaintException { tag.addAttribute("\"" + name + "\":" + String.valueOf(value)); } + @Override public void addAttribute(String name, String value) throws PaintException { // In case of null data output nothing: if ((value == null) || (name == null)) { @@ -400,12 +407,14 @@ public class JsonPaintTarget implements PaintTarget { } + @Override public void addAttribute(String name, Component value) throws PaintException { final String id = value.getConnectorId(); addAttribute(name, id); } + @Override public void addAttribute(String name, Map<?, ?> value) throws PaintException { @@ -443,6 +452,7 @@ public class JsonPaintTarget implements PaintTarget { tag.addAttribute(sb.toString()); } + @Override public void addAttribute(String name, Object[] values) { // In case of null data output nothing: if ((values == null) || (name == null)) { @@ -463,41 +473,49 @@ public class JsonPaintTarget implements PaintTarget { tag.addAttribute(buf.toString()); } + @Override public void addVariable(VariableOwner owner, String name, String value) throws PaintException { tag.addVariable(new StringVariable(owner, name, escapeJSON(value))); } - public void addVariable(VariableOwner owner, String name, - Component value) throws PaintException { + @Override + public void addVariable(VariableOwner owner, String name, Component value) + throws PaintException { tag.addVariable(new StringVariable(owner, name, value.getConnectorId())); } + @Override public void addVariable(VariableOwner owner, String name, int value) throws PaintException { tag.addVariable(new IntVariable(owner, name, value)); } + @Override public void addVariable(VariableOwner owner, String name, long value) throws PaintException { tag.addVariable(new LongVariable(owner, name, value)); } + @Override public void addVariable(VariableOwner owner, String name, float value) throws PaintException { tag.addVariable(new FloatVariable(owner, name, value)); } + @Override public void addVariable(VariableOwner owner, String name, double value) throws PaintException { tag.addVariable(new DoubleVariable(owner, name, value)); } + @Override public void addVariable(VariableOwner owner, String name, boolean value) throws PaintException { tag.addVariable(new BooleanVariable(owner, name, value)); } + @Override public void addVariable(VariableOwner owner, String name, String[] value) throws PaintException { tag.addVariable(new ArrayVariable(owner, name, value)); @@ -516,6 +534,7 @@ public class JsonPaintTarget implements PaintTarget { * @throws PaintException * if the paint operation failed. */ + @Override public void addUploadStreamVariable(VariableOwner owner, String name) throws PaintException { startTag("uploadstream"); @@ -535,6 +554,7 @@ public class JsonPaintTarget implements PaintTarget { * @throws PaintException * if the paint operation failed. */ + @Override public void addSection(String sectionTagName, String sectionData) throws PaintException { tag.addData("{\"" + sectionTagName + "\":\"" + escapeJSON(sectionData) @@ -549,6 +569,7 @@ public class JsonPaintTarget implements PaintTarget { * @throws PaintException * if the paint operation failed. */ + @Override public void addUIDL(String xml) throws PaintException { // Ensure that the target is open @@ -582,6 +603,7 @@ public class JsonPaintTarget implements PaintTarget { * @see com.vaadin.terminal.PaintTarget#addXMLSection(String, String, * String) */ + @Override public void addXMLSection(String sectionTagName, String sectionData, String namespace) throws PaintException { @@ -646,12 +668,14 @@ public class JsonPaintTarget implements PaintTarget { * @see com.vaadin.terminal.PaintTarget#startPaintable(com.vaadin.terminal * .Paintable, java.lang.String) */ + @Override 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); @@ -671,9 +695,11 @@ public class JsonPaintTarget implements PaintTarget { return PaintStatus.PAINTING; } + @Override 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 +718,7 @@ public class JsonPaintTarget implements PaintTarget { * * @see com.vaadin.terminal.PaintTarget#addCharacterData(java.lang.String ) */ + @Override public void addCharacterData(String text) throws PaintException { if (text != null) { tag.addData(text); @@ -961,6 +988,7 @@ public class JsonPaintTarget implements PaintTarget { return usedResources; } + @Override @SuppressWarnings("unchecked") public String getTag(ClientConnector clientConnector) { Class<? extends ClientConnector> clientConnectorClass = clientConnector @@ -983,6 +1011,7 @@ public class JsonPaintTarget implements PaintTarget { return usedClientConnectors; } + @Override public void addVariable(VariableOwner owner, String name, StreamVariable value) throws PaintException { String url = manager.getStreamVariableTargetUrl((Connector) owner, @@ -998,8 +1027,13 @@ public class JsonPaintTarget implements PaintTarget { * * @see com.vaadin.terminal.PaintTarget#isFullRepaint() */ + @Override 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..b87fea4233 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. */ + @Override public String getDefaultTheme() { return null; } @@ -52,6 +51,7 @@ public class WebBrowser implements Terminal { * * @see com.vaadin.terminal.Terminal#getScreenHeight() */ + @Override public int getScreenHeight() { return screenHeight; } @@ -61,35 +61,12 @@ public class WebBrowser implements Terminal { * * @see com.vaadin.terminal.Terminal#getScreenWidth() */ + @Override 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/ClassPathExplorer.java b/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java index 6a0aa0f4c2..ced92d519b 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java @@ -31,7 +31,6 @@ 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. @@ -53,15 +52,13 @@ 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"; /** * File filter that only accepts directories. */ private final static FileFilter DIRECTORIES_ONLY = new FileFilter() { + @Override public boolean accept(File f) { if (f.exists() && f.isDirectory()) { return true; @@ -98,10 +95,9 @@ public class ClassPathExplorer { * * 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() { + final Logger logger = getLogger(); logger.info("Searching for accept criteria.."); long start = System.currentTimeMillis(); Set<String> keySet = classpathLocations.keySet(); @@ -154,6 +150,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 +211,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 +247,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 +275,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 +309,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 +350,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 +361,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; @@ -510,7 +510,7 @@ public class ClassPathExplorer { } } } catch (IOException e) { - logger.warning(e.toString()); + getLogger().warning(e.toString()); } } @@ -582,7 +582,8 @@ public class ClassPathExplorer { // Must be done here after stderr and stdout have been reset. if (errorToShow != null && logLevel != null) { - logger.log(logLevel, + getLogger().log( + logLevel, "Failed to load class " + fullclassName + ". " + errorToShow.getClass().getName() + ": " + errorToShow.getMessage()); @@ -601,6 +602,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>( @@ -656,20 +660,24 @@ public class ClassPathExplorer { */ public static void main(String[] args) { ClassPathExplorer.findAcceptCriteria(); - logger.info("Found client criteria:"); + getLogger().info("Found client criteria:"); for (Class<? extends AcceptCriterion> cls : acceptCriterion) { - logger.info(cls.getCanonicalName()); + getLogger().info(cls.getCanonicalName()); } - logger.info(""); - logger.info("Searching available widgetsets..."); + getLogger().info(""); + 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/AbstractSplitPanel.java b/src/com/vaadin/ui/AbstractSplitPanel.java index 5205952621..6a7099ba9d 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,17 +31,22 @@ 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 = Unit.PERCENTAGE; + private Unit posMaxUnit = Unit.PERCENTAGE; private AbstractSplitPanelRpc rpc = new AbstractSplitPanelRpc() { + @Override public void splitterClick(MouseEventDetails mouseDetails) { fireEvent(new SplitterClickEvent(AbstractSplitPanel.this, mouseDetails)); } + @Override public void setSplitterPosition(float position) { - getState().getSplitterState().setPosition(position); + getSplitterState().setPosition(position); } }; @@ -59,6 +64,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { int i = 0; + @Override public boolean hasNext() { if (i < getComponentCount()) { return true; @@ -66,6 +72,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { return false; } + @Override public Component next() { if (!hasNext()) { return null; @@ -80,6 +87,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { return null; } + @Override public void remove() { if (i == 1) { if (getFirstComponent() != null) { @@ -204,6 +212,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { * * @see com.vaadin.ui.ComponentContainer#getComponentIterator() */ + @Override public Iterator<Component> getComponentIterator() { return new ComponentIterator(); } @@ -214,6 +223,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { * * @return the number of contained components (zero, one or two) */ + @Override public int getComponentCount() { int count = 0; if (getFirstComponent() != null) { @@ -226,6 +236,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { } /* Documented in superclass */ + @Override public void replaceComponent(Component oldComponent, Component newComponent) { if (oldComponent == getFirstComponent()) { setFirstComponent(newComponent); @@ -297,7 +308,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 +324,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { * @return position of the splitter */ public float getSplitPosition() { - return getState().getSplitterState().getPosition(); + return getSplitterState().getPosition(); } /** @@ -326,6 +337,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); + posMinUnit = minPosUnit; + + state.setMaxPosition(maxPos); + state.setMaxPositionUnit("" + maxPosUnit); + posMaxUnit = maxPosUnit; + + requestRepaint(); + } + + /** * Lock the SplitPanels position, disabling the user from dragging the split * handle. * @@ -333,7 +448,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 +459,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 +509,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..9551cbaaab 100644 --- a/src/com/vaadin/ui/Button.java +++ b/src/com/vaadin/ui/Button.java @@ -38,10 +38,12 @@ public class Button extends AbstractComponent implements Action.ShortcutNotifier { private ButtonServerRpc rpc = new ButtonServerRpc() { + @Override public void click(MouseEventDetails mouseEventDetails) { fireClick(mouseEventDetails); } + @Override public void disableOnClick() { // Could be optimized so the button is not repainted because of // this (client side has already disabled the button) @@ -330,20 +332,24 @@ public class Button extends AbstractComponent implements fireEvent(new Button.ClickEvent(this, details)); } + @Override public void addListener(BlurListener listener) { addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, BlurListener.blurMethod); } + @Override public void removeListener(BlurListener listener) { removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); } + @Override public void addListener(FocusListener listener) { addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, FocusListener.focusMethod); } + @Override public void removeListener(FocusListener listener) { removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); @@ -469,10 +475,12 @@ public class Button extends AbstractComponent implements requestRepaint(); } + @Override public int getTabIndex() { return tabIndex; } + @Override public void setTabIndex(int tabIndex) { this.tabIndex = tabIndex; diff --git a/src/com/vaadin/ui/TabSheet.java b/src/com/vaadin/ui/TabSheet.java index 23dee15359..7aef4a2b2a 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() { + @Override 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 */ + @Override 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 */ + @Override public int getComponentCount() { return components.size(); } @@ -359,6 +362,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, * @throws PaintException * if the paint operation failed. */ + @Override public void paintContent(PaintTarget target) throws PaintException { if (areTabsHidden()) { @@ -683,6 +687,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, } // inherits javadoc + @Override public void changeVariables(Object source, Map<String, Object> variables) { if (variables.containsKey("selected")) { setSelectedTab(keyMapper.get((String) variables.get("selected"))); @@ -719,6 +724,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, * * {@inheritDoc} */ + @Override public void replaceComponent(Component oldComponent, Component newComponent) { if (selected == oldComponent) { @@ -729,25 +735,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 +756,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,28 +1079,34 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, /** * Returns the tab caption. Can never be null. */ + @Override public String getCaption() { return caption; } + @Override public void setCaption(String caption) { this.caption = caption; requestRepaint(); } + @Override public Resource getIcon() { return icon; } + @Override public void setIcon(Resource icon) { this.icon = icon; requestRepaint(); } + @Override public boolean isEnabled() { return enabled; } + @Override public void setEnabled(boolean enabled) { this.enabled = enabled; if (updateSelection()) { @@ -1136,10 +1115,12 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, requestRepaint(); } + @Override public boolean isVisible() { return visible; } + @Override public void setVisible(boolean visible) { this.visible = visible; if (updateSelection()) { @@ -1148,10 +1129,12 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, requestRepaint(); } + @Override public boolean isClosable() { return closable; } + @Override public void setClosable(boolean closable) { this.closable = closable; requestRepaint(); @@ -1161,24 +1144,29 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, } + @Override public String getDescription() { return description; } + @Override public void setDescription(String description) { this.description = description; requestRepaint(); } + @Override public ErrorMessage getComponentError() { return componentError; } + @Override public void setComponentError(ErrorMessage componentError) { this.componentError = componentError; requestRepaint(); } + @Override public Component getComponent() { for (Map.Entry<Component, Tab> entry : tabs.entrySet()) { if (entry.getValue() == this) { @@ -1188,11 +1176,13 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, return null; } + @Override public void setStyleName(String styleName) { this.styleName = styleName; requestRepaint(); } + @Override public String getStyleName() { return styleName; } @@ -1268,29 +1258,35 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, super.focus(); } + @Override public int getTabIndex() { return tabIndex; } + @Override public void setTabIndex(int tabIndex) { this.tabIndex = tabIndex; requestRepaint(); } + @Override public void addListener(BlurListener listener) { addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, BlurListener.blurMethod); } + @Override public void removeListener(BlurListener listener) { removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); } + @Override public void addListener(FocusListener listener) { addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, FocusListener.focusMethod); } + @Override public void removeListener(FocusListener listener) { removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); @@ -1300,4 +1296,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..a83c9bd87a 100644 --- a/src/com/vaadin/ui/Table.java +++ b/src/com/vaadin/ui/Table.java @@ -78,8 +78,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 +330,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 +356,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 +1253,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 +1295,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 +1612,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) { @@ -1714,8 +1764,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 +1869,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 +1893,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 +2077,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 +2110,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 +2192,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 @@ -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; @@ -2884,8 +2943,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 +2968,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 +3169,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 +3684,7 @@ public class Table extends AbstractSelect implements Action.Container, * * @see com.vaadin.event.Action.Container#addActionHandler(Action.Handler) */ + @Override public void addActionHandler(Action.Handler actionHandler) { if (actionHandler != null) { @@ -3639,6 +3711,7 @@ public class Table extends AbstractSelect implements Action.Container, * * @see com.vaadin.event.Action.Container#removeActionHandler(Action.Handler) */ + @Override public void removeActionHandler(Action.Handler actionHandler) { if (actionHandlers != null && actionHandlers.contains(actionHandler)) { @@ -4036,6 +4109,7 @@ public class Table extends AbstractSelect implements Action.Container, * * @see com.vaadin.data.Container.Ordered#nextItemId(java.lang.Object) */ + @Override public Object nextItemId(Object itemId) { return ((Container.Ordered) items).nextItemId(itemId); } @@ -4046,6 +4120,7 @@ public class Table extends AbstractSelect implements Action.Container, * * @see com.vaadin.data.Container.Ordered#prevItemId(java.lang.Object) */ + @Override public Object prevItemId(Object itemId) { return ((Container.Ordered) items).prevItemId(itemId); } @@ -4055,6 +4130,7 @@ public class Table extends AbstractSelect implements Action.Container, * * @see com.vaadin.data.Container.Ordered#firstItemId() */ + @Override public Object firstItemId() { return ((Container.Ordered) items).firstItemId(); } @@ -4064,6 +4140,7 @@ public class Table extends AbstractSelect implements Action.Container, * * @see com.vaadin.data.Container.Ordered#lastItemId() */ + @Override public Object lastItemId() { return ((Container.Ordered) items).lastItemId(); } @@ -4074,6 +4151,7 @@ public class Table extends AbstractSelect implements Action.Container, * * @see com.vaadin.data.Container.Ordered#isFirstId(java.lang.Object) */ + @Override public boolean isFirstId(Object itemId) { return ((Container.Ordered) items).isFirstId(itemId); } @@ -4084,6 +4162,7 @@ public class Table extends AbstractSelect implements Action.Container, * * @see com.vaadin.data.Container.Ordered#isLastId(java.lang.Object) */ + @Override public boolean isLastId(Object itemId) { return ((Container.Ordered) items).isLastId(itemId); } @@ -4093,6 +4172,7 @@ public class Table extends AbstractSelect implements Action.Container, * * @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object) */ + @Override public Object addItemAfter(Object previousItemId) throws UnsupportedOperationException { Object itemId = ((Container.Ordered) items) @@ -4109,6 +4189,7 @@ public class Table extends AbstractSelect implements Action.Container, * @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object, * java.lang.Object) */ + @Override public Item addItemAfter(Object previousItemId, Object newItemId) throws UnsupportedOperationException { Item item = ((Container.Ordered) items).addItemAfter(previousItemId, @@ -4201,6 +4282,7 @@ public class Table extends AbstractSelect implements Action.Container, * boolean[]) * */ + @Override public void sort(Object[] propertyId, boolean[] ascending) throws UnsupportedOperationException { final Container c = getContainerDataSource(); @@ -4236,6 +4318,7 @@ public class Table extends AbstractSelect implements Action.Container, * * @see com.vaadin.data.Container.Sortable#getSortableContainerPropertyIds() */ + @Override public Collection<?> getSortableContainerPropertyIds() { final Container c = getContainerDataSource(); if (c instanceof Container.Sortable && !isSortDisabled()) { @@ -4425,11 +4508,13 @@ public class Table extends AbstractSelect implements Action.Container, public abstract String getStyle(Object itemId, Object propertyId); } + @Override public void addListener(ItemClickListener listener) { addListener(VScrollTable.ITEM_CLICK_EVENT_ID, ItemClickEvent.class, listener, ItemClickEvent.ITEM_CLICK_METHOD); } + @Override public void removeListener(ItemClickListener listener) { removeListener(VScrollTable.ITEM_CLICK_EVENT_ID, ItemClickEvent.class, listener); @@ -4505,11 +4590,13 @@ public class Table extends AbstractSelect implements Action.Container, } + @Override public TableTransferable getTransferable(Map<String, Object> rawVariables) { TableTransferable transferable = new TableTransferable(rawVariables); return transferable; } + @Override public DropHandler getDropHandler() { return dropHandler; } @@ -4518,6 +4605,7 @@ public class Table extends AbstractSelect implements Action.Container, this.dropHandler = dropHandler; } + @Override public AbstractSelectTargetDetails translateDropTargetDetails( Map<String, Object> clientVariables) { return new AbstractSelectTargetDetails(clientVariables); @@ -4586,6 +4674,7 @@ public class Table extends AbstractSelect implements Action.Container, * com.vaadin.event.dd.acceptcriteria.AcceptCriterion#accepts(com.vaadin * .event.dd.DragAndDropEvent) */ + @Override @SuppressWarnings("unchecked") public boolean accept(DragAndDropEvent dragEvent) { AbstractSelectTargetDetails dropTargetData = (AbstractSelectTargetDetails) dragEvent @@ -5260,10 +5349,12 @@ public class Table extends AbstractSelect implements Action.Container, super.setVisible(visible); } + @Override public Iterator<Component> iterator() { return getComponentIterator(); } + @Override public Iterator<Component> getComponentIterator() { if (visibleComponents == null) { Collection<Component> empty = Collections.emptyList(); @@ -5273,7 +5364,15 @@ public class Table extends AbstractSelect implements Action.Container, return visibleComponents.iterator(); } + @Override public boolean isComponentVisible(Component childComponent) { return true; } + + private final Logger getLogger() { + if (logger == null) { + logger = Logger.getLogger(Table.class.getName()); + } + return logger; + } } diff --git a/src/com/vaadin/ui/TreeTable.java b/src/com/vaadin/ui/TreeTable.java index 9607add2c9..6c832d37fe 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. */ + @Override public int getDepth(Object itemId) { int depth = 0; Hierarchical hierarchicalContainer = getContainerDataSource(); @@ -94,6 +92,7 @@ public class TreeTable extends Table implements Hierarchical { return depth; } + @Override public void containerItemSetChange(ItemSetChangeEvent event) { } @@ -112,44 +111,54 @@ public class TreeTable extends Table implements Hierarchical { return (Collapsible) getContainerDataSource(); } + @Override public void toggleChildVisibility(Object itemId) { c().setCollapsed(itemId, !c().isCollapsed(itemId)); } + @Override public boolean isNodeOpen(Object itemId) { return !c().isCollapsed(itemId); } + @Override public int size() { return TreeTable.super.size(); } + @Override public Object getIdByIndex(int index) { return TreeTable.super.getIdByIndex(index); } + @Override public int indexOfId(Object id) { return TreeTable.super.indexOfId(id); } + @Override public boolean isLastId(Object itemId) { // using the default impl return TreeTable.super.isLastId(itemId); } + @Override public Object lastItemId() { // using the default impl return TreeTable.super.lastItemId(); } + @Override public Object nextItemId(Object itemId) { return TreeTable.super.nextItemId(itemId); } + @Override public Object prevItemId(Object itemId) { return TreeTable.super.prevItemId(itemId); } + @Override public Collection<?> getItemIds() { return TreeTable.super.getItemIds(); } @@ -167,18 +176,22 @@ public class TreeTable extends Table implements Hierarchical { private final HashSet<Object> openItems = new HashSet<Object>(); + @Override public boolean isNodeOpen(Object itemId) { return openItems.contains(itemId); } + @Override public int size() { return getPreOrder().size(); } + @Override public Collection<Object> getItemIds() { return Collections.unmodifiableCollection(getPreOrder()); } + @Override public boolean isLastId(Object itemId) { if (itemId == null) { return false; @@ -187,6 +200,7 @@ public class TreeTable extends Table implements Hierarchical { return itemId.equals(lastItemId()); } + @Override public Object lastItemId() { if (getPreOrder().size() > 0) { return getPreOrder().get(getPreOrder().size() - 1); @@ -195,6 +209,7 @@ public class TreeTable extends Table implements Hierarchical { } } + @Override public Object nextItemId(Object itemId) { int indexOf = getPreOrder().indexOf(itemId); if (indexOf == -1) { @@ -208,6 +223,7 @@ public class TreeTable extends Table implements Hierarchical { } } + @Override public Object prevItemId(Object itemId) { int indexOf = getPreOrder().indexOf(itemId); indexOf--; @@ -218,13 +234,14 @@ public class TreeTable extends Table implements Hierarchical { } } + @Override public void toggleChildVisibility(Object itemId) { 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(); } @@ -267,10 +284,12 @@ public class TreeTable extends Table implements Hierarchical { } + @Override public int indexOfId(Object id) { return getPreOrder().indexOf(id); } + @Override public Object getIdByIndex(int index) { return getPreOrder().get(index); } @@ -612,36 +631,44 @@ public class TreeTable extends Table implements Hierarchical { return getContainerStrategy().getItemIds(); } + @Override public boolean areChildrenAllowed(Object itemId) { return getContainerDataSource().areChildrenAllowed(itemId); } + @Override public Collection<?> getChildren(Object itemId) { return getContainerDataSource().getChildren(itemId); } + @Override public Object getParent(Object itemId) { return getContainerDataSource().getParent(itemId); } + @Override public boolean hasChildren(Object itemId) { return getContainerDataSource().hasChildren(itemId); } + @Override public boolean isRoot(Object itemId) { return getContainerDataSource().isRoot(itemId); } + @Override public Collection<?> rootItemIds() { return getContainerDataSource().rootItemIds(); } + @Override public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) throws UnsupportedOperationException { return getContainerDataSource().setChildrenAllowed(itemId, areChildrenAllowed); } + @Override public boolean setParent(Object itemId, Object newParentId) throws UnsupportedOperationException { return getContainerDataSource().setParent(itemId, newParentId); @@ -789,4 +816,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..889afb7e93 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; @@ -78,11 +79,16 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, private WindowServerRpc rpc = new WindowServerRpc() { + @Override public void click(MouseEventDetails mouseDetails) { fireEvent(new ClickEvent(Window.this, mouseDetails)); } }; + private int browserWindowWidth = -1; + + private int browserWindowHeight = -1; + /** * Creates a new unnamed window with a default layout. */ @@ -161,15 +167,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); @@ -788,11 +808,13 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, * * @see com.vaadin.event.FieldEvents.FocusNotifier#addListener(com.vaadin.event.FieldEvents.FocusListener) */ + @Override public void addListener(FocusListener listener) { addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, FocusListener.focusMethod); } + @Override public void removeListener(FocusListener listener) { removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); } @@ -804,11 +826,13 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, * * @see com.vaadin.event.FieldEvents.BlurNotifier#addListener(com.vaadin.event.FieldEvents.BlurListener) */ + @Override public void addListener(BlurListener listener) { addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, BlurListener.blurMethod); } + @Override public void removeListener(BlurListener listener) { removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); } @@ -835,4 +859,35 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, return (WindowState) super.getState(); } + /** + * Gets the height of the viewport area of the browser window where this + * window is displayed. + * + * @return the browser viewport height in pixels + */ + public int getBrowserWindowHeight() { + // Size only reported by VView -> data only available from application + // level window + if (getParent() != null) { + return ((Root) getParent()).getBrowserWindowHeight(); + } + + return browserWindowHeight; + } + + /** + * Gets the width of the viewport area of the browser window where this + * window is displayed. + * + * @return the browser viewport width in pixels + */ + public int getBrowserWindowWidth() { + // Size only reported by VView -> data only available from application + // level window + if (getParent() != null) { + return ((Root) getParent()).getBrowserWindowWidth(); + } + + return browserWindowWidth; + } } |