Skip to content

Commit

Permalink
Update NativeSelect to use DataSource, extend AbstractListing
Browse files Browse the repository at this point in the history
Selection and focus/blur support not yet implemented.

Change-Id: I76752084442216e60055d93367475c1c0a612787
  • Loading branch information
jdahlstrom authored and Ilia Motornyi committed Sep 12, 2016
1 parent 0b4ef82 commit f5104e3
Show file tree
Hide file tree
Showing 8 changed files with 452 additions and 6 deletions.
34 changes: 34 additions & 0 deletions client/src/main/java/com/vaadin/client/ui/VNativeSelect.java
@@ -0,0 +1,34 @@
/*
* 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 com.google.gwt.user.client.ui.ListBox;
import com.vaadin.shared.ui.nativeselect.NativeSelectState;

/**
* The client-side widget for the {@code NativeSelect} component.
*
* @author Vaadin Ltd.
*/
public class VNativeSelect extends ListBox {

/**
* Creates a new {@code VNativeSelect} instance.
*/
public VNativeSelect() {
setStyleName(NativeSelectState.STYLE_NAME);
}
}
@@ -0,0 +1,102 @@
/*
* 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.nativeselect;

import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.connectors.AbstractListingConnector;
import com.vaadin.client.data.DataSource;
import com.vaadin.client.ui.VNativeSelect;
import com.vaadin.shared.Range;
import com.vaadin.shared.Registration;
import com.vaadin.shared.data.selection.SelectionModel;
import com.vaadin.shared.ui.Connect;

import elemental.json.JsonObject;

/**
* The client-side connector for the {@code NativeSelect} component.
*
* @author Vaadin Ltd.
*
* @see com.vaadin.ui.NativeSelect
* @see com.vaadin.client.ui.VNativeSelect
*
* @since 8.0
*/
@Connect(com.vaadin.ui.NativeSelect.class)
public class NativeSelectConnector extends
AbstractListingConnector<SelectionModel<?>> {

private Registration dataChangeRegistration;

@Override
public VNativeSelect getWidget() {
return (VNativeSelect) super.getWidget();
}

@Override
public void setDataSource(DataSource<JsonObject> dataSource) {
if (dataChangeRegistration != null) {
dataChangeRegistration.remove();
}
dataChangeRegistration = dataSource.addDataChangeHandler(
this::onDataChange);
super.setDataSource(dataSource);
}

@OnStateChange("readOnly")
@SuppressWarnings("deprecation")
void updateWidgetReadOnly() {
getWidget().setEnabled(isEnabled() && !isReadOnly());
}

/**
* A data change handler registered to the data source. Updates the data
* items and selection status when the data source notifies of new changes
* from the server side.
*
* @param range
* the new range of data items
*/
private void onDataChange(Range range) {
assert range.getStart() == 0 && range.getEnd() == getDataSource()
.size() : "NativeSelect only supports full updates, but got range "
+ range;

final VNativeSelect select = getWidget();
final int itemCount = select.getItemCount();

for (int i = range.getStart(); i < range.getEnd(); i++) {

final JsonObject row = getDataSource().getRow(i);

if (i < itemCount) {
// Reuse and update an existing item
select.setItemText(i, getRowData(row).asString());
select.setValue(i, getRowKey(row));
} else {
// Add new items if the new dataset is larger than the old
select.addItem(getRowData(row).asString(), getRowKey(row));
}
}

for (int i = select.getItemCount() - 1; i >= range.getEnd(); i--) {
// Remove extra items if the new dataset is smaller than the old
select.removeItem(i);
}
}
}
114 changes: 114 additions & 0 deletions server/src/main/java/com/vaadin/ui/NativeSelect.java
@@ -0,0 +1,114 @@
/*
* 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.ui;

import java.util.Collection;
import java.util.Collections;
import java.util.Set;

import com.vaadin.server.data.DataSource;
import com.vaadin.shared.data.DataCommunicatorConstants;
import com.vaadin.shared.data.selection.SelectionModel;
import com.vaadin.shared.ui.nativeselect.NativeSelectState;

/**
* A simple drop-down select component. Represented on the client side by a
* "native" HTML {@code <select>} element. Lacks advanced features such as lazy
* loading, filtering, and adding new items.
*
* @author Vaadin Ltd.
*
* @param <T>
* the data item type
*
* @see com.vaadin.ui.ComboBox
*/
public class NativeSelect<T> extends AbstractListing<T, SelectionModel<T>> {

/**
* Creates a new {@code NativeSelect} with an empty caption and no items.
*/
public NativeSelect() {
addDataGenerator((item, json) -> json.put(
DataCommunicatorConstants.DATA, String.valueOf(item)));

setSelectionModel(new SelectionModel<T>() {

@Override
public Set<T> getSelectedItems() {
return Collections.emptySet();
}

@Override
public void select(T item) {
}

@Override
public void deselect(T item) {
}
});
}

/**
* Creates a new {@code NativeSelect} with the given caption and no items.
*
* @param caption
* the component caption to set, null for no caption
*/
public NativeSelect(String caption) {
this();
setCaption(caption);
}

/**
* Creates a new {@code NativeSelect} with the given caption, containing the
* data items in the given collection.
*
* @param caption
* the component caption to set, null for no caption
* @param items
* the data items to use, not null
*/
public NativeSelect(String caption, Collection<T> items) {
this(caption);
setItems(items);
}

/**
* Creates a new {@code NativeSelect} with the given caption, using the
* given {@code DataSource} as the source of data items.
*
* @param caption
* the component caption to set, null for no caption
* @param dataSource
* the source of data items to use, not null
*/
public NativeSelect(String caption, DataSource<T> dataSource) {
this(caption);
setDataSource(dataSource);
}

@Override
protected NativeSelectState getState() {
return getState(true);
}

@Override
protected NativeSelectState getState(boolean markAsDirty) {
return (NativeSelectState) super.getState(markAsDirty);
}
}
@@ -0,0 +1,37 @@
/*
* 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.shared.ui.nativeselect;

import com.vaadin.shared.ui.AbstractSingleSelectState;

/**
* Shared state for {@code NativeSelect}.
*
* @author Vaadin Ltd.
*
* @since 8.0
*/
public class NativeSelectState extends AbstractSingleSelectState {

/**
* The default primary style name for {@code NativeSelect}.
*/
public static final String STYLE_NAME = "v-nativeselect";

{
primaryStyleName = STYLE_NAME;
}
}
@@ -0,0 +1,75 @@
/*
* 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.testbench.customelements;

import java.util.List;

import org.openqa.selenium.support.ui.Select;

import com.vaadin.testbench.TestBenchElement;
import com.vaadin.testbench.elements.AbstractSelectElement;
import com.vaadin.testbench.elementsbase.ServerClass;

@ServerClass("com.vaadin.ui.NativeSelect")
public class NativeSelectElement extends AbstractSelectElement {
private Select selectElement;

@Override
protected void init() {
super.init();
selectElement = new Select(this);
}

public List<TestBenchElement> getOptions() {
return wrapElements(selectElement.getOptions(), getCommandExecutor());
}

public void selectByText(String text) throws ReadOnlyException {
if (isReadOnly()) {
throw new ReadOnlyException();
}
selectElement.selectByVisibleText(text);
waitForVaadin();
}

/**
* Clear operation is not supported for Native Select. This operation has no
* effect on Native Select element.
*/
@Override
public void clear() {
super.clear();
}

/**
* Return value of the selected item in the native select element
*
* @return value of the selected item in the native select element
*/
public String getValue() {
return selectElement.getFirstSelectedOption().getText();
}

/**
* Select item of the native select element with the specified value
*
* @param chars
* value of the native select item will be selected
*/
public void setValue(CharSequence chars) throws ReadOnlyException {
selectByText((String) chars);
}
}

0 comments on commit f5104e3

Please sign in to comment.