summaryrefslogtreecommitdiffstats
path: root/shared
diff options
context:
space:
mode:
Diffstat (limited to 'shared')
-rw-r--r--shared/src/com/vaadin/shared/AbstractComponentState.java3
-rw-r--r--shared/src/com/vaadin/shared/annotations/NoLayout.java43
-rw-r--r--shared/src/com/vaadin/shared/communication/SharedState.java2
-rw-r--r--shared/src/com/vaadin/shared/data/DataProviderRpc.java92
-rw-r--r--shared/src/com/vaadin/shared/data/DataRequestRpc.java57
-rw-r--r--shared/src/com/vaadin/shared/data/sort/SortDirection.java54
-rw-r--r--shared/src/com/vaadin/shared/ui/AbstractEmbeddedState.java2
-rw-r--r--shared/src/com/vaadin/shared/ui/AbstractMediaState.java4
-rw-r--r--shared/src/com/vaadin/shared/ui/MediaControl.java3
-rw-r--r--shared/src/com/vaadin/shared/ui/TabIndexState.java2
-rw-r--r--shared/src/com/vaadin/shared/ui/button/ButtonState.java4
-rw-r--r--shared/src/com/vaadin/shared/ui/datefield/PopupDateFieldState.java3
-rw-r--r--shared/src/com/vaadin/shared/ui/datefield/TextualDateFieldState.java3
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/ColumnGroupState.java45
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/EditorClientRpc.java55
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/EditorServerRpc.java58
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/GridClientRpc.java53
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/GridColumnState.java79
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/GridConstants.java44
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/GridServerRpc.java36
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/GridState.java149
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/GridStaticCellType.java39
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java68
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/HeightMode.java42
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/Range.java431
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/ScrollDestination.java55
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/renderers/RendererClickRpc.java31
-rw-r--r--shared/src/com/vaadin/shared/ui/panel/PanelState.java3
-rw-r--r--shared/src/com/vaadin/shared/ui/popupview/PopupViewState.java2
-rw-r--r--shared/src/com/vaadin/shared/ui/progressindicator/ProgressBarState.java2
-rw-r--r--shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorState.java3
-rw-r--r--shared/src/com/vaadin/shared/ui/slider/SliderState.java5
-rw-r--r--shared/src/com/vaadin/shared/ui/tabsheet/TabsheetState.java2
-rw-r--r--shared/src/com/vaadin/shared/ui/textarea/TextAreaState.java2
-rw-r--r--shared/src/com/vaadin/shared/ui/textfield/AbstractTextFieldState.java4
-rw-r--r--shared/src/com/vaadin/shared/ui/ui/ScrollClientRpc.java3
-rw-r--r--shared/src/com/vaadin/shared/ui/window/WindowState.java15
-rw-r--r--shared/src/com/vaadin/shared/util/SharedUtil.java136
-rw-r--r--shared/tests/src/com/vaadin/shared/ui/grid/RangeTest.java406
-rw-r--r--shared/tests/src/com/vaadin/shared/util/SharedUtilTests.java66
40 files changed, 2091 insertions, 15 deletions
diff --git a/shared/src/com/vaadin/shared/AbstractComponentState.java b/shared/src/com/vaadin/shared/AbstractComponentState.java
index 9e21954f3e..1c32a67c70 100644
--- a/shared/src/com/vaadin/shared/AbstractComponentState.java
+++ b/shared/src/com/vaadin/shared/AbstractComponentState.java
@@ -18,6 +18,7 @@ package com.vaadin.shared;
import java.util.List;
+import com.vaadin.shared.annotations.NoLayout;
import com.vaadin.shared.communication.SharedState;
/**
@@ -31,7 +32,9 @@ public class AbstractComponentState extends SharedState {
public String height = "";
public String width = "";
public boolean readOnly = false;
+ @NoLayout
public boolean immediate = false;
+ @NoLayout
public String description = "";
// Note: for the caption, there is a difference between null and an empty
// string!
diff --git a/shared/src/com/vaadin/shared/annotations/NoLayout.java b/shared/src/com/vaadin/shared/annotations/NoLayout.java
new file mode 100644
index 0000000000..78ff1e2984
--- /dev/null
+++ b/shared/src/com/vaadin/shared/annotations/NoLayout.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation used to mark client RPC methods, state fields, or state setter
+ * methods that should not trigger an layout phase after changes have been
+ * processed. Whenever there's at least one change that is not marked with this
+ * annotation, the framework will assume some sizes might have changed an will
+ * therefore start a layout phase after applying the changes.
+ * <p>
+ * This annotation can be used for any RPC method or state property that does
+ * not cause the size of the component or its children to change. Please note
+ * that almost anything related to CSS (e.g. adding or removing a stylename) has
+ * the potential of causing sizes to change with appropriate style definitions
+ * in the application theme.
+ *
+ * @since
+ *
+ * @author Vaadin Ltd
+ */
+@Documented
+@Target({ ElementType.METHOD, ElementType.FIELD })
+public @interface NoLayout {
+ // Just an empty marker annotation
+}
diff --git a/shared/src/com/vaadin/shared/communication/SharedState.java b/shared/src/com/vaadin/shared/communication/SharedState.java
index e16fc51fae..b21a675a4a 100644
--- a/shared/src/com/vaadin/shared/communication/SharedState.java
+++ b/shared/src/com/vaadin/shared/communication/SharedState.java
@@ -22,6 +22,7 @@ import java.util.Map;
import java.util.Set;
import com.vaadin.shared.Connector;
+import com.vaadin.shared.annotations.NoLayout;
/**
* Interface to be implemented by all shared state classes used to communicate
@@ -64,6 +65,7 @@ public class SharedState implements Serializable {
/**
* A set of event identifiers with registered listeners.
*/
+ @NoLayout
public Set<String> registeredEventListeners = null;
}
diff --git a/shared/src/com/vaadin/shared/data/DataProviderRpc.java b/shared/src/com/vaadin/shared/data/DataProviderRpc.java
new file mode 100644
index 0000000000..3e5dd9a332
--- /dev/null
+++ b/shared/src/com/vaadin/shared/data/DataProviderRpc.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.shared.data;
+
+import com.vaadin.shared.annotations.NoLayout;
+import com.vaadin.shared.communication.ClientRpc;
+
+/**
+ * RPC interface used for pushing container data to the client.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public interface DataProviderRpc extends ClientRpc {
+
+ /**
+ * Sends updated row data to a client.
+ * <p>
+ * rowDataJson represents a JSON array of JSON objects in the following
+ * format:
+ *
+ * <pre>
+ * [{
+ * "d": [COL_1_JSON, COL_2_json, ...],
+ * "k": "1"
+ * },
+ * ...
+ * ]
+ * </pre>
+ *
+ * where COL_INDEX is the index of the column (as a string), and COL_n_JSON
+ * is valid JSON of the column's data.
+ *
+ * @param firstRowIndex
+ * the index of the first updated row
+ * @param rowDataJson
+ * the updated row data
+ * @see com.vaadin.shared.ui.grid.GridState#JSONKEY_DATA
+ * @see com.vaadin.ui.components.grid.Renderer#encode(Object)
+ */
+ @NoLayout
+ public void setRowData(int firstRowIndex, String rowDataJson);
+
+ /**
+ * Informs the client to remove row data.
+ *
+ * @param firstRowIndex
+ * the index of the first removed row
+ * @param count
+ * the number of rows removed from <code>firstRowIndex</code> and
+ * onwards
+ */
+ @NoLayout
+ public void removeRowData(int firstRowIndex, int count);
+
+ /**
+ * Informs the client to insert new row data.
+ *
+ * @param firstRowIndex
+ * the index of the first new row
+ * @param count
+ * the number of rows inserted at <code>firstRowIndex</code>
+ */
+ @NoLayout
+ public void insertRowData(int firstRowIndex, int count);
+
+ /**
+ * Resets all data and defines a new size for the data.
+ * <p>
+ * This should be used in the cases where the data has changed in some
+ * unverifiable way. I.e. "something happened". This will lead to a
+ * re-rendering of the current Grid viewport
+ *
+ * @param size
+ * the size of the new data set
+ */
+ public void resetDataAndSize(int size);
+}
diff --git a/shared/src/com/vaadin/shared/data/DataRequestRpc.java b/shared/src/com/vaadin/shared/data/DataRequestRpc.java
new file mode 100644
index 0000000000..637a353447
--- /dev/null
+++ b/shared/src/com/vaadin/shared/data/DataRequestRpc.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.shared.data;
+
+import com.vaadin.shared.annotations.Delayed;
+import com.vaadin.shared.communication.ServerRpc;
+
+/**
+ * RPC interface used for requesting container data to the client.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public interface DataRequestRpc extends ServerRpc {
+
+ /**
+ * Request rows from the server.
+ *
+ * @param firstRowIndex
+ * the index of the first requested row
+ * @param numberOfRows
+ * the number of requested rows
+ * @param firstCachedRowIndex
+ * the index of the first cached row
+ * @param cacheSize
+ * the number of cached rows
+ */
+ public void requestRows(int firstRowIndex, int numberOfRows,
+ int firstCachedRowIndex, int cacheSize);
+
+ /**
+ * Informs the server that an item referenced with a key pinned status has
+ * changed. This is a delayed call that happens along with next rpc call to
+ * server.
+ *
+ * @param key
+ * key mapping to item
+ * @param isPinned
+ * pinned status of referenced item
+ */
+ @Delayed
+ public void setPinned(String key, boolean isPinned);
+}
diff --git a/shared/src/com/vaadin/shared/data/sort/SortDirection.java b/shared/src/com/vaadin/shared/data/sort/SortDirection.java
new file mode 100644
index 0000000000..043b363226
--- /dev/null
+++ b/shared/src/com/vaadin/shared/data/sort/SortDirection.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.data.sort;
+
+import java.io.Serializable;
+
+/**
+ * Describes sorting direction.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public enum SortDirection implements Serializable {
+
+ /**
+ * Ascending (e.g. A-Z, 1..9) sort order
+ */
+ ASCENDING {
+ @Override
+ public SortDirection getOpposite() {
+ return DESCENDING;
+ }
+ },
+
+ /**
+ * Descending (e.g. Z-A, 9..1) sort order
+ */
+ DESCENDING {
+ @Override
+ public SortDirection getOpposite() {
+ return ASCENDING;
+ }
+ };
+
+ /**
+ * Get the sort direction that is the direct opposite to this one.
+ *
+ * @return a sort direction value
+ */
+ public abstract SortDirection getOpposite();
+}
diff --git a/shared/src/com/vaadin/shared/ui/AbstractEmbeddedState.java b/shared/src/com/vaadin/shared/ui/AbstractEmbeddedState.java
index f5779de43d..0cb9be8702 100644
--- a/shared/src/com/vaadin/shared/ui/AbstractEmbeddedState.java
+++ b/shared/src/com/vaadin/shared/ui/AbstractEmbeddedState.java
@@ -16,10 +16,12 @@
package com.vaadin.shared.ui;
import com.vaadin.shared.AbstractComponentState;
+import com.vaadin.shared.annotations.NoLayout;
public class AbstractEmbeddedState extends AbstractComponentState {
public static final String SOURCE_RESOURCE = "source";
+ @NoLayout
public String alternateText;
}
diff --git a/shared/src/com/vaadin/shared/ui/AbstractMediaState.java b/shared/src/com/vaadin/shared/ui/AbstractMediaState.java
index d2ef09810b..3029bedca7 100644
--- a/shared/src/com/vaadin/shared/ui/AbstractMediaState.java
+++ b/shared/src/com/vaadin/shared/ui/AbstractMediaState.java
@@ -19,17 +19,21 @@ import java.util.ArrayList;
import java.util.List;
import com.vaadin.shared.AbstractComponentState;
+import com.vaadin.shared.annotations.NoLayout;
import com.vaadin.shared.communication.URLReference;
public class AbstractMediaState extends AbstractComponentState {
public boolean showControls;
+ @NoLayout
public String altText;
public boolean htmlContentAllowed;
+ @NoLayout
public boolean autoplay;
+ @NoLayout
public boolean muted;
public List<URLReference> sources = new ArrayList<URLReference>();
diff --git a/shared/src/com/vaadin/shared/ui/MediaControl.java b/shared/src/com/vaadin/shared/ui/MediaControl.java
index 2311d57b16..ab31d6f95f 100644
--- a/shared/src/com/vaadin/shared/ui/MediaControl.java
+++ b/shared/src/com/vaadin/shared/ui/MediaControl.java
@@ -16,6 +16,7 @@
package com.vaadin.shared.ui;
+import com.vaadin.shared.annotations.NoLayout;
import com.vaadin.shared.communication.ClientRpc;
/**
@@ -27,10 +28,12 @@ public interface MediaControl extends ClientRpc {
/**
* Start playing the media.
*/
+ @NoLayout
public void play();
/**
* Pause playback of the media.
*/
+ @NoLayout
public void pause();
}
diff --git a/shared/src/com/vaadin/shared/ui/TabIndexState.java b/shared/src/com/vaadin/shared/ui/TabIndexState.java
index eec61a0595..1afe982546 100644
--- a/shared/src/com/vaadin/shared/ui/TabIndexState.java
+++ b/shared/src/com/vaadin/shared/ui/TabIndexState.java
@@ -16,6 +16,7 @@
package com.vaadin.shared.ui;
import com.vaadin.shared.AbstractComponentState;
+import com.vaadin.shared.annotations.NoLayout;
/**
* Interface implemented by state classes that support tab indexes.
@@ -29,6 +30,7 @@ public class TabIndexState extends AbstractComponentState {
/**
* The <i>tabulator index</i> of the field.
*/
+ @NoLayout
public int tabIndex = 0;
}
diff --git a/shared/src/com/vaadin/shared/ui/button/ButtonState.java b/shared/src/com/vaadin/shared/ui/button/ButtonState.java
index 5b099572df..01ef9a038b 100644
--- a/shared/src/com/vaadin/shared/ui/button/ButtonState.java
+++ b/shared/src/com/vaadin/shared/ui/button/ButtonState.java
@@ -17,6 +17,7 @@
package com.vaadin.shared.ui.button;
import com.vaadin.shared.AbstractComponentState;
+import com.vaadin.shared.annotations.NoLayout;
import com.vaadin.shared.ui.TabIndexState;
/**
@@ -31,7 +32,10 @@ public class ButtonState extends TabIndexState {
{
primaryStyleName = "v-button";
}
+ @NoLayout
public boolean disableOnClick = false;
+ @NoLayout
public int clickShortcutKeyCode = 0;
+ @NoLayout
public String iconAltText = "";
}
diff --git a/shared/src/com/vaadin/shared/ui/datefield/PopupDateFieldState.java b/shared/src/com/vaadin/shared/ui/datefield/PopupDateFieldState.java
index 07726f8af0..6f10af4314 100644
--- a/shared/src/com/vaadin/shared/ui/datefield/PopupDateFieldState.java
+++ b/shared/src/com/vaadin/shared/ui/datefield/PopupDateFieldState.java
@@ -15,6 +15,8 @@
*/
package com.vaadin.shared.ui.datefield;
+import com.vaadin.shared.annotations.NoLayout;
+
public class PopupDateFieldState extends TextualDateFieldState {
public static final String DESCRIPTION_FOR_ASSISTIVE_DEVICES = "Arrow down key opens calendar element for choosing the date";
@@ -23,5 +25,6 @@ public class PopupDateFieldState extends TextualDateFieldState {
}
public boolean textFieldEnabled = true;
+ @NoLayout
public String descriptionForAssistiveDevices = DESCRIPTION_FOR_ASSISTIVE_DEVICES;
}
diff --git a/shared/src/com/vaadin/shared/ui/datefield/TextualDateFieldState.java b/shared/src/com/vaadin/shared/ui/datefield/TextualDateFieldState.java
index 09bfb9c1a1..bf38ee04a9 100644
--- a/shared/src/com/vaadin/shared/ui/datefield/TextualDateFieldState.java
+++ b/shared/src/com/vaadin/shared/ui/datefield/TextualDateFieldState.java
@@ -18,6 +18,7 @@ package com.vaadin.shared.ui.datefield;
import java.util.Date;
import com.vaadin.shared.AbstractFieldState;
+import com.vaadin.shared.annotations.NoLayout;
public class TextualDateFieldState extends AbstractFieldState {
{
@@ -28,11 +29,13 @@ public class TextualDateFieldState extends AbstractFieldState {
* Start range that has been cleared, depending on the resolution of the
* date field
*/
+ @NoLayout
public Date rangeStart = null;
/*
* End range that has been cleared, depending on the resolution of the date
* field
*/
+ @NoLayout
public Date rangeEnd = null;
}
diff --git a/shared/src/com/vaadin/shared/ui/grid/ColumnGroupState.java b/shared/src/com/vaadin/shared/ui/grid/ColumnGroupState.java
new file mode 100644
index 0000000000..2ef0dfc3f8
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/grid/ColumnGroupState.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.shared.ui.grid;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The column group data shared between the server and the client
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class ColumnGroupState implements Serializable {
+
+ /**
+ * The columns that is included in the group
+ */
+ public List<String> columns = new ArrayList<String>();
+
+ /**
+ * The header text of the group
+ */
+ public String header;
+
+ /**
+ * The footer text of the group
+ */
+ public String footer;
+}
diff --git a/shared/src/com/vaadin/shared/ui/grid/EditorClientRpc.java b/shared/src/com/vaadin/shared/ui/grid/EditorClientRpc.java
new file mode 100644
index 0000000000..c083252754
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/grid/EditorClientRpc.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui.grid;
+
+import com.vaadin.shared.communication.ClientRpc;
+
+/**
+ * An RPC interface for the grid editor server-to-client communications.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public interface EditorClientRpc extends ClientRpc {
+
+ /**
+ * Tells the client to open the editor and bind data to it.
+ *
+ * @param rowIndex
+ * the index of the edited row
+ */
+ void bind(int rowIndex);
+
+ /**
+ * Tells the client to cancel editing and hide the editor.
+ *
+ * @param rowIndex
+ * the index of the edited row
+ */
+ void cancel(int rowIndex);
+
+ /**
+ * Confirms a pending {@link EditorServerRpc#bind(int) bind request}
+ * sent by the client.
+ */
+ void confirmBind();
+
+ /**
+ * Confirms a pending {@link EditorServerRpc#save(int) save request}
+ * sent by the client.
+ */
+ void confirmSave();
+}
diff --git a/shared/src/com/vaadin/shared/ui/grid/EditorServerRpc.java b/shared/src/com/vaadin/shared/ui/grid/EditorServerRpc.java
new file mode 100644
index 0000000000..57df691547
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/grid/EditorServerRpc.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui.grid;
+
+import com.vaadin.shared.communication.ServerRpc;
+
+/**
+ * An RPC interface for the grid editor client-to-server communications.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public interface EditorServerRpc extends ServerRpc {
+
+ /**
+ * Asks the server to open the editor and bind data to it. When a bind
+ * request is sent, it must be acknowledged with a
+ * {@link EditorClientRpc#confirmBind() confirm call} before the client
+ * can open the editor.
+ *
+ * @param rowIndex
+ * the index of the edited row
+ */
+ void bind(int rowIndex);
+
+ /**
+ * Asks the server to save unsaved changes in the editor to the data source.
+ * When a save request is sent, it must be acknowledged with a
+ * {@link EditorClientRpc#confirmSave() confirm call}.
+ *
+ * @param rowIndex
+ * the index of the edited row
+ */
+ void save(int rowIndex);
+
+ /**
+ * Tells the server to cancel editing. When sending a cancel request, the
+ * client does not need to wait for confirmation by the server before hiding
+ * the editor.
+ *
+ * @param rowIndex
+ * the index of the edited row
+ */
+ void cancel(int rowIndex);
+}
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridClientRpc.java b/shared/src/com/vaadin/shared/ui/grid/GridClientRpc.java
new file mode 100644
index 0000000000..ade9e87f36
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/grid/GridClientRpc.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui.grid;
+
+import com.vaadin.shared.communication.ClientRpc;
+
+/**
+ * Server-to-client RPC interface for the Grid component.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public interface GridClientRpc extends ClientRpc {
+
+ /**
+ * Command client Grid to scroll to a specific data row.
+ *
+ * @param row
+ * zero-based row index. If the row index is below zero or above
+ * the row count of the client-side data source, a client-side
+ * exception will be triggered. Since this exception has no
+ * handling by default, an out-of-bounds value will cause a
+ * client-side crash.
+ * @param destination
+ * desired placement of scrolled-to row. See the documentation
+ * for {@link ScrollDestination} for more information.
+ */
+ public void scrollToRow(int row, ScrollDestination destination);
+
+ /**
+ * Command client Grid to scroll to the first row.
+ */
+ public void scrollToStart();
+
+ /**
+ * Command client Grid to scroll to the last row.
+ */
+ public void scrollToEnd();
+
+}
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java b/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java
new file mode 100644
index 0000000000..11cb133fa5
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui.grid;
+
+import java.io.Serializable;
+
+import com.vaadin.shared.Connector;
+
+/**
+ * Column state DTO for transferring column properties from the server to the
+ * client
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class GridColumnState implements Serializable {
+
+ public static final double DEFAULT_MAX_WIDTH = -1;
+ public static final double DEFAULT_MIN_WIDTH = 10.0d;
+ public static final int DEFAULT_EXPAND_RATIO = -1;
+
+ public static final double DEFAULT_COLUMN_WIDTH_PX = -1;
+
+ /**
+ * Id used by grid connector to map server side column with client side
+ * column
+ */
+ public String id;
+
+ /**
+ * Column width in pixels. Default column width is
+ * {@value #DEFAULT_COLUMN_WIDTH_PX}.
+ */
+ public double width = DEFAULT_COLUMN_WIDTH_PX;
+
+ /**
+ * The connector for the renderer used to render the cells in this column.
+ */
+ public Connector rendererConnector;
+
+ /**
+ * The connector for the field used to edit cells in this column when the
+ * editor interface is active.
+ */
+ public Connector editorConnector;
+
+ /**
+ * Are sorting indicators shown for a column. Default is false.
+ */
+ public boolean sortable = false;
+
+ /** How much of the remaining space this column will reserve. */
+ public int expandRatio = DEFAULT_EXPAND_RATIO;
+
+ /**
+ * The maximum expansion width of this column. -1 for "no maximum". If
+ * maxWidth is less than the calculated width, maxWidth is ignored.
+ */
+ public double maxWidth = DEFAULT_MAX_WIDTH;
+
+ /**
+ * The minimum expansion width of this column. -1 for "no minimum". If
+ * minWidth is less than the calculated width, minWidth will win.
+ */
+ public double minWidth = DEFAULT_MIN_WIDTH;
+}
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridConstants.java b/shared/src/com/vaadin/shared/ui/grid/GridConstants.java
new file mode 100644
index 0000000000..1ee79a5d37
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/grid/GridConstants.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui.grid;
+
+import java.io.Serializable;
+
+/**
+ * Container class for common constants and default values used by the Grid
+ * component.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public final class GridConstants implements Serializable {
+
+ /**
+ * Default padding in pixels when scrolling programmatically, without an
+ * explicitly defined padding value.
+ */
+ public static final int DEFAULT_PADDING = 0;
+
+ /**
+ * Delay before a long tap action is triggered. Number in milliseconds.
+ */
+ public static final int LONG_TAP_DELAY = 500;
+
+ /**
+ * The threshold in pixels a finger can move while long tapping.
+ */
+ public static final int LONG_TAP_THRESHOLD = 3;
+}
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridServerRpc.java b/shared/src/com/vaadin/shared/ui/grid/GridServerRpc.java
new file mode 100644
index 0000000000..141b1ed9ca
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/grid/GridServerRpc.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui.grid;
+
+import java.util.List;
+
+import com.vaadin.shared.communication.ServerRpc;
+import com.vaadin.shared.data.sort.SortDirection;
+
+/**
+ * Client-to-server RPC interface for the Grid component
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public interface GridServerRpc extends ServerRpc {
+ void selectionChange(List<String> newSelection);
+
+ void sort(String[] columnIds, SortDirection[] directions,
+ boolean userOriginated);
+
+ void selectAll();
+}
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridState.java b/shared/src/com/vaadin/shared/ui/grid/GridState.java
new file mode 100644
index 0000000000..1f98431caf
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/grid/GridState.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.shared.ui.grid;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.vaadin.shared.AbstractComponentState;
+import com.vaadin.shared.annotations.DelegateToWidget;
+import com.vaadin.shared.data.sort.SortDirection;
+
+/**
+ * The shared state for the {@link com.vaadin.ui.components.grid.Grid} component
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class GridState extends AbstractComponentState {
+
+ /**
+ * A description of which of the three bundled SelectionModels is currently
+ * in use.
+ * <p>
+ * Used as a data transfer object instead of the client/server ones, because
+ * they don't know about each others classes.
+ *
+ * @see com.vaadin.ui.components.grid.Grid.SelectionMode
+ * @see com.vaadin.client.ui.grid.Grid.SelectionMode
+ */
+ public enum SharedSelectionMode {
+ /**
+ * Representation of a single selection mode
+ *
+ * @see com.vaadin.ui.components.grid.Grid.SelectionMode#SINGLE
+ * @see com.vaadin.client.ui.grid.Grid.SelectionMode#SINGLE
+ */
+ SINGLE,
+
+ /**
+ * Representation of a multiselection mode
+ *
+ * @see com.vaadin.ui.components.grid.Grid.SelectionMode#MULTI
+ * @see com.vaadin.client.ui.grid.Grid.SelectionMode#MULTI
+ */
+ MULTI,
+
+ /**
+ * Representation of a no-selection mode
+ *
+ * @see com.vaadin.ui.components.grid.Grid.SelectionMode#NONE
+ * @see com.vaadin.client.ui.grid.Grid.SelectionMode#NONE
+ */
+ NONE;
+ }
+
+ /**
+ * The default value for height-by-rows for both GWT widgets
+ * {@link com.vaadin.ui.components.grid Grid} and
+ * {@link com.vaadin.client.ui.grid.Escalator Escalator}
+ */
+ public static final double DEFAULT_HEIGHT_BY_ROWS = 10.0d;
+
+ /**
+ * The key in which a row's data can be found
+ *
+ * @see com.vaadin.shared.data.DataProviderRpc#setRowData(int, String)
+ */
+ public static final String JSONKEY_DATA = "d";
+
+ /**
+ * The key in which a row's own key can be found
+ *
+ * @see com.vaadin.shared.data.DataProviderRpc#setRowData(int, String)
+ */
+ public static final String JSONKEY_ROWKEY = "k";
+
+ /**
+ * The key in which a row's generated style can be found
+ *
+ * @see com.vaadin.shared.data.DataProviderRpc#setRowData(int, String)
+ */
+ public static final String JSONKEY_ROWSTYLE = "rs";
+
+ /**
+ * The key in which a generated styles for a row's cells can be found
+ *
+ * @see com.vaadin.shared.data.DataProviderRpc#setRowData(int, String)
+ */
+ public static final String JSONKEY_CELLSTYLES = "cs";
+
+ /**
+ * Columns in grid.
+ */
+ public List<GridColumnState> columns = new ArrayList<GridColumnState>();
+
+ /**
+ * Column order in grid.
+ */
+ public List<String> columnOrder = new ArrayList<String>();
+
+ public GridStaticSectionState header = new GridStaticSectionState();
+
+ public GridStaticSectionState footer = new GridStaticSectionState();
+
+ /** The number of frozen columns */
+ public int frozenColumnCount = 0;
+
+ /** The height of the Grid in terms of body rows. */
+ @DelegateToWidget
+ public double heightByRows = DEFAULT_HEIGHT_BY_ROWS;
+
+ /** The mode by which Grid defines its height. */
+ @DelegateToWidget
+ public HeightMode heightMode = HeightMode.CSS;
+
+ // instantiated just to avoid NPEs
+ public List<String> selectedKeys = new ArrayList<String>();
+
+ public SharedSelectionMode selectionMode;
+
+ /** Keys of the currently sorted columns */
+ public String[] sortColumns = new String[0];
+
+ /** Directions for each sorted column */
+ public SortDirection[] sortDirs = new SortDirection[0];
+
+ /** The enabled state of the editor interface */
+ public boolean editorEnabled = false;
+
+ /** Whether row data might contain generated row styles */
+ public boolean hasRowStyleGenerator;
+ /** Whether row data might contain generated cell styles */
+ public boolean hasCellStyleGenerator;
+
+}
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridStaticCellType.java b/shared/src/com/vaadin/shared/ui/grid/GridStaticCellType.java
new file mode 100644
index 0000000000..eae4bc8da4
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/grid/GridStaticCellType.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui.grid;
+
+/**
+ * Enumeration, specifying the content type of a Cell in a GridStaticSection.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public enum GridStaticCellType {
+ /**
+ * Text content
+ */
+ TEXT,
+
+ /**
+ * HTML content
+ */
+ HTML,
+
+ /**
+ * Widget content
+ */
+ WIDGET;
+} \ No newline at end of file
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java b/shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java
new file mode 100644
index 0000000000..88539913d1
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui.grid;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.vaadin.shared.Connector;
+
+/**
+ * Shared state for Grid headers and footers.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class GridStaticSectionState implements Serializable {
+
+ public static class CellState implements Serializable {
+ public String text = "";
+
+ public String html = "";
+
+ public Connector connector = null;
+
+ public GridStaticCellType type = GridStaticCellType.TEXT;
+
+ public String columnId;
+
+ public String styleName = null;
+ }
+
+ public static class RowState implements Serializable {
+ public List<CellState> cells = new ArrayList<CellState>();
+
+ public boolean defaultRow = false;
+
+ /**
+ * Map from column id set to cell state for merged state.
+ */
+ public Map<Set<String>, CellState> cellGroups = new HashMap<Set<String>, CellState>();
+
+ /**
+ * The style name for the row. Null if none.
+ */
+ public String styleName = null;
+ }
+
+ public List<RowState> rows = new ArrayList<RowState>();
+
+ public boolean visible = true;
+}
diff --git a/shared/src/com/vaadin/shared/ui/grid/HeightMode.java b/shared/src/com/vaadin/shared/ui/grid/HeightMode.java
new file mode 100644
index 0000000000..228fcbf0f4
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/grid/HeightMode.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui.grid;
+
+/**
+ * The modes for height calculation that are supported by Grid (
+ * {@link com.vaadin.client.ui.grid.Grid client} and
+ * {@link com.vaadin.ui.components.grid.Grid server}) /
+ * {@link com.vaadin.client.ui.grid.Escalator Escalator}.
+ *
+ * @since
+ * @author Vaadin Ltd
+ * @see com.vaadin.client.ui.grid.Grid#setHeightMode(HeightMode)
+ * @see com.vaadin.ui.components.grid.Grid#setHeightMode(HeightMode)
+ * @see com.vaadin.client.ui.grid.Escalator#setHeightMode(HeightMode)
+ */
+public enum HeightMode {
+ /**
+ * The height of the Component or Widget is defined by a CSS-like value.
+ * (e.g. "100px", "50em" or "25%")
+ */
+ CSS,
+
+ /**
+ * The height of the Component or Widget in question is defined by a number
+ * of rows.
+ */
+ ROW;
+}
diff --git a/shared/src/com/vaadin/shared/ui/grid/Range.java b/shared/src/com/vaadin/shared/ui/grid/Range.java
new file mode 100644
index 0000000000..2054845320
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/grid/Range.java
@@ -0,0 +1,431 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.shared.ui.grid;
+
+import java.io.Serializable;
+
+/**
+ * An immutable representation of a range, marked by start and end points.
+ * <p>
+ * The range is treated as inclusive at the start, and exclusive at the end.
+ * I.e. the range [0..1[ has the length 1, and represents one integer: 0.
+ * <p>
+ * The range is considered {@link #isEmpty() empty} if the start is the same as
+ * the end.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public final class Range implements Serializable {
+ private final int start;
+ private final int end;
+
+ /**
+ * Creates a range object representing a single integer.
+ *
+ * @param integer
+ * the number to represent as a range
+ * @return the range represented by <code>integer</code>
+ */
+ public static Range withOnly(final int integer) {
+ return new Range(integer, integer + 1);
+ }
+
+ /**
+ * Creates a range between two integers.
+ * <p>
+ * The range start is <em>inclusive</em> and the end is <em>exclusive</em>.
+ * So, a range "between" 0 and 5 represents the numbers 0, 1, 2, 3 and 4,
+ * but not 5.
+ *
+ * @param start
+ * the start of the the range, inclusive
+ * @param end
+ * the end of the range, exclusive
+ * @return a range representing <code>[start..end[</code>
+ * @throws IllegalArgumentException
+ * if <code>start &gt; end</code>
+ */
+ public static Range between(final int start, final int end)
+ throws IllegalArgumentException {
+ return new Range(start, end);
+ }
+
+ /**
+ * Creates a range from a start point, with a given length.
+ *
+ * @param start
+ * the first integer to include in the range
+ * @param length
+ * the length of the resulting range
+ * @return a range starting from <code>start</code>, with
+ * <code>length</code> number of integers following
+ * @throws IllegalArgumentException
+ * if length &lt; 0
+ */
+ public static Range withLength(final int start, final int length)
+ throws IllegalArgumentException {
+ if (length < 0) {
+ /*
+ * The constructor of Range will throw an exception if start >
+ * start+length (i.e. if length is negative). We're throwing the
+ * same exception type, just with a more descriptive message.
+ */
+ throw new IllegalArgumentException("length must not be negative");
+ }
+ return new Range(start, start + length);
+ }
+
+ /**
+ * Creates a new range between two numbers: <code>[start..end[</code>.
+ *
+ * @param start
+ * the start integer, inclusive
+ * @param end
+ * the end integer, exclusive
+ * @throws IllegalArgumentException
+ * if <code>start &gt; end</code>
+ */
+ private Range(final int start, final int end)
+ throws IllegalArgumentException {
+ if (start > end) {
+ throw new IllegalArgumentException(
+ "start must not be greater than end");
+ }
+
+ this.start = start;
+ this.end = end;
+ }
+
+ /**
+ * Returns the <em>inclusive</em> start point of this range.
+ *
+ * @return the start point of this range
+ */
+ public int getStart() {
+ return start;
+ }
+
+ /**
+ * Returns the <em>exclusive</em> end point of this range.
+ *
+ * @return the end point of this range
+ */
+ public int getEnd() {
+ return end;
+ }
+
+ /**
+ * The number of integers contained in the range.
+ *
+ * @return the number of integers contained in the range
+ */
+ public int length() {
+ return getEnd() - getStart();
+ }
+
+ /**
+ * Checks whether the range has no elements between the start and end.
+ *
+ * @return <code>true</code> iff the range contains no elements.
+ */
+ public boolean isEmpty() {
+ return getStart() >= getEnd();
+ }
+
+ /**
+ * Checks whether this range and another range are at least partially
+ * covering the same values.
+ *
+ * @param other
+ * the other range to check against
+ * @return <code>true</code> if this and <code>other</code> intersect
+ */
+ public boolean intersects(final Range other) {
+ return getStart() < other.getEnd() && other.getStart() < getEnd();
+ }
+
+ /**
+ * Checks whether an integer is found within this range.
+ *
+ * @param integer
+ * an integer to test for presence in this range
+ * @return <code>true</code> iff <code>integer</code> is in this range
+ */
+ public boolean contains(final int integer) {
+ return getStart() <= integer && integer < getEnd();
+ }
+
+ /**
+ * Checks whether this range is a subset of another range.
+ *
+ * @return <code>true</code> iff <code>other</code> completely wraps this
+ * range
+ */
+ public boolean isSubsetOf(final Range other) {
+ return other.getStart() <= getStart() && getEnd() <= other.getEnd();
+ }
+
+ /**
+ * Overlay this range with another one, and partition the ranges according
+ * to how they position relative to each other.
+ * <p>
+ * The three partitions are returned as a three-element Range array:
+ * <ul>
+ * <li>Elements in this range that occur before elements in
+ * <code>other</code>.
+ * <li>Elements that are shared between the two ranges.
+ * <li>Elements in this range that occur after elements in
+ * <code>other</code>.
+ * </ul>
+ *
+ * @param other
+ * the other range to act as delimiters.
+ * @return a three-element Range array of partitions depicting the elements
+ * before (index 0), shared/inside (index 1) and after (index 2).
+ */
+ public Range[] partitionWith(final Range other) {
+ final Range[] splitBefore = splitAt(other.getStart());
+ final Range rangeBefore = splitBefore[0];
+ final Range[] splitAfter = splitBefore[1].splitAt(other.getEnd());
+ final Range rangeInside = splitAfter[0];
+ final Range rangeAfter = splitAfter[1];
+ return new Range[] { rangeBefore, rangeInside, rangeAfter };
+ }
+
+ /**
+ * Get a range that is based on this one, but offset by a number.
+ *
+ * @param offset
+ * the number to offset by
+ * @return a copy of this range, offset by <code>offset</code>
+ */
+ public Range offsetBy(final int offset) {
+ if (offset == 0) {
+ return this;
+ } else {
+ return new Range(start + offset, end + offset);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + " [" + getStart() + ".." + getEnd()
+ + "[" + (isEmpty() ? " (empty)" : "");
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + end;
+ result = prime * result + start;
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Range other = (Range) obj;
+ if (end != other.end) {
+ return false;
+ }
+ if (start != other.start) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Checks whether this range starts before the start of another range.
+ *
+ * @param other
+ * the other range to compare against
+ * @return <code>true</code> iff this range starts before the
+ * <code>other</code>
+ */
+ public boolean startsBefore(final Range other) {
+ return getStart() < other.getStart();
+ }
+
+ /**
+ * Checks whether this range ends before the start of another range.
+ *
+ * @param other
+ * the other range to compare against
+ * @return <code>true</code> iff this range ends before the
+ * <code>other</code>
+ */
+ public boolean endsBefore(final Range other) {
+ return getEnd() <= other.getStart();
+ }
+
+ /**
+ * Checks whether this range ends after the end of another range.
+ *
+ * @param other
+ * the other range to compare against
+ * @return <code>true</code> iff this range ends after the
+ * <code>other</code>
+ */
+ public boolean endsAfter(final Range other) {
+ return getEnd() > other.getEnd();
+ }
+
+ /**
+ * Checks whether this range starts after the end of another range.
+ *
+ * @param other
+ * the other range to compare against
+ * @return <code>true</code> iff this range starts after the
+ * <code>other</code>
+ */
+ public boolean startsAfter(final Range other) {
+ return getStart() >= other.getEnd();
+ }
+
+ /**
+ * Split the range into two at a certain integer.
+ * <p>
+ * <em>Example:</em> <code>[5..10[.splitAt(7) == [5..7[, [7..10[</code>
+ *
+ * @param integer
+ * the integer at which to split the range into two
+ * @return an array of two ranges, with <code>[start..integer[</code> in the
+ * first element, and <code>[integer..end[</code> in the second
+ * element.
+ * <p>
+ * If {@code integer} is less than {@code start}, [empty,
+ * {@code this} ] is returned. if <code>integer</code> is equal to
+ * or greater than {@code end}, [{@code this}, empty] is returned
+ * instead.
+ */
+ public Range[] splitAt(final int integer) {
+ if (integer < start) {
+ return new Range[] { Range.withLength(start, 0), this };
+ } else if (integer >= end) {
+ return new Range[] { this, Range.withLength(end, 0) };
+ } else {
+ return new Range[] { new Range(start, integer),
+ new Range(integer, end) };
+ }
+ }
+
+ /**
+ * Split the range into two after a certain number of integers into the
+ * range.
+ * <p>
+ * Calling this method is equivalent to calling
+ * <code>{@link #splitAt(int) splitAt}({@link #getStart()}+length);</code>
+ * <p>
+ * <em>Example:</em>
+ * <code>[5..10[.splitAtFromStart(2) == [5..7[, [7..10[</code>
+ *
+ * @param length
+ * the length at which to split this range into two
+ * @return an array of two ranges, having the <code>length</code>-first
+ * elements of this range, and the second range having the rest. If
+ * <code>length</code> &leq; 0, the first element will be empty, and
+ * the second element will be this range. If <code>length</code>
+ * &geq; {@link #length()}, the first element will be this range,
+ * and the second element will be empty.
+ */
+ public Range[] splitAtFromStart(final int length) {
+ return splitAt(getStart() + length);
+ }
+
+ /**
+ * Combines two ranges to create a range containing all values in both
+ * ranges, provided there are no gaps between the ranges.
+ *
+ * @param other
+ * the range to combine with this range
+ *
+ * @return the combined range
+ *
+ * @throws IllegalArgumentException
+ * if the two ranges aren't connected
+ */
+ public Range combineWith(Range other) throws IllegalArgumentException {
+ if (getStart() > other.getEnd() || other.getStart() > getEnd()) {
+ throw new IllegalArgumentException("There is a gap between " + this
+ + " and " + other);
+ }
+
+ return Range.between(Math.min(getStart(), other.getStart()),
+ Math.max(getEnd(), other.getEnd()));
+ }
+
+ /**
+ * Creates a range that is expanded the given amounts in both ends.
+ *
+ * @param startDelta
+ * the amount to expand by in the beginning of the range
+ * @param endDelta
+ * the amount to expand by in the end of the range
+ *
+ * @return an expanded range
+ *
+ * @throws IllegalArgumentException
+ * if the new range would have <code>start &gt; end</code>
+ */
+ public Range expand(int startDelta, int endDelta)
+ throws IllegalArgumentException {
+ return Range.between(getStart() - startDelta, getEnd() + endDelta);
+ }
+
+ /**
+ * Limits this range to be within the bounds of the provided range.
+ * <p>
+ * This is basically an optimized way of calculating
+ * <code>{@link #partitionWith(Range)}[1]</code> without the overhead of
+ * defining the parts that do not overlap.
+ * <p>
+ * If the two ranges do not intersect, an empty range is returned. There are
+ * no guarantees about the position of that range.
+ *
+ * @param bounds
+ * the bounds that the returned range should be limited to
+ * @return a bounded range
+ */
+ public Range restrictTo(Range bounds) {
+ boolean startWithin = getStart() >= bounds.getStart();
+ boolean endWithin = getEnd() <= bounds.getEnd();
+
+ if (startWithin) {
+ if (endWithin) {
+ return this;
+ } else {
+ return Range.between(getStart(), bounds.getEnd());
+ }
+ } else {
+ if (endWithin) {
+ return Range.between(bounds.getStart(), getEnd());
+ } else {
+ return bounds;
+ }
+ }
+ }
+}
diff --git a/shared/src/com/vaadin/shared/ui/grid/ScrollDestination.java b/shared/src/com/vaadin/shared/ui/grid/ScrollDestination.java
new file mode 100644
index 0000000000..43d5fcc21b
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/grid/ScrollDestination.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui.grid;
+
+/**
+ * Enumeration, specifying the destinations that are supported when scrolling
+ * rows or columns into view.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public enum ScrollDestination {
+
+ /**
+ * Scroll as little as possible to show the target element. If the element
+ * fits into view, this works as START or END depending on the current
+ * scroll position. If the element does not fit into view, this works as
+ * START.
+ */
+ ANY,
+
+ /**
+ * Scrolls so that the element is shown at the start of the viewport. The
+ * viewport will, however, not scroll beyond its contents.
+ */
+ START,
+
+ /**
+ * Scrolls so that the element is shown in the middle of the viewport. The
+ * viewport will, however, not scroll beyond its contents, given more
+ * elements than what the viewport is able to show at once. Under no
+ * circumstances will the viewport scroll before its first element.
+ */
+ MIDDLE,
+
+ /**
+ * Scrolls so that the element is shown at the end of the viewport. The
+ * viewport will, however, not scroll before its first element.
+ */
+ END
+
+}
diff --git a/shared/src/com/vaadin/shared/ui/grid/renderers/RendererClickRpc.java b/shared/src/com/vaadin/shared/ui/grid/renderers/RendererClickRpc.java
new file mode 100644
index 0000000000..658caef050
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/grid/renderers/RendererClickRpc.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui.grid.renderers;
+
+import com.vaadin.shared.MouseEventDetails;
+import com.vaadin.shared.communication.ServerRpc;
+
+public interface RendererClickRpc extends ServerRpc {
+ /**
+ * Called when a click event has occurred and there are server side
+ * listeners for the event.
+ *
+ * @param mouseDetails
+ * Details about the mouse when the event took place
+ */
+ public void click(String rowKey, String columnId,
+ MouseEventDetails mouseDetails);
+}
diff --git a/shared/src/com/vaadin/shared/ui/panel/PanelState.java b/shared/src/com/vaadin/shared/ui/panel/PanelState.java
index 6c0fcb683c..8f48fad921 100644
--- a/shared/src/com/vaadin/shared/ui/panel/PanelState.java
+++ b/shared/src/com/vaadin/shared/ui/panel/PanelState.java
@@ -16,11 +16,14 @@
package com.vaadin.shared.ui.panel;
import com.vaadin.shared.AbstractComponentState;
+import com.vaadin.shared.annotations.NoLayout;
public class PanelState extends AbstractComponentState {
{
primaryStyleName = "v-panel";
}
+ @NoLayout
public int tabIndex;
+ @NoLayout
public int scrollLeft, scrollTop;
}
diff --git a/shared/src/com/vaadin/shared/ui/popupview/PopupViewState.java b/shared/src/com/vaadin/shared/ui/popupview/PopupViewState.java
index da49e47ae8..86fda428a1 100644
--- a/shared/src/com/vaadin/shared/ui/popupview/PopupViewState.java
+++ b/shared/src/com/vaadin/shared/ui/popupview/PopupViewState.java
@@ -16,10 +16,12 @@
package com.vaadin.shared.ui.popupview;
import com.vaadin.shared.AbstractComponentState;
+import com.vaadin.shared.annotations.NoLayout;
public class PopupViewState extends AbstractComponentState {
public String html;
+ @NoLayout
public boolean hideOnMouseOut;
}
diff --git a/shared/src/com/vaadin/shared/ui/progressindicator/ProgressBarState.java b/shared/src/com/vaadin/shared/ui/progressindicator/ProgressBarState.java
index 79ef766951..6f557489dd 100644
--- a/shared/src/com/vaadin/shared/ui/progressindicator/ProgressBarState.java
+++ b/shared/src/com/vaadin/shared/ui/progressindicator/ProgressBarState.java
@@ -17,6 +17,7 @@
package com.vaadin.shared.ui.progressindicator;
import com.vaadin.shared.AbstractFieldState;
+import com.vaadin.shared.annotations.NoLayout;
import com.vaadin.shared.communication.SharedState;
/**
@@ -32,6 +33,7 @@ public class ProgressBarState extends AbstractFieldState {
primaryStyleName = PRIMARY_STYLE_NAME;
}
public boolean indeterminate = false;
+ @NoLayout
public Float state = 0.0f;
}
diff --git a/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorState.java b/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorState.java
index 15d0a947d7..9b3cf94d4a 100644
--- a/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorState.java
+++ b/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorState.java
@@ -15,6 +15,8 @@
*/
package com.vaadin.shared.ui.progressindicator;
+import com.vaadin.shared.annotations.NoLayout;
+
@Deprecated
public class ProgressIndicatorState extends ProgressBarState {
public static final String PRIMARY_STYLE_NAME = "v-progressindicator";
@@ -23,5 +25,6 @@ public class ProgressIndicatorState extends ProgressBarState {
primaryStyleName = PRIMARY_STYLE_NAME;
}
+ @NoLayout
public int pollingInterval = 1000;
}
diff --git a/shared/src/com/vaadin/shared/ui/slider/SliderState.java b/shared/src/com/vaadin/shared/ui/slider/SliderState.java
index 0e48a0c4e2..a96d35bc13 100644
--- a/shared/src/com/vaadin/shared/ui/slider/SliderState.java
+++ b/shared/src/com/vaadin/shared/ui/slider/SliderState.java
@@ -16,21 +16,26 @@
package com.vaadin.shared.ui.slider;
import com.vaadin.shared.AbstractFieldState;
+import com.vaadin.shared.annotations.NoLayout;
public class SliderState extends AbstractFieldState {
{
primaryStyleName = "v-slider";
}
+ @NoLayout
public double value;
+ @NoLayout
public double maxValue = 100;
+ @NoLayout
public double minValue = 0;
/**
* The number of fractional digits that are considered significant. Must be
* non-negative.
*/
+ @NoLayout
public int resolution = 0;
public SliderOrientation orientation = SliderOrientation.HORIZONTAL;
diff --git a/shared/src/com/vaadin/shared/ui/tabsheet/TabsheetState.java b/shared/src/com/vaadin/shared/ui/tabsheet/TabsheetState.java
index 98a1d2b87f..69a3330f64 100644
--- a/shared/src/com/vaadin/shared/ui/tabsheet/TabsheetState.java
+++ b/shared/src/com/vaadin/shared/ui/tabsheet/TabsheetState.java
@@ -19,6 +19,7 @@ import java.util.ArrayList;
import java.util.List;
import com.vaadin.shared.AbstractComponentState;
+import com.vaadin.shared.annotations.NoLayout;
public class TabsheetState extends AbstractComponentState {
public static final String PRIMARY_STYLE_NAME = "v-tabsheet";
@@ -31,6 +32,7 @@ public class TabsheetState extends AbstractComponentState {
* Index of the component when switching focus - not related to Tabsheet
* tabs.
*/
+ @NoLayout
public int tabIndex;
public List<TabState> tabs = new ArrayList<TabState>();
diff --git a/shared/src/com/vaadin/shared/ui/textarea/TextAreaState.java b/shared/src/com/vaadin/shared/ui/textarea/TextAreaState.java
index 380ee4c7fb..c1f9536278 100644
--- a/shared/src/com/vaadin/shared/ui/textarea/TextAreaState.java
+++ b/shared/src/com/vaadin/shared/ui/textarea/TextAreaState.java
@@ -16,6 +16,7 @@
package com.vaadin.shared.ui.textarea;
import com.vaadin.shared.annotations.DelegateToWidget;
+import com.vaadin.shared.annotations.NoLayout;
import com.vaadin.shared.ui.textfield.AbstractTextFieldState;
public class TextAreaState extends AbstractTextFieldState {
@@ -33,6 +34,7 @@ public class TextAreaState extends AbstractTextFieldState {
* Tells if word-wrapping should be used in the text area.
*/
@DelegateToWidget
+ @NoLayout
public boolean wordwrap = true;
}
diff --git a/shared/src/com/vaadin/shared/ui/textfield/AbstractTextFieldState.java b/shared/src/com/vaadin/shared/ui/textfield/AbstractTextFieldState.java
index 084d02cd7b..9d4272c22f 100644
--- a/shared/src/com/vaadin/shared/ui/textfield/AbstractTextFieldState.java
+++ b/shared/src/com/vaadin/shared/ui/textfield/AbstractTextFieldState.java
@@ -16,6 +16,7 @@
package com.vaadin.shared.ui.textfield;
import com.vaadin.shared.AbstractFieldState;
+import com.vaadin.shared.annotations.NoLayout;
public class AbstractTextFieldState extends AbstractFieldState {
{
@@ -25,6 +26,7 @@ public class AbstractTextFieldState extends AbstractFieldState {
/**
* Maximum character count in text field.
*/
+ @NoLayout
public int maxLength = -1;
/**
@@ -35,10 +37,12 @@ public class AbstractTextFieldState extends AbstractFieldState {
/**
* The prompt to display in an empty field. Null when disabled.
*/
+ @NoLayout
public String inputPrompt = null;
/**
* The text in the field
*/
+ @NoLayout
public String text = null;
}
diff --git a/shared/src/com/vaadin/shared/ui/ui/ScrollClientRpc.java b/shared/src/com/vaadin/shared/ui/ui/ScrollClientRpc.java
index e32a27830d..fb052a25e9 100644
--- a/shared/src/com/vaadin/shared/ui/ui/ScrollClientRpc.java
+++ b/shared/src/com/vaadin/shared/ui/ui/ScrollClientRpc.java
@@ -16,11 +16,14 @@
package com.vaadin.shared.ui.ui;
+import com.vaadin.shared.annotations.NoLayout;
import com.vaadin.shared.communication.ClientRpc;
public interface ScrollClientRpc extends ClientRpc {
+ @NoLayout
public void setScrollTop(int scrollTop);
+ @NoLayout
public void setScrollLeft(int scrollLeft);
}
diff --git a/shared/src/com/vaadin/shared/ui/window/WindowState.java b/shared/src/com/vaadin/shared/ui/window/WindowState.java
index fa73bea391..7dafba57ff 100644
--- a/shared/src/com/vaadin/shared/ui/window/WindowState.java
+++ b/shared/src/com/vaadin/shared/ui/window/WindowState.java
@@ -16,6 +16,7 @@
package com.vaadin.shared.ui.window;
import com.vaadin.shared.Connector;
+import com.vaadin.shared.annotations.NoLayout;
import com.vaadin.shared.ui.panel.PanelState;
public class WindowState extends PanelState {
@@ -23,20 +24,34 @@ public class WindowState extends PanelState {
primaryStyleName = "v-window";
}
+ @NoLayout
public boolean modal = false;
+ @NoLayout
public boolean resizable = true;
+ @NoLayout
public boolean resizeLazy = false;
+ @NoLayout
public boolean draggable = true;
+ @NoLayout
public boolean centered = false;
+ @NoLayout
public int positionX = -1;
+ @NoLayout
public int positionY = -1;
public WindowMode windowMode = WindowMode.NORMAL;
+ @NoLayout
public String assistivePrefix = "";
+ @NoLayout
public String assistivePostfix = "";
+ @NoLayout
public Connector[] contentDescription = new Connector[0];
+ @NoLayout
public WindowRole role = WindowRole.DIALOG;
+ @NoLayout
public boolean assistiveTabStop = false;
+ @NoLayout
public String assistiveTabStopTopText = "Top of dialog";
+ @NoLayout
public String assistiveTabStopBottomText = "Bottom of Dialog";
}
diff --git a/shared/src/com/vaadin/shared/util/SharedUtil.java b/shared/src/com/vaadin/shared/util/SharedUtil.java
index 7276f418fa..b40d8f03bb 100644
--- a/shared/src/com/vaadin/shared/util/SharedUtil.java
+++ b/shared/src/com/vaadin/shared/util/SharedUtil.java
@@ -60,4 +60,140 @@ public class SharedUtil implements Serializable {
*/
public static final String SIZE_PATTERN = "^(-?\\d*(?:\\.\\d+)?)(%|px|em|rem|ex|in|cm|mm|pt|pc)?$";
+ /**
+ * Splits a camelCaseString into an array of words with the casing
+ * preserved.
+ *
+ * @since 7.4
+ * @param camelCaseString
+ * The input string in camelCase format
+ * @return An array with one entry per word in the input string
+ */
+ public static String[] splitCamelCase(String camelCaseString) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < camelCaseString.length(); i++) {
+ char c = camelCaseString.charAt(i);
+ if (Character.isUpperCase(c) && isWordComplete(camelCaseString, i)) {
+ sb.append(' ');
+ }
+ sb.append(c);
+ }
+ return sb.toString().split(" ");
+ }
+
+ private static boolean isWordComplete(String camelCaseString, int i) {
+ if (i == 0) {
+ // Word can't end at the beginning
+ return false;
+ } else if (!Character.isUpperCase(camelCaseString.charAt(i - 1))) {
+ // Word ends if previous char wasn't upper case
+ return true;
+ } else if (i + 1 < camelCaseString.length()
+ && !Character.isUpperCase(camelCaseString.charAt(i + 1))) {
+ // Word ends if next char isn't upper case
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Converts a camelCaseString to a human friendly format (Camel case
+ * string).
+ * <p>
+ * In general splits words when the casing changes but also handles special
+ * cases such as consecutive upper case characters. Examples:
+ * <p>
+ * {@literal MyBeanContainer} becomes {@literal My Bean Container}
+ * {@literal AwesomeURLFactory} becomes {@literal Awesome URL Factory}
+ * {@literal SomeUriAction} becomes {@literal Some Uri Action}
+ *
+ * @since 7.4
+ * @param camelCaseString
+ * The input string in camelCase format
+ * @return A human friendly version of the input
+ */
+ public static String camelCaseToHumanFriendly(String camelCaseString) {
+ String[] parts = splitCamelCase(camelCaseString);
+ for (int i = 0; i < parts.length; i++) {
+ parts[i] = capitalize(parts[i]);
+ }
+ return join(parts, " ");
+ }
+
+ private static boolean isAllUpperCase(String string) {
+ for (int i = 0; i < string.length(); i++) {
+ char c = string.charAt(i);
+ if (!Character.isUpperCase(c) && !Character.isDigit(c)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Joins the words in the input array together into a single string by
+ * inserting the separator string between each word.
+ *
+ * @since 7.4
+ * @param parts
+ * The array of words
+ * @param separator
+ * The separator string to use between words
+ * @return The constructed string of words and separators
+ */
+ public static String join(String[] parts, String separator) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < parts.length; i++) {
+ sb.append(parts[i]);
+ sb.append(separator);
+ }
+ return sb.substring(0, sb.length() - 1);
+ }
+
+ /**
+ * Capitalizes the first character in the given string
+ *
+ * @since 7.4
+ * @param string
+ * The string to capitalize
+ * @return The capitalized string
+ */
+ public static String capitalize(String string) {
+ if (string == null) {
+ return null;
+ }
+
+ if (string.length() <= 1) {
+ return string.toUpperCase();
+ }
+
+ return string.substring(0, 1).toUpperCase() + string.substring(1);
+ }
+
+ /**
+ * Converts a property id to a human friendly format. Handles nested
+ * properties by only considering the last part, e.g. "address.streetName"
+ * is equal to "streetName" for this method.
+ *
+ * @since 7.4
+ * @param propertyId
+ * The propertyId to format
+ * @return A human friendly version of the property id
+ */
+ public static String propertyIdToHumanFriendly(Object propertyId) {
+ String string = propertyId.toString();
+ if (string.isEmpty()) {
+ return "";
+ }
+
+ // For nested properties, only use the last part
+ int dotLocation = string.lastIndexOf('.');
+ if (dotLocation > 0 && dotLocation < string.length() - 1) {
+ string = string.substring(dotLocation + 1);
+ }
+
+ return camelCaseToHumanFriendly(string);
+ }
+
}
diff --git a/shared/tests/src/com/vaadin/shared/ui/grid/RangeTest.java b/shared/tests/src/com/vaadin/shared/ui/grid/RangeTest.java
new file mode 100644
index 0000000000..ab67b22d0b
--- /dev/null
+++ b/shared/tests/src/com/vaadin/shared/ui/grid/RangeTest.java
@@ -0,0 +1,406 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui.grid;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+@SuppressWarnings("static-method")
+public class RangeTest {
+
+ @Test(expected = IllegalArgumentException.class)
+ public void startAfterEndTest() {
+ Range.between(10, 9);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void negativeLengthTest() {
+ Range.withLength(10, -1);
+ }
+
+ @Test
+ public void constructorEquivalenceTest() {
+ assertEquals("10 == [10,11[", Range.withOnly(10), Range.between(10, 11));
+ assertEquals("[10,20[ == 10, length 10", Range.between(10, 20),
+ Range.withLength(10, 10));
+ assertEquals("10 == 10, length 1", Range.withOnly(10),
+ Range.withLength(10, 1));
+ }
+
+ @Test
+ public void boundsTest() {
+ {
+ final Range range = Range.between(0, 10);
+ assertEquals("between(0, 10) start", 0, range.getStart());
+ assertEquals("between(0, 10) end", 10, range.getEnd());
+ }
+
+ {
+ final Range single = Range.withOnly(10);
+ assertEquals("withOnly(10) start", 10, single.getStart());
+ assertEquals("withOnly(10) end", 11, single.getEnd());
+ }
+
+ {
+ final Range length = Range.withLength(10, 5);
+ assertEquals("withLength(10, 5) start", 10, length.getStart());
+ assertEquals("withLength(10, 5) end", 15, length.getEnd());
+ }
+ }
+
+ @Test
+ @SuppressWarnings("boxing")
+ public void equalsTest() {
+ final Range range1 = Range.between(0, 10);
+ final Range range2 = Range.withLength(0, 11);
+
+ assertTrue("null", !range1.equals(null));
+ assertTrue("reflexive", range1.equals(range1));
+ assertEquals("symmetric", range1.equals(range2), range2.equals(range1));
+ }
+
+ @Test
+ public void containsTest() {
+ final int start = 0;
+ final int end = 10;
+ final Range range = Range.between(start, end);
+
+ assertTrue("start should be contained", range.contains(start));
+ assertTrue("start-1 should not be contained",
+ !range.contains(start - 1));
+ assertTrue("end should not be contained", !range.contains(end));
+ assertTrue("end-1 should be contained", range.contains(end - 1));
+
+ assertTrue("[0..10[ contains 5", Range.between(0, 10).contains(5));
+ assertTrue("empty range does not contain 5", !Range.between(5, 5)
+ .contains(5));
+ }
+
+ @Test
+ public void emptyTest() {
+ assertTrue("[0..0[ should be empty", Range.between(0, 0).isEmpty());
+ assertTrue("Range of length 0 should be empty", Range.withLength(0, 0)
+ .isEmpty());
+
+ assertTrue("[0..1[ should not be empty", !Range.between(0, 1).isEmpty());
+ assertTrue("Range of length 1 should not be empty",
+ !Range.withLength(0, 1).isEmpty());
+ }
+
+ @Test
+ public void splitTest() {
+ final Range startRange = Range.between(0, 10);
+ final Range[] splitRanges = startRange.splitAt(5);
+ assertEquals("[0..10[ split at 5, lower", Range.between(0, 5),
+ splitRanges[0]);
+ assertEquals("[0..10[ split at 5, upper", Range.between(5, 10),
+ splitRanges[1]);
+ }
+
+ @Test
+ public void split_valueBefore() {
+ Range range = Range.between(10, 20);
+ Range[] splitRanges = range.splitAt(5);
+
+ assertEquals(Range.between(10, 10), splitRanges[0]);
+ assertEquals(range, splitRanges[1]);
+ }
+
+ @Test
+ public void split_valueAfter() {
+ Range range = Range.between(10, 20);
+ Range[] splitRanges = range.splitAt(25);
+
+ assertEquals(range, splitRanges[0]);
+ assertEquals(Range.between(20, 20), splitRanges[1]);
+ }
+
+ @Test
+ public void emptySplitTest() {
+ final Range range = Range.between(5, 10);
+ final Range[] split1 = range.splitAt(0);
+ assertTrue("split1, [0]", split1[0].isEmpty());
+ assertEquals("split1, [1]", range, split1[1]);
+
+ final Range[] split2 = range.splitAt(15);
+ assertEquals("split2, [0]", range, split2[0]);
+ assertTrue("split2, [1]", split2[1].isEmpty());
+ }
+
+ @Test
+ public void lengthTest() {
+ assertEquals("withLength length", 5, Range.withLength(10, 5).length());
+ assertEquals("between length", 5, Range.between(10, 15).length());
+ assertEquals("withOnly 10 length", 1, Range.withOnly(10).length());
+ }
+
+ @Test
+ public void intersectsTest() {
+ assertTrue("[0..10[ intersects [5..15[", Range.between(0, 10)
+ .intersects(Range.between(5, 15)));
+ assertTrue("[0..10[ does not intersect [10..20[", !Range.between(0, 10)
+ .intersects(Range.between(10, 20)));
+ }
+
+ @Test
+ public void intersects_emptyInside() {
+ assertTrue("[5..5[ does intersect with [0..10[", Range.between(5, 5)
+ .intersects(Range.between(0, 10)));
+ assertTrue("[0..10[ does intersect with [5..5[", Range.between(0, 10)
+ .intersects(Range.between(5, 5)));
+ }
+
+ @Test
+ public void intersects_emptyOutside() {
+ assertTrue("[15..15[ does not intersect with [0..10[",
+ !Range.between(15, 15).intersects(Range.between(0, 10)));
+ assertTrue("[0..10[ does not intersect with [15..15[",
+ !Range.between(0, 10).intersects(Range.between(15, 15)));
+ }
+
+ @Test
+ public void subsetTest() {
+ assertTrue("[5..10[ is subset of [0..20[", Range.between(5, 10)
+ .isSubsetOf(Range.between(0, 20)));
+
+ final Range range = Range.between(0, 10);
+ assertTrue("range is subset of self", range.isSubsetOf(range));
+
+ assertTrue("[0..10[ is not subset of [5..15[", !Range.between(0, 10)
+ .isSubsetOf(Range.between(5, 15)));
+ }
+
+ @Test
+ public void offsetTest() {
+ assertEquals(Range.between(5, 15), Range.between(0, 10).offsetBy(5));
+ }
+
+ @Test
+ public void rangeStartsBeforeTest() {
+ final Range former = Range.between(0, 5);
+ final Range latter = Range.between(1, 5);
+ assertTrue("former should starts before latter",
+ former.startsBefore(latter));
+ assertTrue("latter shouldn't start before latter",
+ !latter.startsBefore(former));
+
+ assertTrue("no overlap allowed",
+ !Range.between(0, 5).startsBefore(Range.between(0, 10)));
+ }
+
+ @Test
+ public void rangeStartsAfterTest() {
+ final Range former = Range.between(0, 5);
+ final Range latter = Range.between(5, 10);
+ assertTrue("latter should start after former",
+ latter.startsAfter(former));
+ assertTrue("former shouldn't start after latter",
+ !former.startsAfter(latter));
+
+ assertTrue("no overlap allowed",
+ !Range.between(5, 10).startsAfter(Range.between(0, 6)));
+ }
+
+ @Test
+ public void rangeEndsBeforeTest() {
+ final Range former = Range.between(0, 5);
+ final Range latter = Range.between(5, 10);
+ assertTrue("latter should end before former", former.endsBefore(latter));
+ assertTrue("former shouldn't end before latter",
+ !latter.endsBefore(former));
+
+ assertTrue("no overlap allowed",
+ !Range.between(5, 10).endsBefore(Range.between(9, 15)));
+ }
+
+ @Test
+ public void rangeEndsAfterTest() {
+ final Range former = Range.between(1, 5);
+ final Range latter = Range.between(1, 6);
+ assertTrue("latter should end after former", latter.endsAfter(former));
+ assertTrue("former shouldn't end after latter",
+ !former.endsAfter(latter));
+
+ assertTrue("no overlap allowed",
+ !Range.between(0, 10).endsAfter(Range.between(5, 10)));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void combine_notOverlappingFirstSmaller() {
+ Range.between(0, 10).combineWith(Range.between(11, 20));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void combine_notOverlappingSecondLarger() {
+ Range.between(11, 20).combineWith(Range.between(0, 10));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void combine_firstEmptyNotOverlapping() {
+ Range.between(15, 15).combineWith(Range.between(0, 10));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void combine_secondEmptyNotOverlapping() {
+ Range.between(0, 10).combineWith(Range.between(15, 15));
+ }
+
+ @Test
+ public void combine_barelyOverlapping() {
+ Range r1 = Range.between(0, 10);
+ Range r2 = Range.between(10, 20);
+
+ // Test both ways, should give the same result
+ Range combined1 = r1.combineWith(r2);
+ Range combined2 = r2.combineWith(r1);
+ assertEquals(combined1, combined2);
+
+ assertEquals(0, combined1.getStart());
+ assertEquals(20, combined1.getEnd());
+ }
+
+ @Test
+ public void combine_subRange() {
+ Range r1 = Range.between(0, 10);
+ Range r2 = Range.between(2, 8);
+
+ // Test both ways, should give the same result
+ Range combined1 = r1.combineWith(r2);
+ Range combined2 = r2.combineWith(r1);
+ assertEquals(combined1, combined2);
+
+ assertEquals(r1, combined1);
+ }
+
+ @Test
+ public void combine_intersecting() {
+ Range r1 = Range.between(0, 10);
+ Range r2 = Range.between(5, 15);
+
+ // Test both ways, should give the same result
+ Range combined1 = r1.combineWith(r2);
+ Range combined2 = r2.combineWith(r1);
+ assertEquals(combined1, combined2);
+
+ assertEquals(0, combined1.getStart());
+ assertEquals(15, combined1.getEnd());
+
+ }
+
+ @Test
+ public void combine_emptyInside() {
+ Range r1 = Range.between(0, 10);
+ Range r2 = Range.between(5, 5);
+
+ // Test both ways, should give the same result
+ Range combined1 = r1.combineWith(r2);
+ Range combined2 = r2.combineWith(r1);
+ assertEquals(combined1, combined2);
+
+ assertEquals(r1, combined1);
+ }
+
+ @Test
+ public void expand_basic() {
+ Range r1 = Range.between(5, 10);
+ Range r2 = r1.expand(2, 3);
+
+ assertEquals(Range.between(3, 13), r2);
+ }
+
+ @Test
+ public void expand_negativeLegal() {
+ Range r1 = Range.between(5, 10);
+
+ Range r2 = r1.expand(-2, -2);
+ assertEquals(Range.between(7, 8), r2);
+
+ Range r3 = r1.expand(-3, -2);
+ assertEquals(Range.between(8, 8), r3);
+
+ Range r4 = r1.expand(3, -8);
+ assertEquals(Range.between(2, 2), r4);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void expand_negativeIllegal1() {
+ Range r1 = Range.between(5, 10);
+
+ // Should throw because the start would contract beyond the end
+ r1.expand(-3, -3);
+
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void expand_negativeIllegal2() {
+ Range r1 = Range.between(5, 10);
+
+ // Should throw because the end would contract beyond the start
+ r1.expand(3, -9);
+ }
+
+ @Test
+ public void restrictTo_fullyInside() {
+ Range r1 = Range.between(5, 10);
+ Range r2 = Range.between(4, 11);
+
+ Range r3 = r1.restrictTo(r2);
+ assertTrue(r1 == r3);
+ }
+
+ @Test
+ public void restrictTo_fullyOutside() {
+ Range r1 = Range.between(4, 11);
+ Range r2 = Range.between(5, 10);
+
+ Range r3 = r1.restrictTo(r2);
+ assertTrue(r2 == r3);
+ }
+
+ public void restrictTo_notInterstecting() {
+ Range r1 = Range.between(5, 10);
+ Range r2 = Range.between(15, 20);
+
+ Range r3 = r1.restrictTo(r2);
+ assertTrue("Non-intersecting ranges should produce an empty result",
+ r3.isEmpty());
+
+ Range r4 = r2.restrictTo(r1);
+ assertTrue("Non-intersecting ranges should produce an empty result",
+ r4.isEmpty());
+ }
+
+ public void restrictTo_startOutside() {
+ Range r1 = Range.between(5, 10);
+ Range r2 = Range.between(7, 15);
+
+ Range r3 = r1.restrictTo(r2);
+
+ assertEquals(Range.between(7, 10), r3);
+ }
+
+ public void restrictTo_endOutside() {
+ Range r1 = Range.between(5, 10);
+ Range r2 = Range.between(4, 7);
+
+ Range r3 = r1.restrictTo(r2);
+
+ assertEquals(Range.between(5, 7), r3);
+ }
+
+}
diff --git a/shared/tests/src/com/vaadin/shared/util/SharedUtilTests.java b/shared/tests/src/com/vaadin/shared/util/SharedUtilTests.java
index b593032bd6..208d4ca7c7 100644
--- a/shared/tests/src/com/vaadin/shared/util/SharedUtilTests.java
+++ b/shared/tests/src/com/vaadin/shared/util/SharedUtilTests.java
@@ -1,43 +1,79 @@
package com.vaadin.shared.util;
-import org.junit.Before;
-import org.junit.Test;
-
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
-public class SharedUtilTests {
-
- private SharedUtil sut;
+import org.junit.Assert;
+import org.junit.Test;
- @Before
- public void setup() {
- sut = new SharedUtil();
- }
+public class SharedUtilTests {
@Test
public void trailingSlashIsTrimmed() {
- assertThat(sut.trimTrailingSlashes("/path/"), is("/path"));
+ assertThat(SharedUtil.trimTrailingSlashes("/path/"), is("/path"));
}
@Test
public void noTrailingSlashForTrimming() {
- assertThat(sut.trimTrailingSlashes("/path"), is("/path"));
+ assertThat(SharedUtil.trimTrailingSlashes("/path"), is("/path"));
}
@Test
public void trailingSlashesAreTrimmed() {
- assertThat(sut.trimTrailingSlashes("/path///"), is("/path"));
+ assertThat(SharedUtil.trimTrailingSlashes("/path///"), is("/path"));
}
@Test
public void emptyStringIsHandled() {
- assertThat(sut.trimTrailingSlashes(""), is(""));
+ assertThat(SharedUtil.trimTrailingSlashes(""), is(""));
}
@Test
public void rootSlashIsTrimmed() {
- assertThat(sut.trimTrailingSlashes("/"), is(""));
+ assertThat(SharedUtil.trimTrailingSlashes("/"), is(""));
}
+ @Test
+ public void camelCaseToHumanReadable() {
+ Assert.assertEquals("First Name",
+ SharedUtil.camelCaseToHumanFriendly("firstName"));
+ Assert.assertEquals("First Name",
+ SharedUtil.camelCaseToHumanFriendly("first name"));
+ Assert.assertEquals("First Name2",
+ SharedUtil.camelCaseToHumanFriendly("firstName2"));
+ Assert.assertEquals("First",
+ SharedUtil.camelCaseToHumanFriendly("first"));
+ Assert.assertEquals("First",
+ SharedUtil.camelCaseToHumanFriendly("First"));
+ Assert.assertEquals("Some XYZ Abbreviation",
+ SharedUtil.camelCaseToHumanFriendly("SomeXYZAbbreviation"));
+
+ // Javadoc examples
+ Assert.assertEquals("My Bean Container",
+ SharedUtil.camelCaseToHumanFriendly("MyBeanContainer"));
+ Assert.assertEquals("Awesome URL Factory",
+ SharedUtil.camelCaseToHumanFriendly("AwesomeURLFactory"));
+ Assert.assertEquals("Some Uri Action",
+ SharedUtil.camelCaseToHumanFriendly("SomeUriAction"));
+
+ }
+
+ @Test
+ public void splitCamelCase() {
+ assertCamelCaseSplit("firstName", "first", "Name");
+ assertCamelCaseSplit("fooBar", "foo", "Bar");
+ assertCamelCaseSplit("fooBar", "foo", "Bar");
+ assertCamelCaseSplit("fBar", "f", "Bar");
+ assertCamelCaseSplit("FBar", "F", "Bar");
+ assertCamelCaseSplit("MYCdi", "MY", "Cdi");
+ assertCamelCaseSplit("MyCDIUI", "My", "CDIUI");
+ assertCamelCaseSplit("MyCDIUITwo", "My", "CDIUI", "Two");
+ assertCamelCaseSplit("first name", "first", "name");
+
+ }
+
+ private void assertCamelCaseSplit(String camelCaseString, String... parts) {
+ String[] splitParts = SharedUtil.splitCamelCase(camelCaseString);
+ Assert.assertArrayEquals(parts, splitParts);
+ }
}