Skip to content

Commit

Permalink
Allow defining a focus delegate component for CustomField (#20336)
Browse files Browse the repository at this point in the history
  • Loading branch information
pleku authored and ahie committed Dec 15, 2016
1 parent 10d4d70 commit 04f30c6
Show file tree
Hide file tree
Showing 12 changed files with 487 additions and 115 deletions.
59 changes: 59 additions & 0 deletions client/src/main/java/com/vaadin/client/ui/VCustomField.java
@@ -0,0 +1,59 @@
/*
* 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.vaadin.client.Focusable;

public class VCustomField extends VCustomComponent implements Focusable {

private Focusable focusDelegate;

@Override
public void focus() {
if (focusDelegate != null) {
focusDelegate.focus();
}
}

/**
* Sets the focusable widget to focus instead of this custom field.
*
* @param focusDelegate
* the widget to delegate focus to
*/
public void setFocusDelegate(Focusable focusDelegate) {
this.focusDelegate = focusDelegate;

}

/**
* Sets the focusable widget to focus instead of this custom field.
*
* @param focusDelegate
* the widget to delegate focus to
*/
public void setFocusDelegate(
final com.google.gwt.user.client.ui.Focusable focusDelegate) {
this.focusDelegate = new Focusable() {
@Override
public void focus() {
focusDelegate.setFocus(true);
}
};

}

}
Expand Up @@ -17,15 +17,18 @@

import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;

import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
import com.vaadin.client.ConnectorHierarchyChangeEvent.ConnectorHierarchyChangeHandler;
import com.vaadin.client.Focusable;
import com.vaadin.client.HasComponentsConnector;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractFieldConnector;
import com.vaadin.client.ui.VCustomComponent;
import com.vaadin.client.ui.VCustomField;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.customfield.CustomFieldState;
import com.vaadin.ui.CustomField;
Expand All @@ -44,15 +47,46 @@ public CustomFieldConnector() {
}

@Override
public VCustomComponent getWidget() {
return (VCustomComponent) super.getWidget();
public CustomFieldState getState() {
return (CustomFieldState) super.getState();
}

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

@Override
public void updateCaption(ComponentConnector connector) {
// NOP, custom field does not render the caption of its content
}

@Override
public void onStateChanged(StateChangeEvent stateChangeEvent) {
super.onStateChanged(stateChangeEvent);
if (getState().focusDelegate != null) {
Widget widget = ((ComponentConnector) getState().focusDelegate)
.getWidget();
if (widget instanceof Focusable) {
getWidget().setFocusDelegate((Focusable) widget);
} else if (widget instanceof com.google.gwt.user.client.ui.Focusable) {
getWidget().setFocusDelegate(
(com.google.gwt.user.client.ui.Focusable) widget);
} else {
getLogger().warning(
"The given focus delegate does not implement Focusable: "
+ widget.getClass().getName());
}
} else {
getWidget().setFocusDelegate((Focusable) null);
}

}

private static Logger getLogger() {
return Logger.getLogger(CustomFieldConnector.class.getName());
}

@Override
public void onConnectorHierarchyChange(
ConnectorHierarchyChangeEvent event) {
Expand Down Expand Up @@ -122,9 +156,4 @@ protected Widget getContentWidget() {
}
}

@Override
public CustomFieldState getState() {
return (CustomFieldState) super.getState();
}

}
@@ -0,0 +1,60 @@
/*
* 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.v7.client.ui;

import com.vaadin.client.Focusable;

@Deprecated
public class VCustomField extends VCustomComponent implements Focusable {

private Focusable focusDelegate;

@Override
public void focus() {
if (focusDelegate != null) {
focusDelegate.focus();
}
}

/**
* Sets the focusable widget to focus instead of this custom field.
*
* @param focusDelegate
* the widget to delegate focus to
*/
public void setFocusDelegate(Focusable focusDelegate) {
this.focusDelegate = focusDelegate;

}

/**
* Sets the focusable widget to focus instead of this custom field.
*
* @param focusDelegate
* the widget to delegate focus to
*/
public void setFocusDelegate(
final com.google.gwt.user.client.ui.Focusable focusDelegate) {
this.focusDelegate = new Focusable() {
@Override
public void focus() {
focusDelegate.setFocus(true);
}
};

}

}
Expand Up @@ -17,16 +17,19 @@

import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;

import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
import com.vaadin.client.ConnectorHierarchyChangeEvent.ConnectorHierarchyChangeHandler;
import com.vaadin.client.Focusable;
import com.vaadin.client.HasComponentsConnector;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.shared.ui.Connect;
import com.vaadin.v7.client.ui.AbstractFieldConnector;
import com.vaadin.v7.client.ui.VCustomComponent;
import com.vaadin.v7.client.ui.VCustomField;
import com.vaadin.v7.ui.CustomField;

@Connect(value = CustomField.class)
Expand All @@ -43,15 +46,41 @@ public CustomFieldConnector() {
}

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

@Override
public void updateCaption(ComponentConnector connector) {
// NOP, custom field does not render the caption of its content
}

@Override
public void onStateChanged(StateChangeEvent stateChangeEvent) {
super.onStateChanged(stateChangeEvent);
if (getState().focusDelegate != null) {
Widget widget = ((ComponentConnector) getState().focusDelegate)
.getWidget();
if (widget instanceof Focusable) {
getWidget().setFocusDelegate((Focusable) widget);
} else if (widget instanceof com.google.gwt.user.client.ui.Focusable) {
getWidget().setFocusDelegate(
(com.google.gwt.user.client.ui.Focusable) widget);
} else {
getLogger().warning(
"The given focus delegate does not implement Focusable: "
+ widget.getClass().getName());
}
} else {
getWidget().setFocusDelegate((Focusable) null);
}

}

private static Logger getLogger() {
return Logger.getLogger(CustomFieldConnector.class.getName());
}

@Override
public void onConnectorHierarchyChange(
ConnectorHierarchyChangeEvent event) {
Expand Down
Expand Up @@ -130,7 +130,7 @@ public void setWidth(float width, Unit unit) {

private class ComponentIterator
implements Iterator<Component>, Serializable {
boolean first = (root != null);
boolean first = root != null;

@Override
public boolean hasNext() {
Expand All @@ -153,4 +153,53 @@ public void remove() {
public Iterator<Component> iterator() {
return new ComponentIterator();
}

/**
* Sets the component to which all methods from the {@link Focusable}
* interface should be delegated.
* <p>
* Set this to a wrapped field to include that field in the tabbing order,
* to make it receive focus when {@link #focus()} is called and to make it
* be correctly focused when used as a Grid editor component.
* <p>
* By default, {@link Focusable} events are handled by the super class and
* ultimately ignored.
*
* @param focusDelegate
* the focusable component to which focus events are redirected
*/
public void setFocusDelegate(Focusable focusDelegate) {
getState().focusDelegate = focusDelegate;
}

private Focusable getFocusable() {
return (Focusable) getState(false).focusDelegate;
}

@Override
public void focus() {
if (getFocusable() != null) {
getFocusable().focus();
} else {
super.focus();
}
}

@Override
public int getTabIndex() {
if (getFocusable() != null) {
return getFocusable().getTabIndex();
} else {
return super.getTabIndex();
}
}

@Override
public void setTabIndex(int tabIndex) {
if (getFocusable() != null) {
getFocusable().setTabIndex(tabIndex);
} else {
super.setTabIndex(tabIndex);
}
}
}
Expand Up @@ -15,6 +15,7 @@
*/
package com.vaadin.v7.shared;

import com.vaadin.shared.Connector;
import com.vaadin.shared.annotations.NoLayout;

/**
Expand All @@ -34,4 +35,13 @@ public class AbstractFieldState extends AbstractLegacyComponentState {
*/
@NoLayout
public int tabIndex = 0;

/**
* The component which should receive focus events instead of the custom
* field wrapper.
* <p>
* This is not used in all fields, but needs to be here for the time being
* (#20468).
*/
public Connector focusDelegate;
}

0 comments on commit 04f30c6

Please sign in to comment.