From 940b082cd547a110a45e69c13e50a583e9f7ef11 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sauli=20T=C3=A4hk=C3=A4p=C3=A4=C3=A4?= Date: Mon, 16 Mar 2015 23:53:56 +0200 Subject: [PATCH] Sanitize connectors for PopupDateField and DateField. (#17090) Change-Id: I667796430eeaa0ddd8142b0c229fe133cd30cd49 --- .../client/ui/AbstractComponentConnector.java | 3 +- .../ui/datefield/DateFieldConnector.java | 219 ++++++++++++++++++ .../ui/datefield/PopupDateFieldConnector.java | 205 +--------------- .../datefield/PopupDateFieldConnector.java | 24 ++ .../PopupDateFieldConnectorTest.java | 21 ++ 5 files changed, 271 insertions(+), 201 deletions(-) create mode 100644 client/src/com/vaadin/client/ui/datefield/DateFieldConnector.java create mode 100644 uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldConnector.java create mode 100644 uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldConnectorTest.java diff --git a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java index 46ad289488..24a0438476 100644 --- a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java +++ b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java @@ -35,7 +35,6 @@ import com.vaadin.client.communication.StateChangeEvent; import com.vaadin.client.metadata.NoDataException; import com.vaadin.client.metadata.Type; import com.vaadin.client.metadata.TypeData; -import com.vaadin.client.ui.datefield.PopupDateFieldConnector; import com.vaadin.client.ui.ui.UIConnector; import com.vaadin.shared.AbstractComponentState; import com.vaadin.shared.ComponentConstants; @@ -404,7 +403,7 @@ public abstract class AbstractComponentConnector extends AbstractConnector * updated in another widget in addition to the one returned by the * Connector's {@link #getWidget()}, or if the prefix should be * different. For example see - * {@link PopupDateFieldConnector#setWidgetStyleNameWithPrefix(String, String, boolean)} + * {@link com.vaadin.client.ui.datefield.DateFieldConnector#setWidgetStyleNameWithPrefix(String, String, boolean)} *

* * @param styleName diff --git a/client/src/com/vaadin/client/ui/datefield/DateFieldConnector.java b/client/src/com/vaadin/client/ui/datefield/DateFieldConnector.java new file mode 100644 index 0000000000..042b8db8e2 --- /dev/null +++ b/client/src/com/vaadin/client/ui/datefield/DateFieldConnector.java @@ -0,0 +1,219 @@ +/* + * Copyright 2000-2014 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.datefield; + +import java.util.Date; + +import com.google.gwt.event.logical.shared.CloseEvent; +import com.google.gwt.event.logical.shared.CloseHandler; +import com.google.gwt.user.client.ui.PopupPanel; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.DateTimeService; +import com.vaadin.client.UIDL; +import com.vaadin.client.communication.StateChangeEvent; +import com.vaadin.client.ui.VCalendarPanel.FocusChangeListener; +import com.vaadin.client.ui.VCalendarPanel.TimeChangeListener; +import com.vaadin.client.ui.VPopupCalendar; +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.datefield.PopupDateFieldState; +import com.vaadin.shared.ui.datefield.Resolution; +import com.vaadin.ui.DateField; +import com.vaadin.ui.PopupDateField; + +@Connect(DateField.class) +public class DateFieldConnector extends TextualDateConnector { + + /* + * (non-Javadoc) + * + * @see com.vaadin.client.ui.AbstractConnector#init() + */ + @Override + protected void init() { + getWidget().popup.addCloseHandler(new CloseHandler() { + + @Override + public void onClose(CloseEvent event) { + /* + * FIXME This is a hack so we do not have to rewrite half of the + * datefield so values are not sent while selecting a date + * (#6252). + * + * The datefield will now only set the date UIDL variables while + * the user is selecting year/month/date/time and not send them + * directly. Only when the user closes the popup (by clicking on + * a day/enter/clicking outside of popup) then the new value is + * communicated to the server. + */ + if (getWidget().isImmediate()) { + getConnection().sendPendingVariableChanges(); + } + } + }); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.client.ui.VTextualDate#updateFromUIDL(com.vaadin + * .client.UIDL, com.vaadin.client.ApplicationConnection) + */ + @Override + @SuppressWarnings("deprecation") + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + + String oldLocale = getWidget().getCurrentLocale(); + + getWidget().parsable = uidl.getBooleanAttribute("parsable"); + + super.updateFromUIDL(uidl, client); + + getWidget().calendar.setDateTimeService(getWidget() + .getDateTimeService()); + getWidget().calendar.setShowISOWeekNumbers(getWidget() + .isShowISOWeekNumbers()); + if (getWidget().calendar.getResolution() != getWidget() + .getCurrentResolution()) { + boolean hasSelectedDate = false; + getWidget().calendar.setResolution(getWidget() + .getCurrentResolution()); + if (getWidget().calendar.getDate() != null + && getWidget().getCurrentDate() != null) { + hasSelectedDate = true; + getWidget().calendar.setDate((Date) getWidget() + .getCurrentDate().clone()); + } + // force re-render when changing resolution only + getWidget().calendar.renderCalendar(hasSelectedDate); + } + + // Force re-render of calendar if locale has changed (#12153) + if (!getWidget().getCurrentLocale().equals(oldLocale)) { + getWidget().calendar.renderCalendar(); + } + + if (getWidget().getCurrentResolution().getCalendarField() <= Resolution.MONTH + .getCalendarField()) { + getWidget().calendar + .setFocusChangeListener(new FocusChangeListener() { + @Override + public void focusChanged(Date date) { + + getWidget().updateValue(date); + getWidget().buildDate(); + Date date2 = getWidget().calendar.getDate(); + date2.setYear(date.getYear()); + date2.setMonth(date.getMonth()); + } + }); + } else { + getWidget().calendar.setFocusChangeListener(null); + } + + if (getWidget().getCurrentResolution().getCalendarField() > Resolution.DAY + .getCalendarField()) { + getWidget().calendar + .setTimeChangeListener(new TimeChangeListener() { + @Override + public void changed(int hour, int min, int sec, int msec) { + Date d = getWidget().getDate(); + if (d == null) { + // date currently null, use the value from + // calendarPanel + // (~ client time at the init of the widget) + d = (Date) getWidget().calendar.getDate() + .clone(); + } + d.setHours(hour); + d.setMinutes(min); + d.setSeconds(sec); + DateTimeService.setMilliseconds(d, msec); + + // Always update time changes to the server + getWidget().updateValue(d); + + // Update text field + getWidget().buildDate(); + } + }); + } + + if (getWidget().isReadonly()) { + getWidget().calendarToggle.addStyleName(VPopupCalendar.CLASSNAME + + "-button-readonly"); + } else { + getWidget().calendarToggle.removeStyleName(VPopupCalendar.CLASSNAME + + "-button-readonly"); + } + + getWidget().setDescriptionForAssistiveDevices( + getState().descriptionForAssistiveDevices); + + getWidget().setTextFieldTabIndex(); + } + + @Override + public VPopupCalendar getWidget() { + return (VPopupCalendar) super.getWidget(); + } + + @Override + public PopupDateFieldState getState() { + return (PopupDateFieldState) super.getState(); + } + + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + super.onStateChanged(stateChangeEvent); + getWidget().setTextFieldEnabled(getState().textFieldEnabled); + getWidget().setRangeStart(nullSafeDateClone(getState().rangeStart)); + getWidget().setRangeEnd(nullSafeDateClone(getState().rangeEnd)); + } + + private Date nullSafeDateClone(Date date) { + if (date == null) { + return null; + } else { + return (Date) date.clone(); + } + } + + @Override + protected void setWidgetStyleName(String styleName, boolean add) { + super.setWidgetStyleName(styleName, add); + + // update the style change to popup calendar widget + getWidget().popup.setStyleName(styleName, add); + } + + @Override + protected void setWidgetStyleNameWithPrefix(String prefix, + String styleName, boolean add) { + super.setWidgetStyleNameWithPrefix(prefix, styleName, add); + + // update the style change to popup calendar widget with the correct + // prefix + if (!styleName.startsWith("-")) { + getWidget().popup.setStyleName(getWidget().getStylePrimaryName() + + "-popup-" + styleName, add); + } else { + getWidget().popup.setStyleName(getWidget().getStylePrimaryName() + + "-popup" + styleName, add); + } + } + +} diff --git a/client/src/com/vaadin/client/ui/datefield/PopupDateFieldConnector.java b/client/src/com/vaadin/client/ui/datefield/PopupDateFieldConnector.java index 7bcaaba04e..31232177d3 100644 --- a/client/src/com/vaadin/client/ui/datefield/PopupDateFieldConnector.java +++ b/client/src/com/vaadin/client/ui/datefield/PopupDateFieldConnector.java @@ -1,12 +1,12 @@ /* * Copyright 2000-2014 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 @@ -16,203 +16,10 @@ package com.vaadin.client.ui.datefield; -import java.util.Date; - -import com.google.gwt.event.logical.shared.CloseEvent; -import com.google.gwt.event.logical.shared.CloseHandler; -import com.google.gwt.user.client.ui.PopupPanel; -import com.vaadin.client.ApplicationConnection; -import com.vaadin.client.DateTimeService; -import com.vaadin.client.UIDL; -import com.vaadin.client.communication.StateChangeEvent; -import com.vaadin.client.ui.VCalendarPanel.FocusChangeListener; -import com.vaadin.client.ui.VCalendarPanel.TimeChangeListener; -import com.vaadin.client.ui.VPopupCalendar; import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.datefield.PopupDateFieldState; -import com.vaadin.shared.ui.datefield.Resolution; -import com.vaadin.ui.DateField; - -@Connect(DateField.class) -public class PopupDateFieldConnector extends TextualDateConnector { - - /* - * (non-Javadoc) - * - * @see com.vaadin.client.ui.AbstractConnector#init() - */ - @Override - protected void init() { - getWidget().popup.addCloseHandler(new CloseHandler() { - - @Override - public void onClose(CloseEvent event) { - /* - * FIXME This is a hack so we do not have to rewrite half of the - * datefield so values are not sent while selecting a date - * (#6252). - * - * The datefield will now only set the date UIDL variables while - * the user is selecting year/month/date/time and not send them - * directly. Only when the user closes the popup (by clicking on - * a day/enter/clicking outside of popup) then the new value is - * communicated to the server. - */ - if (getWidget().isImmediate()) { - getConnection().sendPendingVariableChanges(); - } - } - }); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.client.ui.VTextualDate#updateFromUIDL(com.vaadin - * .client.UIDL, com.vaadin.client.ApplicationConnection) - */ - @Override - @SuppressWarnings("deprecation") - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - String oldLocale = getWidget().getCurrentLocale(); - - getWidget().parsable = uidl.getBooleanAttribute("parsable"); - - super.updateFromUIDL(uidl, client); - - getWidget().calendar.setDateTimeService(getWidget() - .getDateTimeService()); - getWidget().calendar.setShowISOWeekNumbers(getWidget() - .isShowISOWeekNumbers()); - if (getWidget().calendar.getResolution() != getWidget() - .getCurrentResolution()) { - boolean hasSelectedDate = false; - getWidget().calendar.setResolution(getWidget() - .getCurrentResolution()); - if (getWidget().calendar.getDate() != null - && getWidget().getCurrentDate() != null) { - hasSelectedDate = true; - getWidget().calendar.setDate((Date) getWidget() - .getCurrentDate().clone()); - } - // force re-render when changing resolution only - getWidget().calendar.renderCalendar(hasSelectedDate); - } - - // Force re-render of calendar if locale has changed (#12153) - if (!getWidget().getCurrentLocale().equals(oldLocale)) { - getWidget().calendar.renderCalendar(); - } - - if (getWidget().getCurrentResolution().getCalendarField() <= Resolution.MONTH - .getCalendarField()) { - getWidget().calendar - .setFocusChangeListener(new FocusChangeListener() { - @Override - public void focusChanged(Date date) { - - getWidget().updateValue(date); - getWidget().buildDate(); - Date date2 = getWidget().calendar.getDate(); - date2.setYear(date.getYear()); - date2.setMonth(date.getMonth()); - } - }); - } else { - getWidget().calendar.setFocusChangeListener(null); - } - - if (getWidget().getCurrentResolution().getCalendarField() > Resolution.DAY - .getCalendarField()) { - getWidget().calendar - .setTimeChangeListener(new TimeChangeListener() { - @Override - public void changed(int hour, int min, int sec, int msec) { - Date d = getWidget().getDate(); - if (d == null) { - // date currently null, use the value from - // calendarPanel - // (~ client time at the init of the widget) - d = (Date) getWidget().calendar.getDate() - .clone(); - } - d.setHours(hour); - d.setMinutes(min); - d.setSeconds(sec); - DateTimeService.setMilliseconds(d, msec); - - // Always update time changes to the server - getWidget().updateValue(d); - - // Update text field - getWidget().buildDate(); - } - }); - } - - if (getWidget().isReadonly()) { - getWidget().calendarToggle.addStyleName(VPopupCalendar.CLASSNAME - + "-button-readonly"); - } else { - getWidget().calendarToggle.removeStyleName(VPopupCalendar.CLASSNAME - + "-button-readonly"); - } - - getWidget().setDescriptionForAssistiveDevices( - getState().descriptionForAssistiveDevices); - - getWidget().setTextFieldTabIndex(); - } - - @Override - public VPopupCalendar getWidget() { - return (VPopupCalendar) super.getWidget(); - } - - @Override - public PopupDateFieldState getState() { - return (PopupDateFieldState) super.getState(); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - getWidget().setTextFieldEnabled(getState().textFieldEnabled); - getWidget().setRangeStart(nullSafeDateClone(getState().rangeStart)); - getWidget().setRangeEnd(nullSafeDateClone(getState().rangeEnd)); - } - - private Date nullSafeDateClone(Date date) { - if (date == null) { - return null; - } else { - return (Date) date.clone(); - } - } - - @Override - protected void setWidgetStyleName(String styleName, boolean add) { - super.setWidgetStyleName(styleName, add); - - // update the style change to popup calendar widget - getWidget().popup.setStyleName(styleName, add); - } - - @Override - protected void setWidgetStyleNameWithPrefix(String prefix, - String styleName, boolean add) { - super.setWidgetStyleNameWithPrefix(prefix, styleName, add); +import com.vaadin.ui.PopupDateField; - // update the style change to popup calendar widget with the correct - // prefix - if (!styleName.startsWith("-")) { - getWidget().popup.setStyleName(getWidget().getStylePrimaryName() - + "-popup-" + styleName, add); - } else { - getWidget().popup.setStyleName(getWidget().getStylePrimaryName() - + "-popup" + styleName, add); - } - } +@Connect(PopupDateField.class) +public class PopupDateFieldConnector extends DateFieldConnector { } diff --git a/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldConnector.java b/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldConnector.java new file mode 100644 index 0000000000..5cdc8f1396 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldConnector.java @@ -0,0 +1,24 @@ +package com.vaadin.tests.components.datefield; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.DateField; +import com.vaadin.ui.PopupDateField; + +public class PopupDateFieldConnector extends AbstractTestUI { + @Override + protected void setup(VaadinRequest request) { + addComponent(new PopupDateField()); + addComponent(new DateField()); + } + + @Override + protected Integer getTicketNumber() { + return 17090; + } + + @Override + protected String getTestDescription() { + return "PopupDateFieldElement should be accessible using TB4 PopupDateFieldElement."; + } +} diff --git a/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldConnectorTest.java b/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldConnectorTest.java new file mode 100644 index 0000000000..5334327a83 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldConnectorTest.java @@ -0,0 +1,21 @@ +package com.vaadin.tests.components.datefield; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +import org.junit.Test; + +import com.vaadin.testbench.elements.DateFieldElement; +import com.vaadin.testbench.elements.PopupDateFieldElement; +import com.vaadin.tests.tb3.SingleBrowserTest; + +public class PopupDateFieldConnectorTest extends SingleBrowserTest { + + @Test + public void popupDateFieldElementIsLocated() { + openTestURL(); + + assertThat($(PopupDateFieldElement.class).all().size(), is(1)); + assertThat($(DateFieldElement.class).all().size(), is(2)); + } +} \ No newline at end of file -- 2.39.5