From 7cb49d10de85b038b3f7068bf87b6c10315d3c21 Mon Sep 17 00:00:00 2001 From: Patrik Lindström Date: Mon, 29 Jul 2013 15:09:35 +0300 Subject: Fix invisible calendar actions menu #12181 Change-Id: I4cdf3d1e584f1537f0f216ddd6f65c1ec4a2ee6b --- server/src/com/vaadin/ui/Calendar.java | 1 + .../com/vaadin/ui/components/calendar/CalendarDateRange.java | 11 +++++++++++ 2 files changed, 12 insertions(+) (limited to 'server/src') diff --git a/server/src/com/vaadin/ui/Calendar.java b/server/src/com/vaadin/ui/Calendar.java index c3385baa2c..8b8cc7b475 100644 --- a/server/src/com/vaadin/ui/Calendar.java +++ b/server/src/com/vaadin/ui/Calendar.java @@ -535,6 +535,7 @@ public class Calendar extends AbstractComponent implements // Get day start and end times Date start = cal.getTime(); cal.add(java.util.Calendar.DATE, 1); + cal.add(java.util.Calendar.SECOND, -1); Date end = cal.getTime(); boolean monthView = (durationInDays > 7); diff --git a/server/src/com/vaadin/ui/components/calendar/CalendarDateRange.java b/server/src/com/vaadin/ui/components/calendar/CalendarDateRange.java index 01b766a6db..b78fda3136 100644 --- a/server/src/com/vaadin/ui/components/calendar/CalendarDateRange.java +++ b/server/src/com/vaadin/ui/components/calendar/CalendarDateRange.java @@ -83,4 +83,15 @@ public class CalendarDateRange implements Serializable { return date.compareTo(start) >= 0 && date.compareTo(end) <= 0; } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "CalendarDateRange [start=" + start + ", end=" + end + "]"; + } + } -- cgit v1.2.3 From 44aacf471be2f1846607194af98b795e2247a600 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Tue, 30 Jul 2013 14:58:14 +0300 Subject: Clarify Embedded javadoc (#12290) Change-Id: I3c15bf79236019056eeb501974a6a34799e8fd40 --- server/src/com/vaadin/ui/Embedded.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'server/src') diff --git a/server/src/com/vaadin/ui/Embedded.java b/server/src/com/vaadin/ui/Embedded.java index c9b64af415..53354db0f4 100644 --- a/server/src/com/vaadin/ui/Embedded.java +++ b/server/src/com/vaadin/ui/Embedded.java @@ -31,13 +31,17 @@ import com.vaadin.shared.ui.embedded.EmbeddedConstants; import com.vaadin.shared.ui.embedded.EmbeddedServerRpc; /** - * Component for embedding external objects. + * A component for embedding external objects. *

- * As of Vaadin 7.0, the {@link Image}, {@link Flash}, and {@link BrowserFrame} - * components should be used instead of Embedded for displaying - * images, Adobe Flash objects, and embedded web pages, respectively. - * Embedded is still useful for displaying other multimedia content - * such as applets and PDF documents. + * The {@code Embedded} component is used to display various types of multimedia + * content using the HTML {@code } element. This includes PDF documents, + * Java applets, and QuickTime videos. Installing a browser plug-in is usually + * required to actually view the embedded content. + *

+ * Note that before Vaadin 7, {@code Embedded} was also used to display images, + * Adobe Flash objects, and embedded web pages. This use of the component is + * deprecated in Vaadin 7; the {@link Image}, {@link Flash}, and + * {@link BrowserFrame} components should be used instead, respectively. * * @see Video * @see Audio -- cgit v1.2.3 From 59a043b3b06f516c59c07577c9416a69b6962bfe Mon Sep 17 00:00:00 2001 From: Patrik Lindström Date: Tue, 30 Jul 2013 14:14:07 +0300 Subject: Fix actions in action menu appearing in random order #12250 Change-Id: I77186adb94392cd317d37b9d9250f28891e6f06e --- server/src/com/vaadin/ui/Calendar.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'server/src') diff --git a/server/src/com/vaadin/ui/Calendar.java b/server/src/com/vaadin/ui/Calendar.java index 8b8cc7b475..9ccc8ea2d9 100644 --- a/server/src/com/vaadin/ui/Calendar.java +++ b/server/src/com/vaadin/ui/Calendar.java @@ -26,7 +26,7 @@ import java.util.Date; import java.util.EventListener; import java.util.GregorianCalendar; import java.util.HashMap; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Locale; @@ -573,7 +573,7 @@ public class Calendar extends AbstractComponent implements CalendarDateRange range = new CalendarDateRange(s, e, getTimeZone()); Action[] actions = actionHandler.getActions(range, this); if (actions != null) { - Set actionSet = new HashSet( + Set actionSet = new LinkedHashSet( Arrays.asList(actions)); actionMap.put(range, actionSet); } @@ -587,7 +587,8 @@ public class Calendar extends AbstractComponent implements getTimeZone()); Action[] actions = actionHandler.getActions(range, this); if (actions != null) { - Set actionSet = new HashSet(Arrays.asList(actions)); + Set actionSet = new LinkedHashSet( + Arrays.asList(actions)); actionMap.put(range, actionSet); } } @@ -1872,4 +1873,4 @@ public class Calendar extends AbstractComponent implements dropHandler.getAcceptCriterion().paint(target); } } -} \ No newline at end of file +} -- cgit v1.2.3 From f5e3663d1fda0a5766dd1cfbb48eb31795ad93ff Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Fri, 19 Jul 2013 15:25:40 +0300 Subject: Document multiple load semantics in @StyleSheet and @JavaScript (#12200) Change-Id: Id52f196ad6d14e8077482b19a8d0479aedc64db3 --- server/src/com/vaadin/annotations/JavaScript.java | 14 +++++++++++++- server/src/com/vaadin/annotations/StyleSheet.java | 14 +++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) (limited to 'server/src') diff --git a/server/src/com/vaadin/annotations/JavaScript.java b/server/src/com/vaadin/annotations/JavaScript.java index f2085556c7..bdba70c095 100644 --- a/server/src/com/vaadin/annotations/JavaScript.java +++ b/server/src/com/vaadin/annotations/JavaScript.java @@ -29,9 +29,21 @@ import com.vaadin.server.ClientConnector; * method for the corresponding client-side connector is invoked. *

* Absolute URLs including protocol and host are used as is on the client-side. - * Relative urls are mapped to APP/PUBLISHED/[url] which are by default served + * Relative URLs are mapped to APP/PUBLISHED/[url] which are by default served * from the classpath relative to the class where the annotation is defined. *

+ * The file is only loaded if it has not already been loaded, determined as + * follows: + *

    + *
  • For absolute URLs, the URL is considered loaded if the same URL has + * previously been loaded using {@code @JavaScript} or if a script tag loaded + * from the same URL was present in the DOM when the Vaadin client-side was + * initialized. + *
  • For relative URLs, the URL is considered loaded if another file with the + * same name has already been loaded using {@code @JavaScript}, even if that + * file was loaded from a different folder. + *
+ *

* Example: {@code @JavaScript( "http://host.com/file1.js", "file2.js"})} on the * class com.example.MyConnector would load the file http://host.com/file1.js as * is and file2.js from /com/example/file2.js on the server's classpath using diff --git a/server/src/com/vaadin/annotations/StyleSheet.java b/server/src/com/vaadin/annotations/StyleSheet.java index 2e15d9481c..6540633f8f 100644 --- a/server/src/com/vaadin/annotations/StyleSheet.java +++ b/server/src/com/vaadin/annotations/StyleSheet.java @@ -29,9 +29,21 @@ import com.vaadin.server.ClientConnector; * method for the corresponding client-side connector is invoked. *

* Absolute URLs including protocol and host are used as is on the client-side. - * Relative urls are mapped to APP/PUBLISHED/[url] which are by default served + * Relative URLs are mapped to APP/PUBLISHED/[url] which are by default served * from the classpath relative to the class where the annotation is defined. *

+ * The file is only loaded if it has not already been loaded, determined as + * follows: + *

    + *
  • For absolute URLs, the URL is considered loaded if the same URL has + * previously been loaded using {@code StyleSheet} or if a + * {@code } tag using the same URL was present in the DOM + * when the Vaadin client-side was initialized. + *
  • For relative URLs, the URL is considered loaded if another file with the + * same name has already been loaded using {@code StyleSheet}, even if that file + * was loaded from a different folder. + *
+ *

* Special Vaadin urls are also supported. The most useful is vaadin:// which * maps to the location of the automatically published VAADIN folder. Using the * VAADIN folder and vaadin:// you can publish stylesheets which use images or -- cgit v1.2.3 From 7fc105440755357d469d87b9523afc6f84e0bda7 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Thu, 1 Aug 2013 11:53:34 +0300 Subject: Ensure StringToIntegerConverter rejects values outside range of int (#12230) Change-Id: I150bee64144045355bfa75ac10ede663d3feb5ce --- .../data/util/converter/StringToIntegerConverter.java | 17 ++++++++++++++++- .../data/converter/TestStringToIntegerConverter.java | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) (limited to 'server/src') diff --git a/server/src/com/vaadin/data/util/converter/StringToIntegerConverter.java b/server/src/com/vaadin/data/util/converter/StringToIntegerConverter.java index bc436112fe..f6f668ad4d 100644 --- a/server/src/com/vaadin/data/util/converter/StringToIntegerConverter.java +++ b/server/src/com/vaadin/data/util/converter/StringToIntegerConverter.java @@ -62,7 +62,22 @@ public class StringToIntegerConverter extends Class targetType, Locale locale) throws ConversionException { Number n = convertToNumber(value, targetType, locale); - return n == null ? null : n.intValue(); + + if (n == null) { + return null; + } + + int intValue = n.intValue(); + if (intValue == n.longValue()) { + // If the value of n is outside the range of long, the return value + // of longValue() is either Long.MIN_VALUE or Long.MAX_VALUE. The + // above comparison promotes int to long and thus does not need to + // consider wrap-around. + return intValue; + } + + throw new ConversionException("Could not convert '" + value + "' to " + + Integer.class.getName() + ": value out of range"); } diff --git a/server/tests/src/com/vaadin/tests/data/converter/TestStringToIntegerConverter.java b/server/tests/src/com/vaadin/tests/data/converter/TestStringToIntegerConverter.java index c73853578e..e810106631 100644 --- a/server/tests/src/com/vaadin/tests/data/converter/TestStringToIntegerConverter.java +++ b/server/tests/src/com/vaadin/tests/data/converter/TestStringToIntegerConverter.java @@ -2,6 +2,7 @@ package com.vaadin.tests.data.converter; import junit.framework.TestCase; +import com.vaadin.data.util.converter.Converter.ConversionException; import com.vaadin.data.util.converter.StringToIntegerConverter; public class TestStringToIntegerConverter extends TestCase { @@ -16,6 +17,23 @@ public class TestStringToIntegerConverter extends TestCase { assertEquals(null, converter.convertToModel("", Integer.class, null)); } + public void testValueOutOfRange() { + Double[] values = new Double[] { Integer.MAX_VALUE * 2.0, + Integer.MIN_VALUE * 2.0, Long.MAX_VALUE * 2.0, + Long.MIN_VALUE * 2.0 }; + + boolean accepted = false; + for (Number value : values) { + try { + converter.convertToModel(String.format("%.0f", value), + Integer.class, null); + accepted = true; + } catch (ConversionException expected) { + } + } + assertFalse("Accepted value outside range of int", accepted); + } + public void testValueConversion() { assertEquals(Integer.valueOf(10), converter.convertToModel("10", Integer.class, null)); -- cgit v1.2.3 From f5872981ddf8ff274a12ee59d7a0116e61bde602 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Fri, 2 Aug 2013 08:32:45 +0300 Subject: Improve URI fragment listener javadocs (#12296) Change-Id: I7c91768f02d04c613f25e5984cb015067465815c --- server/src/com/vaadin/server/Page.java | 53 +++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 7 deletions(-) (limited to 'server/src') diff --git a/server/src/com/vaadin/server/Page.java b/server/src/com/vaadin/server/Page.java index 4dd7d34e38..3656309be5 100644 --- a/server/src/com/vaadin/server/Page.java +++ b/server/src/com/vaadin/server/Page.java @@ -244,9 +244,23 @@ public class Page implements Serializable { public static final BorderStyle BORDER_DEFAULT = BorderStyle.DEFAULT; /** - * Listener that listens to changes in URI fragment. + * Listener that that gets notified when the URI fragment of the page + * changes. + * + * @see Page#addUriFragmentChangedListener(UriFragmentChangedListener) */ public interface UriFragmentChangedListener extends Serializable { + /** + * Event handler method invoked when the URI fragment of the page + * changes. Please note that the initial URI fragment has already been + * set when a new UI is initialized, so there will not be any initial + * event for listeners added during {@link UI#init(VaadinRequest)}. + * + * @see Page#addUriFragmentChangedListener(UriFragmentChangedListener) + * + * @param event + * the URI fragment changed event + */ public void uriFragmentChanged(UriFragmentChangedEvent event); } @@ -267,12 +281,14 @@ public class Page implements Serializable { private List notifications; /** - * Event fired when uri fragment changes. + * Event fired when the URI fragment of a Page changes. + * + * @see Page#addUriFragmentChangedListener(UriFragmentChangedListener) */ public static class UriFragmentChangedEvent extends EventObject { /** - * The new uri fragment + * The new URI fragment */ private final String uriFragment; @@ -281,6 +297,8 @@ public class Page implements Serializable { * * @param source * the Source of the event. + * @param uriFragment + * the new uriFragment */ public UriFragmentChangedEvent(Page source, String uriFragment) { super(source); @@ -288,16 +306,16 @@ public class Page implements Serializable { } /** - * Gets the uI in which the fragment has changed. + * Gets the page in which the fragment has changed. * - * @return the uI in which the fragment has changed + * @return the page in which the fragment has changed */ public Page getPage() { return (Page) getSource(); } /** - * Get the new fragment + * Get the new URI fragment * * @return the new fragment */ @@ -476,6 +494,19 @@ public class Page implements Serializable { } } + /** + * Adds a listener that gets notified every time the URI fragment of this + * page is changed. Please note that the initial URI fragment has already + * been set when a new UI is initialized, so there will not be any initial + * event for listeners added during {@link UI#init(VaadinRequest)}. + * + * @see #getUriFragment() + * @see #setUriFragment(String) + * @see #removeUriFragmentChangedListener(UriFragmentChangedListener) + * + * @param listener + * the URI fragment listener to add + */ public void addUriFragmentChangedListener( Page.UriFragmentChangedListener listener) { addListener(UriFragmentChangedEvent.class, listener, @@ -491,6 +522,14 @@ public class Page implements Serializable { addUriFragmentChangedListener(listener); } + /** + * Removes a URI fragment listener that was previously added to this page. + * + * @param listener + * the URI fragment listener to remove + * + * @see Page#addUriFragmentChangedListener(UriFragmentChangedListener) + */ public void removeUriFragmentChangedListener( Page.UriFragmentChangedListener listener) { removeListener(UriFragmentChangedEvent.class, listener, @@ -520,7 +559,7 @@ public class Page implements Serializable { * * @param newUriFragment * The new fragment. - * @param fireEvent + * @param fireEvents * true to fire event * * @see #getUriFragment() -- cgit v1.2.3 From d97cfbc9a1409582bbe4456f08f648921b7e3300 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Fri, 2 Aug 2013 10:20:40 +0300 Subject: Refine handling of null and empty URI fragments (#12207) Change-Id: Ie133694b010a586c6336e9b04be7bcd94d2525e9 --- .../src/com/vaadin/client/ui/ui/UIConnector.java | 23 ++++++-- server/src/com/vaadin/server/Page.java | 14 +++-- .../tests/components/ui/UriFragmentTest.html | 61 +++++++++++++++++++++- .../tests/components/ui/UriFragmentTest.java | 15 ++++++ 4 files changed, 105 insertions(+), 8 deletions(-) (limited to 'server/src') diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java index 45b0a7ab9d..c6d2e1436b 100644 --- a/client/src/com/vaadin/client/ui/ui/UIConnector.java +++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java @@ -40,6 +40,7 @@ import com.google.gwt.user.client.Event; import com.google.gwt.user.client.History; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.Window.Location; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; import com.google.web.bindery.event.shared.HandlerRegistration; @@ -352,14 +353,30 @@ public class UIConnector extends AbstractSingleComponentContainerConnector if (uidl.hasAttribute(UIConstants.LOCATION_VARIABLE)) { String location = uidl .getStringAttribute(UIConstants.LOCATION_VARIABLE); + String newFragment; + int fragmentIndex = location.indexOf('#'); if (fragmentIndex >= 0) { // Decode fragment to avoid double encoding (#10769) - getWidget().currentFragment = URL.decodePathSegment(location + newFragment = URL.decodePathSegment(location .substring(fragmentIndex + 1)); + + if (newFragment.isEmpty() + && Location.getHref().indexOf('#') == -1) { + // Ensure there is a trailing # even though History and + // Location.getHash() treat null and "" the same way. + Location.assign(Location.getHref() + "#"); + } + } else { + // No fragment in server-side location, but can't completely + // remove the browser fragment since that would reload the page + newFragment = ""; } - if (!getWidget().currentFragment.equals(History.getToken())) { - History.newItem(getWidget().currentFragment, true); + + getWidget().currentFragment = newFragment; + + if (!newFragment.equals(History.getToken())) { + History.newItem(newFragment, true); } } diff --git a/server/src/com/vaadin/server/Page.java b/server/src/com/vaadin/server/Page.java index 3656309be5..037d8e8352 100644 --- a/server/src/com/vaadin/server/Page.java +++ b/server/src/com/vaadin/server/Page.java @@ -552,10 +552,11 @@ public class Page implements Serializable { * The fragment is the optional last component of a URI, prefixed with a * hash sign ("#"). *

- * Passing null as newFragment clears the fragment - * (no "#" in the URI); passing an empty string sets an empty fragment (a - * trailing "#" in the URI.) This is consistent with the semantics of - * {@link java.net.URI}. + * Passing an empty string as newFragment sets an empty + * fragment (a trailing "#" in the URI.) Passing null if there + * is already a non-null fragment will leave a trailing # in the URI since + * removing it would cause the browser to reload the page. This is not fully + * consistent with the semantics of {@link java.net.URI}. * * @param newUriFragment * The new fragment. @@ -570,6 +571,11 @@ public class Page implements Serializable { */ public void setUriFragment(String newUriFragment, boolean fireEvents) { String oldUriFragment = location.getFragment(); + if (newUriFragment == null && getUriFragment() != null) { + // Can't completely remove the fragment once it has been set, will + // instead set it to the empty string + newUriFragment = ""; + } if (newUriFragment == oldUriFragment || (newUriFragment != null && newUriFragment .equals(oldUriFragment))) { diff --git a/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.html b/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.html index bcb9f52afe..ba24b55f64 100644 --- a/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.html +++ b/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.html @@ -71,7 +71,66 @@ vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0] Current URI fragment: test - + + + open + /run/ + + + + open + /run/com.vaadin.tests.components.ui.UriFragmentTest?restartApplication + + + + + assertText + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0] + No URI fragment set + + + click + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VButton[0]/domChild[0]/domChild[0] + + + + + assertText + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0] + No URI fragment set + + + click + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0] + + + + + assertText + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0] + Current URI fragment: + + + click + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VButton[0]/domChild[0]/domChild[0] + + + + assertText + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0] + Current URI fragment: test + + + click + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VButton[0]/domChild[0]/domChild[0] + + + + + assertText + vaadin=runcomvaadintestscomponentsuiUriFragmentTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0] + Current URI fragment: + diff --git a/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.java b/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.java index 2172b00ee3..bfd784280a 100644 --- a/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.java +++ b/uitest/src/com/vaadin/tests/components/ui/UriFragmentTest.java @@ -29,6 +29,21 @@ public class UriFragmentTest extends AbstractTestUI { getPage().setUriFragment("test"); } })); + + addComponent(new Button("Navigate to #", new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + getPage().setUriFragment(""); + } + })); + + addComponent(new Button("setUriFragment(null)", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + getPage().setUriFragment(null); + } + })); } private void updateLabel() { -- cgit v1.2.3