Skip to content

Commit 5da756b

Browse files
authored
Merge pull request #74 from FlowingCode/sort
feat: extend selection semantics to support ordered value along with UI to adjust
2 parents 114f771 + aa94498 commit 5da756b

File tree

8 files changed

+255
-61
lines changed

8 files changed

+255
-61
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,5 @@ rebel.xml
3232
/webpack.generated.js
3333
/package.json
3434
/bin/
35+
/.npmrc
36+
/frontend/generated/vaadin.ts

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@
101101
</exclusions>
102102
</dependency>
103103
<dependency>
104+
<groupId>org.projectlombok</groupId>
105+
<artifactId>lombok</artifactId>
106+
<version>1.18.12</version>
107+
<scope>provided</scope>
108+
</dependency>
109+
<dependency>
104110
<groupId>org.slf4j</groupId>
105111
<artifactId>slf4j-simple</artifactId>
106112
<scope>test</scope>

src/main/java/com/flowingcode/vaadin/addons/twincolgrid/TwinColGrid.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import com.vaadin.flow.data.renderer.TextRenderer;
4545
import com.vaadin.flow.data.selection.SelectionListener;
4646
import com.vaadin.flow.data.value.ValueChangeMode;
47+
import com.vaadin.flow.function.SerializableComparator;
4748
import com.vaadin.flow.function.SerializableFunction;
4849
import com.vaadin.flow.shared.Registration;
4950
import java.io.Serializable;
@@ -52,9 +53,11 @@
5253
import java.util.Comparator;
5354
import java.util.HashSet;
5455
import java.util.LinkedHashSet;
56+
import java.util.List;
5557
import java.util.Objects;
5658
import java.util.Set;
5759
import java.util.function.Consumer;
60+
import java.util.stream.Collector;
5861
import java.util.stream.Collectors;
5962
import java.util.stream.Stream;
6063
import org.apache.commons.lang3.StringUtils;
@@ -64,8 +67,15 @@
6467
public class TwinColGrid<T> extends VerticalLayout
6568
implements HasValue<ValueChangeEvent<Set<T>>, Set<T>>, HasComponents, HasSize {
6669

70+
private static final class GridEx<T> extends Grid<T> {
71+
@Override
72+
protected SerializableComparator<T> createSortingComparator() {
73+
return super.createSortingComparator();
74+
}
75+
}
76+
6777
private static final class TwinColModel<T> implements Serializable {
68-
final Grid<T> grid = new Grid<>();
78+
final GridEx<T> grid = new GridEx<>();
6979
final Label columnLabel = new Label();
7080
final VerticalLayout layout = new VerticalLayout(columnLabel, grid);
7181
HeaderRow headerRow;
@@ -471,7 +481,23 @@ public void setValue(final Set<T> value) {
471481
*/
472482
@Override
473483
public Set<T> getValue() {
474-
return Collections.unmodifiableSet(new LinkedHashSet<>(right.getItems()));
484+
return Collections
485+
.unmodifiableSet(collectValue(Collectors.<T, Set<T>>toCollection(LinkedHashSet::new)));
486+
}
487+
488+
/**
489+
* Collects the current value of this object according to the configured order.
490+
*
491+
* @return the current selection
492+
*/
493+
<C> C collectValue(Collector<T, ?, C> collector) {
494+
Stream<T> stream = right.getItems().stream();
495+
SerializableComparator<T> comparator = right.grid.createSortingComparator();
496+
if (comparator != null) {
497+
return stream.sorted(comparator).collect(collector);
498+
} else {
499+
return stream.collect(collector);
500+
}
475501
}
476502

477503
@Override
@@ -648,4 +674,13 @@ public TwinColGrid<T> selectRowOnClick() {
648674
});
649675
return this;
650676
}
677+
678+
public HasValue<? extends ValueChangeEvent<List<T>>, List<T>> asList() {
679+
return new TwinColGridListAdapter<>(this);
680+
}
681+
682+
@Override
683+
public Set<T> getEmptyValue() {
684+
return Collections.emptySet();
685+
}
651686
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*-
2+
* #%L
3+
* TwinColGrid add-on
4+
* %%
5+
* Copyright (C) 2017 - 2021 Flowing Code
6+
* %%
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
* #L%
19+
*/
20+
package com.flowingcode.vaadin.addons.twincolgrid;
21+
22+
import com.vaadin.flow.component.HasValue;
23+
import com.vaadin.flow.component.HasValue.ValueChangeEvent;
24+
import com.vaadin.flow.shared.Registration;
25+
import java.util.ArrayList;
26+
import java.util.Collections;
27+
import java.util.LinkedHashSet;
28+
import java.util.List;
29+
import java.util.stream.Collectors;
30+
import lombok.AllArgsConstructor;
31+
import lombok.Getter;
32+
import lombok.NonNull;
33+
import lombok.RequiredArgsConstructor;
34+
import lombok.experimental.Delegate;
35+
36+
/**
37+
* Expose {@link TwinColGrid} as a {@code HasValue} of {@code List}
38+
*
39+
* @author Javier Godoy
40+
*/
41+
@SuppressWarnings("serial")
42+
@RequiredArgsConstructor
43+
class TwinColGridListAdapter<T> implements HasValue<ValueChangeEvent<List<T>>, List<T>> {
44+
45+
private interface IDelegate {
46+
boolean isEmpty();
47+
48+
void clear();
49+
50+
void setReadOnly(boolean readOnly);
51+
52+
boolean isReadOnly();
53+
54+
void setRequiredIndicatorVisible(boolean requiredIndicatorVisible);
55+
56+
boolean isRequiredIndicatorVisible();
57+
}
58+
59+
@Getter
60+
@AllArgsConstructor
61+
private final class ValueChangeEventImpl implements ValueChangeEvent<List<T>> {
62+
63+
boolean isFromClient;
64+
List<T> value;
65+
66+
@Override
67+
public HasValue<?, List<T>> getHasValue() {
68+
return TwinColGridListAdapter.this;
69+
}
70+
71+
@Override
72+
public List<T> getOldValue() {
73+
return null;
74+
}
75+
76+
}
77+
78+
@NonNull
79+
@Delegate(types = IDelegate.class)
80+
private final TwinColGrid<T> delegate;
81+
82+
@Override
83+
public void setValue(List<T> value) {
84+
delegate.setValue(new LinkedHashSet<>(value));
85+
}
86+
87+
@Override
88+
public List<T> getValue() {
89+
return Collections.unmodifiableList(delegate.collectValue(Collectors.toList()));
90+
}
91+
92+
@Override
93+
public Registration addValueChangeListener(
94+
ValueChangeListener<? super ValueChangeEvent<List<T>>> listener) {
95+
96+
List<Registration> registrations = new ArrayList<>();
97+
98+
registrations.add(delegate.addValueChangeListener(ev -> {
99+
List<T> value = new ArrayList<>(ev.getValue());
100+
ValueChangeEvent<List<T>> listEvent;
101+
listEvent = new ValueChangeEventImpl(ev.isFromClient(), new ArrayList<>(value));
102+
listener.valueChanged(listEvent);
103+
}));
104+
105+
// sorting the grid changes its value under List::equals
106+
registrations.add(delegate.getRightGrid().addSortListener(ev -> {
107+
List<T> value = getValue();
108+
ValueChangeEvent<List<T>> listEvent;
109+
listEvent = new ValueChangeEventImpl(ev.isFromClient(), value);
110+
listener.valueChanged(listEvent);
111+
}));
112+
113+
return () -> registrations.forEach(Registration::remove);
114+
}
115+
116+
@Override
117+
public List<T> getEmptyValue() {
118+
return Collections.emptyList();
119+
}
120+
121+
}

src/test/java/com/flowingcode/vaadin/addons/twincolgrid/BoundDemo.java

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,50 +20,67 @@
2020

2121
package com.flowingcode.vaadin.addons.twincolgrid;
2222

23+
import com.vaadin.flow.component.button.Button;
24+
import com.vaadin.flow.component.notification.Notification;
25+
import com.vaadin.flow.component.notification.Notification.Position;
2326
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
2427
import com.vaadin.flow.data.binder.Binder;
2528
import java.util.ArrayList;
26-
import java.util.HashSet;
29+
import java.util.Comparator;
2730
import java.util.List;
28-
import java.util.Set;
2931

3032
@SuppressWarnings("serial")
3133
public class BoundDemo extends VerticalLayout {
3234

35+
private final List<Book> selectedBooks = new ArrayList<>();
36+
private final List<Book> availableBooks = new ArrayList<>();
37+
3338
public BoundDemo() {
34-
final Set<Book> selectedBooks = new HashSet<>();
35-
selectedBooks.add(new Book("1478375108", "Vaadin Recipes"));
36-
selectedBooks.add(new Book("9789526800677", "Book of Vaadin: Volume 2 "));
39+
initializeData();
3740
final Library library = new Library("Public Library", selectedBooks);
3841

39-
final List<Book> availableBooks = new ArrayList<>();
40-
availableBooks.add(new Book("1478375108", "Vaadin Recipes"));
41-
availableBooks.add(new Book("9781849515221", "Learning Vaadin"));
42-
availableBooks.add(
43-
new Book("9781782162261", "Vaadin 7 UI Design By Example: Beginner�s Guide"));
44-
availableBooks.add(new Book("9781849518802", "Vaadin 7 Cookbook"));
45-
availableBooks.add(new Book("9526800605", "Book of Vaadin: 7th Edition, 1st Revision"));
46-
availableBooks.add(new Book("9789526800677", "Book of Vaadin: Volume 2 "));
47-
availableBooks.add(new Book("9529267533", "Book of Vaadin"));
48-
availableBooks.add(new Book("1782169776", "Learning Vaadin 7, Second Edition"));
49-
5042
// Binded
51-
final TwinColGrid<Book> bindedTwinColGrid =
43+
final TwinColGrid<Book> twinColGrid =
5244
new TwinColGrid<>(
5345
availableBooks, "TwinColGrid demo with Binder and row select without checkbox")
54-
.addColumn(Book::getIsbn, "ISBN")
55-
.addColumn(Book::getTitle, "Title")
46+
.addSortableColumn(Book::getIsbn, Comparator.comparing(Book::getIsbn), "ISBN")
47+
.addSortableColumn(Book::getTitle, Comparator.comparing(Book::getTitle), "Title")
5648
.withLeftColumnCaption("Available books")
5749
.withRightColumnCaption("Added books")
5850
.withoutRemoveAllButton()
5951
.withSizeFull()
6052
.selectRowOnClick();
6153

6254
final Binder<Library> binder = new Binder<>();
63-
binder.bind(bindedTwinColGrid, Library::getBooks, Library::setBooks);
55+
binder.bind(twinColGrid.asList(), Library::getBooks, Library::setBooks);
6456
binder.setBean(library);
6557

66-
add(bindedTwinColGrid);
58+
add(twinColGrid);
59+
add(new Button("Get values", ev -> {
60+
binder.getBean().getBooks()
61+
.forEach(book -> Notification.show(book.getTitle(), 3000, Position.BOTTOM_START));
62+
}));
63+
64+
add(new Button("Clear TwinColGrid", ev -> {
65+
twinColGrid.clear();
66+
}));
67+
6768
setSizeFull();
6869
}
70+
71+
private void initializeData() {
72+
selectedBooks.add(new Book("1478375108", "Vaadin Recipes"));
73+
selectedBooks.add(new Book("9789526800677", "Book of Vaadin: Volume 2 "));
74+
75+
76+
availableBooks.add(new Book("1478375108", "Vaadin Recipes"));
77+
availableBooks.add(new Book("9781849515221", "Learning Vaadin"));
78+
availableBooks
79+
.add(new Book("9781782162261", "Vaadin 7 UI Design By Example: Beginner\u2019s Guide"));
80+
availableBooks.add(new Book("9781849518802", "Vaadin 7 Cookbook"));
81+
availableBooks.add(new Book("9526800605", "Book of Vaadin: 7th Edition, 1st Revision"));
82+
availableBooks.add(new Book("9789526800677", "Book of Vaadin: Volume 2 "));
83+
availableBooks.add(new Book("9529267533", "Book of Vaadin"));
84+
availableBooks.add(new Book("1782169776", "Learning Vaadin 7, Second Edition"));
85+
}
6986
}

src/test/java/com/flowingcode/vaadin/addons/twincolgrid/DragAndDropDemo.java

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,13 @@
3030

3131
@SuppressWarnings("serial")
3232
public class DragAndDropDemo extends VerticalLayout {
33-
public DragAndDropDemo() {
34-
final Set<Book> selectedBooks = new HashSet<>();
35-
selectedBooks.add(new Book("1478375108", "Vaadin Recipes"));
36-
selectedBooks.add(new Book("9789526800677", "Book of Vaadin: Volume 2 "));
3733

38-
final List<Book> availableBooks = new ArrayList<>();
39-
availableBooks.add(new Book("1478375108", "Vaadin Recipes"));
40-
availableBooks.add(new Book("9781849515221", "Learning Vaadin"));
41-
availableBooks.add(
42-
new Book("9781782162261", "Vaadin 7 UI Design By Example: Beginner�s Guide"));
43-
availableBooks.add(new Book("9781849518802", "Vaadin 7 Cookbook"));
44-
availableBooks.add(new Book("9526800605", "Book of Vaadin: 7th Edition, 1st Revision"));
45-
availableBooks.add(new Book("9789526800677", "Book of Vaadin: Volume 2 "));
46-
availableBooks.add(new Book("9529267533", "Book of Vaadin"));
47-
availableBooks.add(new Book("1782169776", "Learning Vaadin 7, Second Edition"));
34+
private final Set<Book> selectedBooks = new HashSet<>();
35+
private final List<Book> availableBooks = new ArrayList<>();
36+
37+
public DragAndDropDemo() {
38+
initializeData();
4839

49-
// Drag and drop
5040
final TwinColGrid<Book> twinColGrid =
5141
new TwinColGrid<>(availableBooks, "TwinColGrid demo with drag and drop support")
5242
.addSortableColumn(Book::getIsbn, Comparator.comparing(Book::getIsbn), "ISBN")
@@ -67,4 +57,20 @@ public DragAndDropDemo() {
6757
add(twinColGrid, countLabel);
6858
setSizeFull();
6959
}
60+
61+
private void initializeData() {
62+
selectedBooks.add(new Book("1478375108", "Vaadin Recipes"));
63+
selectedBooks.add(new Book("9789526800677", "Book of Vaadin: Volume 2 "));
64+
65+
66+
availableBooks.add(new Book("1478375108", "Vaadin Recipes"));
67+
availableBooks.add(new Book("9781849515221", "Learning Vaadin"));
68+
availableBooks
69+
.add(new Book("9781782162261", "Vaadin 7 UI Design By Example: Beginner\u2019s Guide"));
70+
availableBooks.add(new Book("9781849518802", "Vaadin 7 Cookbook"));
71+
availableBooks.add(new Book("9526800605", "Book of Vaadin: 7th Edition, 1st Revision"));
72+
availableBooks.add(new Book("9789526800677", "Book of Vaadin: Volume 2 "));
73+
availableBooks.add(new Book("9529267533", "Book of Vaadin"));
74+
availableBooks.add(new Book("1782169776", "Learning Vaadin 7, Second Edition"));
75+
}
7076
}

0 commit comments

Comments
 (0)