diff options
author | Denis Anisimov <denis@vaadin.com> | 2016-10-30 18:11:21 +0200 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2016-10-31 14:45:13 +0000 |
commit | 287614dbabc4ec8f2e72f56067312ad47ce46f5d (patch) | |
tree | 2f4811c2de5dd2aa4cf10b3a50b6ac484764f866 /client/src | |
parent | ee47a94e17aadae18fbee6ad804e35ab12446df5 (diff) | |
download | vaadin-framework-287614dbabc4ec8f2e72f56067312ad47ce46f5d.tar.gz vaadin-framework-287614dbabc4ec8f2e72f56067312ad47ce46f5d.zip |
Implement focus/blur events for RadioButtonGroup.
Fixes vaadin/framework8-issues#333
Change-Id: I55f5d6a0cd690f2c0b5e757318a5f528a67ef34e
Diffstat (limited to 'client/src')
4 files changed, 82 insertions, 87 deletions
diff --git a/client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java b/client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java index 6ba7ea75d5..d6b8c3ade9 100644 --- a/client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java +++ b/client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java @@ -42,8 +42,8 @@ import elemental.json.JsonObject; * @author Vaadin Ltd. * @since 8.0 */ -public class VCheckBoxGroup extends FocusableFlowPanelComposite implements - Field, ClickHandler, com.vaadin.client.Focusable, HasEnabled { +public class VCheckBoxGroup extends FocusableFlowPanelComposite + implements Field, ClickHandler, HasEnabled { public static final String CLASSNAME = "v-select-optiongroup"; public static final String CLASSNAME_OPTION = "v-select-option"; @@ -99,7 +99,7 @@ public class VCheckBoxGroup extends FocusableFlowPanelComposite implements } private void updateItem(VCheckBox widget, JsonObject item, - boolean requireInitializations) { + boolean requireInitialization) { String itemHtml = item .getString(ListingJsonConstants.JSONKEY_ITEM_VALUE); if (!isHtmlContentAllowed()) { @@ -117,7 +117,7 @@ public class VCheckBoxGroup extends FocusableFlowPanelComposite implements item.getBoolean(ListingJsonConstants.JSONKEY_ITEM_SELECTED)); setOptionEnabled(widget, item); - if (requireInitializations) { + if (requireInitialization) { widget.addStyleName(CLASSNAME_OPTION); widget.addClickHandler(this); getWidget().add(widget); @@ -168,11 +168,6 @@ public class VCheckBoxGroup extends FocusableFlowPanelComposite implements checkBox.setEnabled(enabled); } - @Override - public void focus() { - getWidget().focus(); - } - public boolean isHtmlContentAllowed() { return htmlContentAllowed; } diff --git a/client/src/main/java/com/vaadin/client/ui/VRadioButtonGroup.java b/client/src/main/java/com/vaadin/client/ui/VRadioButtonGroup.java index fd4d7cf98a..fe5afea620 100644 --- a/client/src/main/java/com/vaadin/client/ui/VRadioButtonGroup.java +++ b/client/src/main/java/com/vaadin/client/ui/VRadioButtonGroup.java @@ -18,7 +18,6 @@ package com.vaadin.client.ui; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.function.Consumer; @@ -27,17 +26,14 @@ import com.google.gwt.aria.client.Roles; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.FocusWidget; -import com.google.gwt.user.client.ui.Focusable; import com.google.gwt.user.client.ui.HasEnabled; -import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.RadioButton; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.BrowserInfo; import com.vaadin.client.WidgetUtil; +import com.vaadin.client.widgets.FocusableFlowPanelComposite; import com.vaadin.shared.Registration; import com.vaadin.shared.data.DataCommunicatorConstants; import com.vaadin.shared.ui.ListingJsonConstants; @@ -50,8 +46,8 @@ import elemental.json.JsonObject; * @author Vaadin Ltd. * @since 8.0 */ -public class VRadioButtonGroup extends Composite implements Field, ClickHandler, - com.vaadin.client.Focusable, HasEnabled { +public class VRadioButtonGroup extends FocusableFlowPanelComposite + implements Field, ClickHandler, HasEnabled { public static final String CLASSNAME = "v-select-optiongroup"; public static final String CLASSNAME_OPTION = "v-select-option"; @@ -64,14 +60,6 @@ public class VRadioButtonGroup extends Composite implements Field, ClickHandler, */ public ApplicationConnection client; - /** - * Widget holding the different options (e.g. ListBox or Panel for radio - * buttons) (optional, fallbacks to container Panel) - * <p> - * For internal use only. May be removed or replaced in the future. - */ - public Panel optionsContainer; - private boolean htmlContentAllowed = false; private boolean enabled; @@ -81,9 +69,7 @@ public class VRadioButtonGroup extends Composite implements Field, ClickHandler, public VRadioButtonGroup() { groupId = DOM.createUniqueId(); - optionsContainer = new FlowPanel(); - initWidget(optionsContainer); - optionsContainer.setStyleName(CLASSNAME); + getWidget().setStyleName(CLASSNAME); optionsToItems = new HashMap<>(); keyToOptions = new HashMap<>(); selectionChangeListeners = new ArrayList<>(); @@ -93,47 +79,68 @@ public class VRadioButtonGroup extends Composite implements Field, ClickHandler, * Build all the options */ public void buildOptions(List<JsonObject> items) { - /* - * In order to retain focus, we need to update values rather than - * recreate panel from scratch (#10451). However, the panel will be - * rebuilt (losing focus) if number of elements or their order is - * changed. - */ - Roles.getRadiogroupRole().set(getElement()); - optionsContainer.clear(); - optionsToItems.clear(); - keyToOptions.clear(); - for (JsonObject item : items) { - String itemHtml = item - .getString(ListingJsonConstants.JSONKEY_ITEM_VALUE); - if (!isHtmlContentAllowed()) { - itemHtml = WidgetUtil.escapeHTML(itemHtml); + int i = 0; + int widgetsToRemove = getWidget().getWidgetCount() - items.size(); + if (widgetsToRemove < 0) { + widgetsToRemove = 0; + } + List<Widget> remove = new ArrayList<>(widgetsToRemove); + for (Widget widget : getWidget()) { + if (i < items.size()) { + updateItem((RadioButton) widget, items.get(i), false); + i++; + } else { + remove.add(widget); } - RadioButton radioButton = new RadioButton(groupId); + } + remove.stream().forEach(this::remove); + while (i < items.size()) { + updateItem(new RadioButton(groupId), items.get(i), true); + i++; + } + } - String iconUrl = item - .getString(ListingJsonConstants.JSONKEY_ITEM_ICON); - if (iconUrl != null && iconUrl.length() != 0) { - Icon icon = client.getIcon(iconUrl); - itemHtml = icon.getElement().getString() + itemHtml; - } - radioButton.setStyleName("v-radiobutton"); - radioButton.addStyleName(CLASSNAME_OPTION); - radioButton.addClickHandler(this); - radioButton.setHTML(itemHtml); - radioButton.setValue(item - .getBoolean(ListingJsonConstants.JSONKEY_ITEM_SELECTED)); - boolean optionEnabled = !item - .getBoolean(ListingJsonConstants.JSONKEY_ITEM_DISABLED); - boolean enabled = optionEnabled && !isReadonly() && isEnabled(); - radioButton.setEnabled(enabled); + private void remove(Widget widget) { + getWidget().remove(widget); + JsonObject item = optionsToItems.remove(widget); + if (item != null) { String key = item.getString(DataCommunicatorConstants.KEY); + keyToOptions.remove(key); + } + } + + private void updateItem(RadioButton button, JsonObject item, + boolean requireInitialization) { + String itemHtml = item + .getString(ListingJsonConstants.JSONKEY_ITEM_VALUE); + if (!isHtmlContentAllowed()) { + itemHtml = WidgetUtil.escapeHTML(itemHtml); + } + + String iconUrl = item.getString(ListingJsonConstants.JSONKEY_ITEM_ICON); + if (iconUrl != null && iconUrl.length() != 0) { + Icon icon = client.getIcon(iconUrl); + itemHtml = icon.getElement().getString() + itemHtml; + } - optionsContainer.add(radioButton); - optionsToItems.put(radioButton, item); - keyToOptions.put(key, radioButton); + button.setHTML(itemHtml); + button.setValue( + item.getBoolean(ListingJsonConstants.JSONKEY_ITEM_SELECTED)); + boolean optionEnabled = !item + .getBoolean(ListingJsonConstants.JSONKEY_ITEM_DISABLED); + boolean enabled = optionEnabled && !isReadonly() && isEnabled(); + button.setEnabled(enabled); + String key = item.getString(DataCommunicatorConstants.KEY); + + if (requireInitialization) { + getWidget().add(button); + button.setStyleName("v-radiobutton"); + button.addStyleName(CLASSNAME_OPTION); + button.addClickHandler(this); } + optionsToItems.put(button, item); + keyToOptions.put(key, button); } @Override @@ -160,7 +167,7 @@ public class VRadioButtonGroup extends Composite implements Field, ClickHandler, } public void setTabIndex(int tabIndex) { - for (Widget anOptionsContainer : optionsContainer) { + for (Widget anOptionsContainer : getWidget()) { FocusWidget widget = (FocusWidget) anOptionsContainer; widget.setTabIndex(tabIndex); } @@ -180,14 +187,6 @@ public class VRadioButtonGroup extends Composite implements Field, ClickHandler, } } - @Override - public void focus() { - Iterator<Widget> iterator = optionsContainer.iterator(); - if (iterator.hasNext()) { - ((Focusable) iterator.next()).setFocus(true); - } - } - public boolean isHtmlContentAllowed() { return htmlContentAllowed; } @@ -229,7 +228,7 @@ public class VRadioButtonGroup extends Composite implements Field, ClickHandler, public void selectItemKey(String selectedItemKey) { RadioButton radioButton = keyToOptions.get(selectedItemKey); - if(radioButton!=null) {//Items might not be loaded yet + if (radioButton != null) {// Items might not be loaded yet radioButton.setValue(true); } } diff --git a/client/src/main/java/com/vaadin/client/ui/optiongroup/RadioButtonGroupConnector.java b/client/src/main/java/com/vaadin/client/ui/optiongroup/RadioButtonGroupConnector.java index 135126a099..4f3cad3c4c 100644 --- a/client/src/main/java/com/vaadin/client/ui/optiongroup/RadioButtonGroupConnector.java +++ b/client/src/main/java/com/vaadin/client/ui/optiongroup/RadioButtonGroupConnector.java @@ -16,9 +16,12 @@ package com.vaadin.client.ui.optiongroup; +import java.util.ArrayList; +import java.util.List; + import com.vaadin.client.annotations.OnStateChange; import com.vaadin.client.communication.StateChangeEvent; -import com.vaadin.client.connectors.AbstractListingConnector; +import com.vaadin.client.connectors.AbstractFocusableListingConnector; import com.vaadin.client.data.DataSource; import com.vaadin.client.ui.VRadioButtonGroup; import com.vaadin.shared.Range; @@ -28,14 +31,12 @@ import com.vaadin.shared.data.selection.SelectionServerRpc; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.optiongroup.RadioButtonGroupState; import com.vaadin.ui.RadioButtonGroup; -import elemental.json.JsonObject; -import java.util.ArrayList; -import java.util.List; +import elemental.json.JsonObject; @Connect(RadioButtonGroup.class) -public class RadioButtonGroupConnector - extends AbstractListingConnector<SelectionModel.Single<?>> { +public class RadioButtonGroupConnector extends + AbstractFocusableListingConnector<VRadioButtonGroup, SelectionModel.Single<?>> { private Registration selectionChangeRegistration; private Registration dataChangeRegistration; @@ -86,11 +87,6 @@ public class RadioButtonGroupConnector } @Override - public VRadioButtonGroup getWidget() { - return (VRadioButtonGroup) super.getWidget(); - } - - @Override public RadioButtonGroupState getState() { return (RadioButtonGroupState) super.getState(); } @@ -105,9 +101,8 @@ public class RadioButtonGroupConnector */ private void onDataChange(Range range) { assert range.getStart() == 0 && range.getEnd() == getDataSource() - .size() : "RadioButtonGroup only supports full updates, but " + - "got range " - + range; + .size() : "RadioButtonGroup only supports full updates, but " + + "got range " + range; final VRadioButtonGroup select = getWidget(); DataSource<JsonObject> dataSource = getDataSource(); diff --git a/client/src/main/java/com/vaadin/client/widgets/FocusableFlowPanelComposite.java b/client/src/main/java/com/vaadin/client/widgets/FocusableFlowPanelComposite.java index 4a5d031c3f..7a24549664 100644 --- a/client/src/main/java/com/vaadin/client/widgets/FocusableFlowPanelComposite.java +++ b/client/src/main/java/com/vaadin/client/widgets/FocusableFlowPanelComposite.java @@ -20,6 +20,7 @@ import com.google.gwt.event.dom.client.FocusHandler; import com.google.gwt.event.dom.client.HasAllFocusHandlers; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.ui.Composite; +import com.vaadin.client.Focusable; /** * Focusable composite whose widget is {@link ChildFocusAwareFlowPanel} (flow @@ -29,7 +30,7 @@ import com.google.gwt.user.client.ui.Composite; * */ public abstract class FocusableFlowPanelComposite extends Composite - implements HasAllFocusHandlers { + implements HasAllFocusHandlers, Focusable { private final ChildFocusAwareFlowPanel panel; @@ -55,4 +56,9 @@ public abstract class FocusableFlowPanelComposite extends Composite public HandlerRegistration addBlurHandler(BlurHandler handler) { return panel.addBlurHandler(handler); } + + @Override + public void focus() { + getWidget().focus(); + } } |