Procházet zdrojové kódy

Implement escalator pattern for widget (#12645)

Change-Id: Ibdc5a5162ae88e886e74d93f3f75f4ea3c6dab89
tags/7.2.0.beta1
Henrik Paul před 10 roky
rodič
revize
ecb954092f

+ 34
- 14
WebContent/VAADIN/themes/base/escalator/escalator.scss Zobrazit soubor

@@ -31,34 +31,54 @@ $border-color: #aaa;
width: inherit; /* a decent default fallback */
}

.#{$primaryStyleName}-header {
.#{$primaryStyleName}-header,
.#{$primaryStyleName}-body,
.#{$primaryStyleName}-footer {
position: absolute;
top: 0;
left: 0;
width: inherit;
z-index: 10;
}

.#{$primaryStyleName}-header { top: 0; }
.#{$primaryStyleName}-footer { bottom: 0; }

.#{$primaryStyleName}-body {
position: absolute;
z-index: 0;
top: 0;
left: 0;
width: inherit;
.#{$primaryStyleName}-row {
position: absolute;
top: 0;
left: 0;
}
}

.#{$primaryStyleName}-footer {
position: absolute;
bottom: 0;
left: 0;
width: inherit;
.#{$primaryStyleName}-row {
display: block;
.v-ie8 & {
/* IE8 doesn't let table rows be longer than body only with display block. Moar hax. */
float: left;
clear: left;
/*
* The inline style of margin-top from the <tbody> to offset the header's dimension is,
* for some strange reason, inherited into each contained <tr>.
* We need to cancel it:
*/
margin-top: 0;
}

> td, > th {
/* IE8 likes the bgcolor here instead of on the row */
background-color: $background-color;
}
}


.#{$primaryStyleName}-row {
position: absolute;
width: inherit;
top: 0;
left: 0;
background-color: $background-color;
}

.#{$primaryStyleName}-cell {

+ 14
- 14
client/src/com/vaadin/client/ui/grid/ColumnConfiguration.java Zobrazit soubor

@@ -26,29 +26,29 @@ package com.vaadin.client.ui.grid;
public interface ColumnConfiguration {

/**
* Removes columns at a certain offset.
* Removes columns at a certain index.
*
* @param offset
* @param index
* the index of the first column to be removed
* @param numberOfColumns
* the number of rows to remove, starting from the offset
* the number of rows to remove, starting from the index
* @throws IndexOutOfBoundsException
* if any integer in the range
* <code>[offset..(offset+numberOfColumns)]</code> is not an
* <code>[index..(index+numberOfColumns)]</code> is not an
* existing column index.
* @throws IllegalArgumentException
* if <code>numberOfColumns</code> is less than 1.
*/
public void removeColumns(int offset, int numberOfColumns)
public void removeColumns(int index, int numberOfColumns)
throws IndexOutOfBoundsException, IllegalArgumentException;

/**
* Adds columns at a certain offset.
* Adds columns at a certain index.
* <p>
* The new columns will be inserted between the column at the offset, and
* the column before (an offset of 0 means that the columns are inserted at
* the beginning). Therefore, the columns at the offset and afterwards will
* be moved to the right.
* The new columns will be inserted between the column at the index, and the
* column before (an index of 0 means that the columns are inserted at the
* beginning). Therefore, the columns at the index and afterwards will be
* moved to the right.
* <p>
* The contents of the inserted columns will be queried from the respective
* cell renderers in the header, body and footer.
@@ -58,18 +58,18 @@ public interface ColumnConfiguration {
* columns, {@link RowContainer#refreshRows(int, int)} needs to be called as
* appropriate.
*
* @param offset
* @param index
* the index of the column before which new columns are inserted,
* or {@link #getColumnCount()} to add new columns at the end
* @param numberOfColumns
* the number of columns to insert after the <code>offset</code>
* the number of columns to insert after the <code>index</code>
* @throws IndexOutOfBoundsException
* if <code>offset</code> is not an integer in the range
* if <code>index</code> is not an integer in the range
* <code>[0..{@link #getColumnCount()}]</code>
* @throws IllegalArgumentException
* if {@code numberOfColumns} is less than 1.
*/
public void insertColumns(int offset, int numberOfColumns)
public void insertColumns(int index, int numberOfColumns)
throws IndexOutOfBoundsException, IllegalArgumentException;

/**

+ 1709
- 236
client/src/com/vaadin/client/ui/grid/Escalator.java
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 1
- 1
client/src/com/vaadin/client/ui/grid/PositionFunction.java Zobrazit soubor

@@ -58,7 +58,7 @@ interface PositionFunction {
@Override
public void set(Element e, double x, double y) {
e.getStyle().setProperty("webkitTransform",
"translate3d(" + x + "px," + y + "px,0");
"translate3d(" + x + "px," + y + "px,0)");
}
}


+ 362
- 0
client/src/com/vaadin/client/ui/grid/Range.java Zobrazit soubor

@@ -0,0 +1,362 @@
/*
* 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.client.ui.grid;

/**
* 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 7.2
* @author Vaadin Ltd
*/
public final class Range {
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 of all integers 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 of all the integers 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 shares integers.
* <p>
* An empty range never intersects with any other range.
*
* @param other
* the other range to check against
* @return <code>true</code> if this and <code>other</code> have any
* integers in common
*/
public boolean intersects(final Range other) {
if (!isEmpty() && !other.isEmpty()) {
return getStart() < other.getEnd() && other.getStart() < getEnd();
} else {
return false;
}
}

/**
* 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(integer, 0), this };
} else if (integer >= end) {
return new Range[] { this, Range.withLength(integer, 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);
}
}

+ 19
- 19
client/src/com/vaadin/client/ui/grid/RowContainer.java Zobrazit soubor

@@ -49,29 +49,29 @@ public interface RowContainer {
throws IllegalArgumentException;

/**
* Removes rows at a certain offset in the current row container.
* Removes rows at a certain index in the current row container.
*
* @param offset
* @param index
* the index of the first row to be removed
* @param numberOfRows
* the number of rows to remove, starting from the offset
* the number of rows to remove, starting from the index
* @throws IndexOutOfBoundsException
* if any integer number in the range
* <code>[offset..(offset+numberOfRows)]</code> is not an
* existing row index
* <code>[index..(index+numberOfRows)]</code> is not an existing
* row index
* @throws IllegalArgumentException
* if {@code numberOfRows} is less than 1.
*/
public void removeRows(int offset, int numberOfRows)
public void removeRows(int index, int numberOfRows)
throws IndexOutOfBoundsException, IllegalArgumentException;

/**
* Adds rows at a certain offset in this row container.
* Adds rows at a certain index in this row container.
* <p>
* The new rows will be inserted between the row at the offset, and the row
* before (an offset of 0 means that the rows are inserted at the
* beginning). Therefore, the rows currently at the offset and afterwards
* will be moved downwards.
* The new rows will be inserted between the row at the index, and the row
* before (an index of 0 means that the rows are inserted at the beginning).
* Therefore, the rows currently at the index and afterwards will be moved
* downwards.
* <p>
* The contents of the inserted rows will subsequently be queried from the
* cell renderer.
@@ -81,19 +81,19 @@ public interface RowContainer {
* {@link #refreshRows(int, int)} needs to be called for those rows
* separately.
*
* @param offset
* @param index
* the index of the row before which new rows are inserted, or
* {@link #getRowCount()} to add rows at the end
* @param numberOfRows
* the number of rows to insert after the <code>offset</code>
* the number of rows to insert after the <code>index</code>
* @see #setCellRenderer(CellRenderer)
* @throws IndexOutOfBoundsException
* if <code>offset</code> is not an integer in the range
* if <code>index</code> is not an integer in the range
* <code>[0..{@link #getRowCount()}]</code>
* @throws IllegalArgumentException
* if {@code numberOfRows} is less than 1.
*/
public void insertRows(int offset, int numberOfRows)
public void insertRows(int index, int numberOfRows)
throws IndexOutOfBoundsException, IllegalArgumentException;

/**
@@ -102,19 +102,19 @@ public interface RowContainer {
* The data for the refreshed rows are queried from the current cell
* renderer.
*
* @param offset
* @param index
* the index of the first row that will be updated
* @param numberOfRows
* the number of rows to update, starting from the offset
* the number of rows to update, starting from the index
* @see #setCellRenderer(CellRenderer)
* @throws IndexOutOfBoundsException
* if any integer number in the range
* <code>[offset..(offset+numberOfColumns)]</code> is not an
* <code>[index..(index+numberOfColumns)]</code> is not an
* existing column index.
* @throws IllegalArgumentException
* if {@code numberOfRows} is less than 1.
*/
public void refreshRows(int offset, int numberOfRows)
public void refreshRows(int index, int numberOfRows)
throws IndexOutOfBoundsException, IllegalArgumentException;

/**

+ 45
- 0
client/src/com/vaadin/client/ui/grid/ScrollDestination.java Zobrazit soubor

@@ -0,0 +1,45 @@
/*
* 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.client.ui.grid;

/**
* The destinations that are supported in an Escalator when scrolling rows or
* columns into view.
*
* @since 7.2
* @author Vaadin Ltd
*/
public enum ScrollDestination {
/**
* "scrollIntoView" i.e. 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 view port.
*/
START,
/**
* Scrolls so that the element is shown in the middle of the view port.
*/
MIDDLE,
/**
* Scrolls so that the element is shown at the end of the view port.
*/
END
}

+ 102
- 0
client/tests/src/com/vaadin/client/ui/grid/PartitioningTest.java Zobrazit soubor

@@ -0,0 +1,102 @@
/*
* 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.client.ui.grid;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

@SuppressWarnings("static-method")
public class PartitioningTest {

@Test
public void selfRangeTest() {
final Range range = Range.between(0, 10);
final Range[] partitioning = range.partitionWith(range);

assertTrue("before is empty", partitioning[0].isEmpty());
assertTrue("inside is self", partitioning[1].equals(range));
assertTrue("after is empty", partitioning[2].isEmpty());
}

@Test
public void beforeRangeTest() {
final Range beforeRange = Range.between(0, 10);
final Range afterRange = Range.between(10, 20);
final Range[] partitioning = beforeRange.partitionWith(afterRange);

assertTrue("before is self", partitioning[0].equals(beforeRange));
assertTrue("inside is empty", partitioning[1].isEmpty());
assertTrue("after is empty", partitioning[2].isEmpty());
}

@Test
public void afterRangeTest() {
final Range beforeRange = Range.between(0, 10);
final Range afterRange = Range.between(10, 20);
final Range[] partitioning = afterRange.partitionWith(beforeRange);

assertTrue("before is empty", partitioning[0].isEmpty());
assertTrue("inside is empty", partitioning[1].isEmpty());
assertTrue("after is self", partitioning[2].equals(afterRange));
}

@Test
public void beforeAndInsideRangeTest() {
final Range beforeRange = Range.between(0, 10);
final Range afterRange = Range.between(5, 15);
final Range[] partitioning = beforeRange.partitionWith(afterRange);

assertEquals("before", Range.between(0, 5), partitioning[0]);
assertEquals("inside", Range.between(5, 10), partitioning[1]);
assertTrue("after is empty", partitioning[2].isEmpty());
}

@Test
public void insideRangeTest() {
final Range fullRange = Range.between(0, 20);
final Range insideRange = Range.between(5, 15);
final Range[] partitioning = insideRange.partitionWith(fullRange);

assertTrue("before is empty", partitioning[0].isEmpty());
assertEquals("inside", Range.between(5, 15), partitioning[1]);
assertTrue("after is empty", partitioning[2].isEmpty());
}

@Test
public void insideAndBelowTest() {
final Range beforeRange = Range.between(0, 10);
final Range afterRange = Range.between(5, 15);
final Range[] partitioning = afterRange.partitionWith(beforeRange);

assertTrue("before is empty", partitioning[0].isEmpty());
assertEquals("inside", Range.between(5, 10), partitioning[1]);
assertEquals("after", Range.between(10, 15), partitioning[2]);
}

@Test
public void aboveAndBelowTest() {
final Range fullRange = Range.between(0, 20);
final Range insideRange = Range.between(5, 15);
final Range[] partitioning = fullRange.partitionWith(insideRange);

assertEquals("before", Range.between(0, 5), partitioning[0]);
assertEquals("inside", Range.between(5, 15), partitioning[1]);
assertEquals("after", Range.between(15, 20), partitioning[2]);
}
}

+ 212
- 0
client/tests/src/com/vaadin/client/ui/grid/RangeTest.java Zobrazit soubor

@@ -0,0 +1,212 @@
/*
* 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.client.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 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)));
assertTrue("empty range does not intersect with [0..10[", !Range
.between(5, 5).intersects(Range.between(0, 10)));
assertTrue("[0..10[ does not intersect with empty range", !Range
.between(0, 10).intersects(Range.between(5, 5)));
}

@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)));
}
}

+ 151
- 0
uitest/src/com/vaadin/tests/components/grid/GridTest.html Zobrazit soubor

@@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="http://localhost:8888/" />
<title>GridTest</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">GridTest</td></tr>
</thead><tbody>
<tr>
<td>open</td>
<td>/run/com.vaadin.tests.components.grid.GridTest?restartApplication</td>
<td></td>
</tr>
<tr>
<td>verifyText</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VTestGrid[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]</td>
<td>Logical row 0/0</td>
</tr>
<tr>
<td>verifyText</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VTestGrid[0]/domChild[1]/domChild[0]/domChild[1]/domChild[9]/domChild[0]</td>
<td>Logical row 9/9</td>
</tr>
<tr>
<td>verifyTextNotPresent</td>
<td>Logical row 0/10</td>
<td></td>
</tr>
<tr>
<td>verifyTextNotPresent</td>
<td>Logical row 11/11</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VHorizontalLayout[0]/Slot[0]/VTextField[0]</td>
<td>0</td>
</tr>
<tr>
<td>type</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VHorizontalLayout[0]/Slot[1]/VTextField[0]</td>
<td>1</td>
</tr>
<tr>
<td>click</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VHorizontalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td>
<td></td>
</tr>
<tr>
<td>verifyText</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VTestGrid[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]</td>
<td>Logical row 0/10</td>
</tr>
<tr>
<td>type</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VHorizontalLayout[0]/Slot[0]/VTextField[0]</td>
<td>11</td>
</tr>
<tr>
<td>click</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VHorizontalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td>
<td></td>
</tr>
<tr>
<td>verifyText</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VTestGrid[0]/domChild[1]/domChild[0]/domChild[1]/domChild[11]/domChild[0]</td>
<td>Logical row 11/11</td>
</tr>
<tr>
<td>type</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VHorizontalLayout[0]/Slot[0]/VTextField[0]</td>
<td>0</td>
</tr>
<tr>
<td>type</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VHorizontalLayout[0]/Slot[1]/VTextField[0]</td>
<td>100</td>
</tr>
<tr>
<td>click</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VHorizontalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td>
<td></td>
</tr>
<tr>
<td>verifyText</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VTestGrid[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]</td>
<td>Logical row 0/12</td>
</tr>
<tr>
<td>verifyText</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VTestGrid[0]/domChild[1]/domChild[0]/domChild[1]/domChild[10]/domChild[0]</td>
<td>Logical row 17/29</td>
</tr>
<tr>
<td>scroll</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VTestGrid[0]/domChild[0]</td>
<td>1109</td>
</tr>
<tr>
<td>verifyTextPresent</td>
<td>Logical row 56/68</td>
<td></td>
</tr>
<tr>
<td>verifyTextPresent</td>
<td>Logical row 72/84</td>
<td></td>
</tr>
<tr>
<td>scroll</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VTestGrid[0]/domChild[0]</td>
<td>1875</td>
</tr>
<tr>
<td>verifyTextPresent</td>
<td>Logical row 111/</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VHorizontalLayout[0]/Slot[0]/VTextField[0]</td>
<td>111</td>
</tr>
<tr>
<td>type</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VHorizontalLayout[0]/Slot[1]/VTextField[0]</td>
<td>1</td>
</tr>
<tr>
<td>click</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VHorizontalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td>
<td></td>
</tr>
<tr>
<td>verifyText</td>
<td>vaadin=runcomvaadintestscomponentsgridGridTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VTestGrid[0]/domChild[1]/domChild[0]/domChild[1]/domChild[17]/domChild[0]</td>
<td>Logical row 110/144</td>
</tr>
<tr>
<td>verifyTextNotPresent</td>
<td>Logical row 111/</td>
<td></td>
</tr>
</tbody></table>
</body>
</html>

+ 84
- 2
uitest/src/com/vaadin/tests/components/grid/GridTest.java Zobrazit soubor

@@ -21,6 +21,11 @@ import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.components.AbstractTestUI;
import com.vaadin.tests.widgetset.TestingWidgetSet;
import com.vaadin.tests.widgetset.server.grid.TestGrid;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Layout;
import com.vaadin.ui.TextField;

/**
* @since 7.2
@@ -29,8 +34,85 @@ import com.vaadin.tests.widgetset.server.grid.TestGrid;
@Widgetset(TestingWidgetSet.NAME)
public class GridTest extends AbstractTestUI {
@Override
protected void setup(VaadinRequest request) {
addComponent(new TestGrid());
protected void setup(final VaadinRequest request) {
final TestGrid grid = new TestGrid();
addComponent(grid);

final Layout insertRowsLayout = new HorizontalLayout();
final TextField insertRowsOffset = new TextField();
insertRowsLayout.addComponent(insertRowsOffset);
final TextField insertRowsAmount = new TextField();
insertRowsLayout.addComponent(insertRowsAmount);
insertRowsLayout.addComponent(new Button("insert rows",
new Button.ClickListener() {
@Override
@SuppressWarnings("boxing")
public void buttonClick(final ClickEvent event) {
int offset = Integer.valueOf(insertRowsOffset
.getValue());
int amount = Integer.valueOf(insertRowsAmount
.getValue());
grid.insertRows(offset, amount);
}
}));
addComponent(insertRowsLayout);

final Layout removeRowsLayout = new HorizontalLayout();
final TextField removeRowsOffset = new TextField();
removeRowsLayout.addComponent(removeRowsOffset);
final TextField removeRowsAmount = new TextField();
removeRowsLayout.addComponent(removeRowsAmount);
removeRowsLayout.addComponent(new Button("remove rows",
new Button.ClickListener() {
@Override
@SuppressWarnings("boxing")
public void buttonClick(final ClickEvent event) {
int offset = Integer.valueOf(removeRowsOffset
.getValue());
int amount = Integer.valueOf(removeRowsAmount
.getValue());
grid.removeRows(offset, amount);
}
}));
addComponent(removeRowsLayout);

final Layout insertColumnsLayout = new HorizontalLayout();
final TextField insertColumnsOffset = new TextField();
insertColumnsLayout.addComponent(insertColumnsOffset);
final TextField insertColumnsAmount = new TextField();
insertColumnsLayout.addComponent(insertColumnsAmount);
insertColumnsLayout.addComponent(new Button("insert columns",
new Button.ClickListener() {
@Override
@SuppressWarnings("boxing")
public void buttonClick(final ClickEvent event) {
int offset = Integer.valueOf(insertColumnsOffset
.getValue());
int amount = Integer.valueOf(insertColumnsAmount
.getValue());
grid.insertColumns(offset, amount);
}
}));
addComponent(insertColumnsLayout);

final Layout removeColumnsLayout = new HorizontalLayout();
final TextField removeColumnsOffset = new TextField();
removeColumnsLayout.addComponent(removeColumnsOffset);
final TextField removeColumnsAmount = new TextField();
removeColumnsLayout.addComponent(removeColumnsAmount);
removeColumnsLayout.addComponent(new Button("remove columns",
new Button.ClickListener() {
@Override
@SuppressWarnings("boxing")
public void buttonClick(final ClickEvent event) {
int offset = Integer.valueOf(removeColumnsOffset
.getValue());
int amount = Integer.valueOf(removeColumnsAmount
.getValue());
grid.removeColumns(offset, amount);
}
}));
addComponent(removeColumnsLayout);
}

@Override

+ 28
- 0
uitest/src/com/vaadin/tests/widgetset/client/grid/TestGridClientRpc.java Zobrazit soubor

@@ -0,0 +1,28 @@
/*
* 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.tests.widgetset.client.grid;

import com.vaadin.shared.communication.ClientRpc;

public interface TestGridClientRpc extends ClientRpc {
void insertRows(int offset, int amount);

void removeRows(int offset, int amount);

void insertColumns(int offset, int amount);

void removeColumns(int offset, int amount);
}

+ 23
- 0
uitest/src/com/vaadin/tests/widgetset/client/grid/TestGridConnector.java Zobrazit soubor

@@ -28,6 +28,29 @@ public class TestGridConnector extends AbstractComponentConnector {
@Override
protected void init() {
super.init();
registerRpc(TestGridClientRpc.class, new TestGridClientRpc() {
@Override
public void insertRows(int offset, int amount) {
getWidget().getBody().insertRows(offset, amount);
}

@Override
public void removeRows(int offset, int amount) {
getWidget().getBody().removeRows(offset, amount);
}

@Override
public void removeColumns(int offset, int amount) {
getWidget().getColumnConfiguration().removeColumns(offset,
amount);
}

@Override
public void insertColumns(int offset, int amount) {
getWidget().getColumnConfiguration().insertColumns(offset,
amount);
}
});
}

@Override

+ 2
- 1
uitest/src/com/vaadin/tests/widgetset/client/grid/TestGridState.java Zobrazit soubor

@@ -22,7 +22,8 @@ import com.vaadin.shared.AbstractComponentState;
* @author Vaadin Ltd
*/
public class TestGridState extends AbstractComponentState {
public static final String DEFAULT_HEIGHT = "400px";
// public static final String DEFAULT_HEIGHT = "400px";
public static final String DEFAULT_HEIGHT = "405px";

/* TODO: this should be "100%" before setting final. */
public static final String DEFAULT_WIDTH = "800px";

+ 16
- 42
uitest/src/com/vaadin/tests/widgetset/client/grid/VTestGrid.java Zobrazit soubor

@@ -19,10 +19,16 @@ public class VTestGrid extends Composite {

public static class BodyRenderer implements CellRenderer {
private int i = 0;
private int ri = 0;

@Override
public void renderCell(final Cell cell) {
cell.getElement().setInnerText("Cell #" + (i++));
if (cell.getColumn() != 0) {
cell.getElement().setInnerText("Cell #" + (i++));
} else {
cell.getElement().setInnerText(
"Logical row " + cell.getRow() + "/" + (ri++));
}

double c = i * .1;
int r = (int) ((Math.cos(c) + 1) * 128);
@@ -30,8 +36,10 @@ public class VTestGrid extends Composite {
int b = (int) ((Math.cos(c / (Math.PI * 2)) + 1) * 128);
cell.getElement().getStyle()
.setBackgroundColor("rgb(" + r + "," + g + "," + b + ")");
if ((r + g + b) / 3 < 127) {
if ((r * .8 + g * 1.3 + b * .9) / 3 < 127) {
cell.getElement().getStyle().setColor("white");
} else {
cell.getElement().getStyle().clearColor();
}
}
}
@@ -49,12 +57,8 @@ public class VTestGrid extends Composite {

public VTestGrid() {
initWidget(escalator);

final ColumnConfiguration cConf = escalator.getColumnConfiguration();
cConf.insertColumns(0, 1);
cConf.insertColumns(0, 1); // prepend one column
cConf.insertColumns(cConf.getColumnCount(), 1); // append one column
// cConf.insertColumns(cConf.getColumnCount(), 10); // append 10 columns
cConf.insertColumns(cConf.getColumnCount(), 5);

final RowContainer h = escalator.getHeader();
h.setCellRenderer(new HeaderRenderer());
@@ -62,52 +66,22 @@ public class VTestGrid extends Composite {

final RowContainer b = escalator.getBody();
b.setCellRenderer(new BodyRenderer());
b.insertRows(0, 5);
b.insertRows(0, 10);

final RowContainer f = escalator.getFooter();
f.setCellRenderer(new FooterRenderer());
f.insertRows(0, 1);

b.removeRows(3, 2);
// iterative transformations for testing.
// step2();
// step3();
// step4();
// step5();
// step6();

setWidth(TestGridState.DEFAULT_WIDTH);
setHeight(TestGridState.DEFAULT_HEIGHT);
}

private void step2() {
RowContainer b = escalator.getBody();
b.insertRows(0, 5); // prepend five rows
b.insertRows(b.getRowCount(), 5); // append five rows
}

private void step3() {
ColumnConfiguration cConf = escalator.getColumnConfiguration();
cConf.insertColumns(0, 1); // prepend one column
cConf.insertColumns(cConf.getColumnCount(), 1); // append one column
public RowContainer getBody() {
return escalator.getBody();
}

private void step4() {
final ColumnConfiguration cConf = escalator.getColumnConfiguration();
cConf.removeColumns(0, 1);
cConf.removeColumns(1, 1);
cConf.removeColumns(cConf.getColumnCount() - 1, 1);
public ColumnConfiguration getColumnConfiguration() {
return escalator.getColumnConfiguration();
}

private void step5() {
final RowContainer b = escalator.getBody();
b.removeRows(0, 1);
b.removeRows(b.getRowCount() - 1, 1);
}

private void step6() {
RowContainer b = escalator.getBody();
b.refreshRows(0, b.getRowCount());
}

}

+ 21
- 0
uitest/src/com/vaadin/tests/widgetset/server/grid/TestGrid.java Zobrazit soubor

@@ -15,6 +15,7 @@
*/
package com.vaadin.tests.widgetset.server.grid;

import com.vaadin.tests.widgetset.client.grid.TestGridClientRpc;
import com.vaadin.tests.widgetset.client.grid.TestGridState;
import com.vaadin.ui.AbstractComponent;

@@ -32,4 +33,24 @@ public class TestGrid extends AbstractComponent {
protected TestGridState getState() {
return (TestGridState) super.getState();
}

public void insertRows(int offset, int amount) {
rpc().insertRows(offset, amount);
}

public void removeRows(int offset, int amount) {
rpc().removeRows(offset, amount);
}

public void insertColumns(int offset, int amount) {
rpc().insertColumns(offset, amount);
}

public void removeColumns(int offset, int amount) {
rpc().removeColumns(offset, amount);
}

private TestGridClientRpc rpc() {
return getRpcProxy(TestGridClientRpc.class);
}
}

Načítá se…
Zrušit
Uložit