From 25013128a7e2eb80b565d28abcc0af26219098db Mon Sep 17 00:00:00 2001 From: Denis Anisimov Date: Wed, 26 Oct 2016 16:22:00 +0300 Subject: Implement focus/blur listeners for NativeSelect. Fixes vaadin/framework8-issues#332 Change-Id: I19996ea83ed1fbe2b115d92d6be5e6a5e158f283 --- .../AbstractFocusableListingConnector.java | 56 +++++++++++++++++++++ .../java/com/vaadin/client/ui/VCheckBoxGroup.java | 44 ++++------------ .../java/com/vaadin/client/ui/VNativeSelect.java | 11 ++-- .../ui/nativeselect/NativeSelectConnector.java | 11 ++-- .../ui/optiongroup/CheckBoxGroupConnector.java | 22 ++------ .../widgets/FocusableFlowPanelComposite.java | 58 ++++++++++++++++++++++ 6 files changed, 135 insertions(+), 67 deletions(-) create mode 100644 client/src/main/java/com/vaadin/client/connectors/AbstractFocusableListingConnector.java create mode 100644 client/src/main/java/com/vaadin/client/widgets/FocusableFlowPanelComposite.java (limited to 'client') diff --git a/client/src/main/java/com/vaadin/client/connectors/AbstractFocusableListingConnector.java b/client/src/main/java/com/vaadin/client/connectors/AbstractFocusableListingConnector.java new file mode 100644 index 0000000000..996086d36d --- /dev/null +++ b/client/src/main/java/com/vaadin/client/connectors/AbstractFocusableListingConnector.java @@ -0,0 +1,56 @@ +/* + * 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.connectors; + +import com.google.gwt.event.dom.client.HasAllFocusHandlers; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.client.ui.ConnectorFocusAndBlurHandler; +import com.vaadin.shared.data.selection.SelectionModel; + +/** + * Abstract class for listing widget connectors that contains focusable children + * to track their focus/blur events. + * + * @author Vaadin Ltd + * + * @param + * widget type which has to allow to register focus/blur handlers + * @param + * the client-side selection model type + */ +public abstract class AbstractFocusableListingConnector> + extends AbstractListingConnector { + + private ConnectorFocusAndBlurHandler handler; + + @Override + protected void init() { + handler = ConnectorFocusAndBlurHandler.addHandlers(this); + } + + @Override + public void onUnregister() { + super.onUnregister(); + handler.removeHandlers(); + handler = null; + } + + @SuppressWarnings("unchecked") + @Override + public WIDGET getWidget() { + return (WIDGET) super.getWidget(); + } +} 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 d99d179d74..6ba7ea75d5 100644 --- a/client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java +++ b/client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java @@ -23,19 +23,14 @@ import java.util.Map; import java.util.function.BiConsumer; import com.google.gwt.aria.client.Roles; -import com.google.gwt.event.dom.client.BlurHandler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; -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.google.gwt.user.client.ui.FocusWidget; import com.google.gwt.user.client.ui.HasEnabled; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.WidgetUtil; -import com.vaadin.client.widgets.ChildFocusAwareFlowPanel; +import com.vaadin.client.widgets.FocusableFlowPanelComposite; import com.vaadin.shared.Registration; import com.vaadin.shared.ui.ListingJsonConstants; @@ -47,8 +42,8 @@ import elemental.json.JsonObject; * @author Vaadin Ltd. * @since 8.0 */ -public class VCheckBoxGroup extends Composite implements Field, ClickHandler, - com.vaadin.client.Focusable, HasEnabled, HasAllFocusHandlers { +public class VCheckBoxGroup extends FocusableFlowPanelComposite implements + Field, ClickHandler, com.vaadin.client.Focusable, HasEnabled { public static final String CLASSNAME = "v-select-optiongroup"; public static final String CLASSNAME_OPTION = "v-select-option"; @@ -60,14 +55,6 @@ public class VCheckBoxGroup 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) - *

- * For internal use only. May be removed or replaced in the future. - */ - private ChildFocusAwareFlowPanel optionsContainer; - private boolean htmlContentAllowed = false; private boolean enabled; @@ -75,9 +62,7 @@ public class VCheckBoxGroup extends Composite implements Field, ClickHandler, private List> selectionChangeListeners; public VCheckBoxGroup() { - optionsContainer = new ChildFocusAwareFlowPanel(); - initWidget(optionsContainer); - optionsContainer.setStyleName(CLASSNAME); + getWidget().setStyleName(CLASSNAME); optionsToItems = new HashMap<>(); selectionChangeListeners = new ArrayList<>(); } @@ -88,12 +73,12 @@ public class VCheckBoxGroup extends Composite implements Field, ClickHandler, public void buildOptions(List items) { Roles.getGroupRole().set(getElement()); int i = 0; - int widgetsToRemove = optionsContainer.getWidgetCount() - items.size(); + int widgetsToRemove = getWidget().getWidgetCount() - items.size(); if (widgetsToRemove < 0) { widgetsToRemove = 0; } List remove = new ArrayList<>(widgetsToRemove); - for (Widget widget : optionsContainer) { + for (Widget widget : getWidget()) { if (i < items.size()) { updateItem((VCheckBox) widget, items.get(i), false); i++; @@ -109,7 +94,7 @@ public class VCheckBoxGroup extends Composite implements Field, ClickHandler, } private void remove(Widget widget) { - optionsContainer.remove(widget); + getWidget().remove(widget); optionsToItems.remove(widget); } @@ -135,7 +120,7 @@ public class VCheckBoxGroup extends Composite implements Field, ClickHandler, if (requireInitializations) { widget.addStyleName(CLASSNAME_OPTION); widget.addClickHandler(this); - optionsContainer.add(widget); + getWidget().add(widget); } optionsToItems.put(widget, item); } @@ -161,7 +146,7 @@ public class VCheckBoxGroup 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); } @@ -185,7 +170,7 @@ public class VCheckBoxGroup extends Composite implements Field, ClickHandler, @Override public void focus() { - optionsContainer.focus(); + getWidget().focus(); } public boolean isHtmlContentAllowed() { @@ -227,13 +212,4 @@ public class VCheckBoxGroup extends Composite implements Field, ClickHandler, .remove(selectionChanged); } - @Override - public HandlerRegistration addFocusHandler(FocusHandler handler) { - return optionsContainer.addFocusHandler(handler); - } - - @Override - public HandlerRegistration addBlurHandler(BlurHandler handler) { - return optionsContainer.addBlurHandler(handler); - } } diff --git a/client/src/main/java/com/vaadin/client/ui/VNativeSelect.java b/client/src/main/java/com/vaadin/client/ui/VNativeSelect.java index efbba52efc..5005c79fbb 100644 --- a/client/src/main/java/com/vaadin/client/ui/VNativeSelect.java +++ b/client/src/main/java/com/vaadin/client/ui/VNativeSelect.java @@ -17,16 +17,17 @@ package com.vaadin.client.ui; import java.util.Objects; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.event.dom.client.HasAllFocusHandlers; import com.google.gwt.user.client.ui.ListBox; +import com.vaadin.client.widgets.FocusableFlowPanelComposite; /** * The client-side widget for the {@code NativeSelect} component. * * @author Vaadin Ltd. */ -public class VNativeSelect extends Composite { +public class VNativeSelect extends FocusableFlowPanelComposite + implements HasAllFocusHandlers { private final ListBox listBox = new ListBox(); @@ -34,9 +35,7 @@ public class VNativeSelect extends Composite { * Creates a new {@code VNativeSelect} instance. */ public VNativeSelect() { - FlowPanel panel = new FlowPanel(); - panel.add(listBox); - initWidget(panel); + getWidget().add(listBox); } /** diff --git a/client/src/main/java/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java b/client/src/main/java/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java index 93861b41dc..20c625a40d 100644 --- a/client/src/main/java/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java +++ b/client/src/main/java/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java @@ -18,7 +18,7 @@ package com.vaadin.client.ui.nativeselect; import com.google.gwt.event.shared.HandlerRegistration; import com.vaadin.client.annotations.OnStateChange; -import com.vaadin.client.connectors.AbstractListingConnector; +import com.vaadin.client.connectors.AbstractFocusableListingConnector; import com.vaadin.client.data.DataSource; import com.vaadin.client.ui.VNativeSelect; import com.vaadin.shared.Range; @@ -41,8 +41,8 @@ import elemental.json.JsonObject; * @since 8.0 */ @Connect(com.vaadin.ui.NativeSelect.class) -public class NativeSelectConnector - extends AbstractListingConnector> { +public class NativeSelectConnector extends + AbstractFocusableListingConnector> { private HandlerRegistration selectionChangeRegistration; private Registration dataChangeRegistration; @@ -67,11 +67,6 @@ public class NativeSelectConnector selectionChangeRegistration = null; } - @Override - public VNativeSelect getWidget() { - return (VNativeSelect) super.getWidget(); - } - @Override public void setDataSource(DataSource dataSource) { if (dataChangeRegistration != null) { diff --git a/client/src/main/java/com/vaadin/client/ui/optiongroup/CheckBoxGroupConnector.java b/client/src/main/java/com/vaadin/client/ui/optiongroup/CheckBoxGroupConnector.java index 289a89eadb..5955037e65 100644 --- a/client/src/main/java/com/vaadin/client/ui/optiongroup/CheckBoxGroupConnector.java +++ b/client/src/main/java/com/vaadin/client/ui/optiongroup/CheckBoxGroupConnector.java @@ -22,9 +22,8 @@ import java.util.HashSet; import java.util.List; 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.ConnectorFocusAndBlurHandler; import com.vaadin.client.ui.VCheckBoxGroup; import com.vaadin.shared.data.selection.MultiSelectServerRpc; import com.vaadin.shared.data.selection.SelectionModel; @@ -36,23 +35,13 @@ import elemental.json.JsonObject; @Connect(CheckBoxGroup.class) // We don't care about the framework-provided selection model at this point -public class CheckBoxGroupConnector - extends AbstractListingConnector> { - - private ConnectorFocusAndBlurHandler handler; +public class CheckBoxGroupConnector extends + AbstractFocusableListingConnector> { @Override protected void init() { super.init(); getWidget().addSelectionChangeHandler(this::selectionChanged); - handler = ConnectorFocusAndBlurHandler.addHandlers(this); - } - - @Override - public void onUnregister() { - super.onUnregister(); - handler.removeHandlers(); - handler = null; } private void selectionChanged(JsonObject changedItem, Boolean selected) { @@ -90,11 +79,6 @@ public class CheckBoxGroupConnector getWidget().buildOptions(items); } - @Override - public VCheckBoxGroup getWidget() { - return (VCheckBoxGroup) super.getWidget(); - } - @Override public CheckBoxGroupState getState() { return (CheckBoxGroupState) super.getState(); diff --git a/client/src/main/java/com/vaadin/client/widgets/FocusableFlowPanelComposite.java b/client/src/main/java/com/vaadin/client/widgets/FocusableFlowPanelComposite.java new file mode 100644 index 0000000000..4a5d031c3f --- /dev/null +++ b/client/src/main/java/com/vaadin/client/widgets/FocusableFlowPanelComposite.java @@ -0,0 +1,58 @@ +/* + * 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.widgets; + +import com.google.gwt.event.dom.client.BlurHandler; +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; + +/** + * Focusable composite whose widget is {@link ChildFocusAwareFlowPanel} (flow + * panel that tracks focus/blur events from its children). + * + * @author Vaadin Ltd + * + */ +public abstract class FocusableFlowPanelComposite extends Composite + implements HasAllFocusHandlers { + + private final ChildFocusAwareFlowPanel panel; + + /** + * Creates a new instance. + */ + protected FocusableFlowPanelComposite() { + panel = new ChildFocusAwareFlowPanel(); + initWidget(panel); + } + + @Override + protected final ChildFocusAwareFlowPanel getWidget() { + return (ChildFocusAwareFlowPanel) super.getWidget(); + } + + @Override + public HandlerRegistration addFocusHandler(FocusHandler handler) { + return panel.addFocusHandler(handler); + } + + @Override + public HandlerRegistration addBlurHandler(BlurHandler handler) { + return panel.addBlurHandler(handler); + } +} -- cgit v1.2.3