-
Notifications
You must be signed in to change notification settings - Fork 728
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ListSelect with new data binding API
No single select mode for list select. Based on AbstractMultiSelect. Removes feature for adding new items. Change-Id: I9a92aaf1f3d338a3b05c3aa4048f9db496dacd1d
- Loading branch information
Pekka Hyvönen
authored and
Denis Anisimov
committed
Sep 28, 2016
1 parent
96119ab
commit c4b17ca
Showing
15 changed files
with
963 additions
and
322 deletions.
There are no files selected for viewing
263 changes: 263 additions & 0 deletions
263
client/src/main/java/com/vaadin/client/ui/VListSelect.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,263 @@ | ||
/* | ||
* Copyright 2000-2016 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; | ||
|
||
import java.util.ArrayList; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.Set; | ||
import java.util.function.BiConsumer; | ||
|
||
import com.google.gwt.event.dom.client.ClickEvent; | ||
import com.google.gwt.event.dom.client.ClickHandler; | ||
import com.google.gwt.user.client.ui.Composite; | ||
import com.google.gwt.user.client.ui.FlowPanel; | ||
import com.google.gwt.user.client.ui.HasEnabled; | ||
import com.google.gwt.user.client.ui.ListBox; | ||
import com.vaadin.client.FastStringSet; | ||
import com.vaadin.client.Focusable; | ||
import com.vaadin.client.connectors.AbstractMultiSelectConnector.MultiSelectWidget; | ||
import com.vaadin.shared.Registration; | ||
|
||
import elemental.json.JsonObject; | ||
|
||
/** | ||
* A simple list select for selecting multiple items. | ||
* | ||
* @author Vaadin Ltd | ||
*/ | ||
public class VListSelect extends Composite implements ClickHandler, Field, | ||
Focusable, HasEnabled, MultiSelectWidget { | ||
|
||
private List<BiConsumer<Set<String>, Set<String>>> selectionChangeListeners = new ArrayList<>(); | ||
|
||
/** Container for select. Kept for DOM backwards compatibility. */ | ||
protected final FlowPanel container; | ||
/** The select component. */ | ||
protected final ListBox select; | ||
|
||
private boolean enabled; | ||
private boolean readOnly; | ||
private FastStringSet selectedItemKeys = FastStringSet.create(); | ||
|
||
/** | ||
* Constructs a simple ListSelect widget in multiselect mode. | ||
*/ | ||
public VListSelect() { | ||
container = new FlowPanel(); | ||
initWidget(container); | ||
|
||
select = new ListBox(); | ||
select.setMultipleSelect(true); | ||
select.addClickHandler(this); | ||
|
||
container.add(select); | ||
|
||
updateEnabledState(); | ||
} | ||
|
||
/** | ||
* Sets the number of visible items for the list select. | ||
* | ||
* @param rows | ||
* the number of items to show | ||
* @see ListBox#setVisibleItemCount(int) | ||
*/ | ||
public void setRows(int rows) { | ||
if (select.getVisibleItemCount() != rows) { | ||
select.setVisibleItemCount(rows); | ||
} | ||
} | ||
|
||
/** | ||
* Returns the number of visible items for the list select. | ||
* | ||
* @return the number of items to show | ||
* @see ListBox#setVisibleItemCount(int) | ||
*/ | ||
public int getRows() { | ||
return select.getVisibleItemCount(); | ||
} | ||
|
||
@Override | ||
public Registration addSelectionChangeListener( | ||
BiConsumer<Set<String>, Set<String>> listener) { | ||
Objects.nonNull(listener); | ||
selectionChangeListeners.add(listener); | ||
return (Registration) () -> selectionChangeListeners.remove(listener); | ||
} | ||
|
||
@Override | ||
public void setStyleName(String style) { | ||
super.setStyleName(style); | ||
updateStyleNames(); | ||
} | ||
|
||
@Override | ||
public void setStylePrimaryName(String style) { | ||
super.setStylePrimaryName(style); | ||
updateStyleNames(); | ||
} | ||
|
||
/** Update the style names for container & select. */ | ||
protected void updateStyleNames() { | ||
container.setStyleName(getStylePrimaryName()); | ||
select.setStyleName(getStylePrimaryName() + "-select"); | ||
} | ||
|
||
@Override | ||
public void setItems(List<JsonObject> items) { | ||
selectedItemKeys = FastStringSet.create(); | ||
for (int i = 0; i < items.size(); i++) { | ||
final JsonObject item = items.get(i); | ||
// reuse existing option if possible | ||
final String key = MultiSelectWidget.getKey(item); | ||
if (i < select.getItemCount()) { | ||
select.setItemText(i, MultiSelectWidget.getCaption(item)); | ||
select.setValue(i, key); | ||
} else { | ||
select.addItem(MultiSelectWidget.getCaption(item), key); | ||
} | ||
final boolean selected = MultiSelectWidget.isSelected(item); | ||
select.setItemSelected(i, selected); | ||
if (selected) { | ||
selectedItemKeys.add(key); | ||
} | ||
} | ||
|
||
// remove extra | ||
for (int i = select.getItemCount() - 1; i >= items.size(); i--) { | ||
select.removeItem(i); | ||
} | ||
} | ||
|
||
/** | ||
* Gets the currently selected item values. | ||
* | ||
* @return the currently selected item keys | ||
*/ | ||
protected FastStringSet getSelectedItems() { | ||
final FastStringSet selectedItemKeys = FastStringSet.create(); | ||
for (int i = 0; i < select.getItemCount(); i++) { | ||
if (select.isItemSelected(i)) { | ||
selectedItemKeys.add(select.getValue(i)); | ||
} | ||
} | ||
return selectedItemKeys; | ||
} | ||
|
||
@Override | ||
public void onClick(ClickEvent event) { | ||
if (event.getSource() == select) { | ||
// selection can change by adding and at the same time removing | ||
// previous keys, or by just adding (e.g. when modifier keys are | ||
// pressed) | ||
final Set<String> newSelectedItemKeys = new HashSet<>(); | ||
final Set<String> removedItemKeys = new HashSet<>(); | ||
for (int i = 0; i < select.getItemCount(); i++) { | ||
String key = select.getValue(i); | ||
boolean selected = select.isItemSelected(i); | ||
boolean wasSelected = selectedItemKeys.contains(key); | ||
if (selected && !wasSelected) { | ||
newSelectedItemKeys.add(key); | ||
selectedItemKeys.add(key); | ||
} else if (!selected && wasSelected) { | ||
removedItemKeys.add(key); | ||
selectedItemKeys.remove(key); | ||
} | ||
} | ||
selectionChangeListeners.forEach( | ||
l -> l.accept(newSelectedItemKeys, removedItemKeys)); | ||
} | ||
} | ||
|
||
@Override | ||
public void setHeight(String height) { | ||
select.setHeight(height); | ||
super.setHeight(height); | ||
} | ||
|
||
@Override | ||
public void setWidth(String width) { | ||
select.setWidth(width); | ||
super.setWidth(width); | ||
} | ||
|
||
/** | ||
* Sets the tab index. | ||
* | ||
* @param tabIndex | ||
* the tab index to set | ||
*/ | ||
public void setTabIndex(int tabIndex) { | ||
select.setTabIndex(tabIndex); | ||
} | ||
|
||
/** | ||
* Gets the tab index. | ||
* | ||
* @return the tab index | ||
*/ | ||
public int getTabIndex() { | ||
return select.getTabIndex(); | ||
} | ||
|
||
/** | ||
* Sets this select as read only, meaning selection cannot be changed. | ||
* | ||
* @param readOnly | ||
* {@code true} for read only, {@code false} for not read only | ||
*/ | ||
public void setReadOnly(boolean readOnly) { | ||
if (this.readOnly != readOnly) { | ||
this.readOnly = readOnly; | ||
updateEnabledState(); | ||
} | ||
} | ||
|
||
/** | ||
* Returns {@code true} if this select is in read only mode, {@code false} | ||
* if not. | ||
* | ||
* @return {@code true} for read only, {@code false} for not read only | ||
*/ | ||
public boolean isReadOnly() { | ||
return readOnly; | ||
} | ||
|
||
@Override | ||
public void setEnabled(boolean enabled) { | ||
if (this.enabled != enabled) { | ||
this.enabled = enabled; | ||
updateEnabledState(); | ||
} | ||
} | ||
|
||
@Override | ||
public boolean isEnabled() { | ||
return enabled; | ||
} | ||
|
||
private void updateEnabledState() { | ||
select.setEnabled(isEnabled() && !isReadOnly()); | ||
} | ||
|
||
@Override | ||
public void focus() { | ||
select.setFocus(true); | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
client/src/main/java/com/vaadin/client/ui/listselect/ListSelectConnector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* Copyright 2000-2016 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.listselect; | ||
|
||
import com.vaadin.client.annotations.OnStateChange; | ||
import com.vaadin.client.connectors.AbstractMultiSelectConnector; | ||
import com.vaadin.client.ui.VListSelect; | ||
import com.vaadin.shared.ui.Connect; | ||
import com.vaadin.shared.ui.listselect.ListSelectState; | ||
import com.vaadin.ui.ListSelect; | ||
|
||
/** | ||
* Client side connector for {@link ListSelect} component. | ||
* | ||
* @author Vaadin Ltd | ||
* | ||
*/ | ||
@Connect(ListSelect.class) | ||
public class ListSelectConnector extends AbstractMultiSelectConnector { | ||
|
||
@Override | ||
public VListSelect getWidget() { | ||
return (VListSelect) super.getWidget(); | ||
} | ||
|
||
@Override | ||
public MultiSelectWidget getMultiSelectWidget() { | ||
return getWidget(); | ||
} | ||
|
||
@Override | ||
public ListSelectState getState() { | ||
return (ListSelectState) super.getState(); | ||
} | ||
|
||
@OnStateChange("readOnly") | ||
void updateReadOnly() { | ||
getWidget().setReadOnly(isReadOnly()); | ||
} | ||
|
||
} |
Oops, something went wrong.