summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis <denis@vaadin.com>2016-12-14 13:50:06 +0200
committerIlia Motornyi <elmot@vaadin.com>2016-12-14 13:50:06 +0200
commitfc011f6a8a08064f48fd5f4280f1d4d3647ab7f1 (patch)
tree3cb8e0f9022aa752b55e9f83f209388e1557b0ba
parent692bbef040a61388d8ba028a9701a760b64baa43 (diff)
downloadvaadin-framework-fc011f6a8a08064f48fd5f4280f1d4d3647ab7f1.tar.gz
vaadin-framework-fc011f6a8a08064f48fd5f4280f1d4d3647ab7f1.zip
Provide configuration for events order in month and week views
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/ui/VCalendar.java227
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/ui/calendar/CalendarConnector.java29
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/ui/calendar/schedule/DateCell.java3
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/ui/Calendar.java31
-rw-r--r--compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/calendar/CalendarState.java26
-rw-r--r--uitest/src/main/java/com/vaadin/v7/tests/components/calendar/CalendarEventsSort.java223
-rw-r--r--uitest/src/test/java/com/vaadin/v7/tests/components/calendar/CalendarEventsSortTest.java183
7 files changed, 672 insertions, 50 deletions
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VCalendar.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VCalendar.java
index 9130a3faec..57bde573c6 100644
--- a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VCalendar.java
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VCalendar.java
@@ -41,6 +41,7 @@ import com.vaadin.v7.client.ui.calendar.schedule.SimpleWeekToolbar;
import com.vaadin.v7.client.ui.calendar.schedule.WeekGrid;
import com.vaadin.v7.client.ui.calendar.schedule.WeeklyLongEvents;
import com.vaadin.v7.client.ui.calendar.schedule.dd.CalendarDropHandler;
+import com.vaadin.v7.shared.ui.calendar.CalendarState.EventSortOrder;
import com.vaadin.v7.shared.ui.calendar.DateConstants;
/**
@@ -98,6 +99,11 @@ public class VCalendar extends Composite implements VHasDropHandler {
private int firstHour;
private int lastHour;
+ private EventSortOrder eventSortOrder = EventSortOrder.DURATION_DESC;
+
+ private static EventDurationComparator DEFAULT_COMPARATOR = new EventDurationComparator(
+ false);
+
private CalendarDropHandler dropHandler;
/**
@@ -241,6 +247,106 @@ public class VCalendar extends Composite implements VHasDropHandler {
void contextMenu(ContextMenuEvent event, Widget widget);
}
+ private static abstract class AbstractEventComparator
+ implements Comparator<CalendarEvent> {
+
+ @Override
+ public int compare(CalendarEvent e1, CalendarEvent e2) {
+ if (e1.isAllDay() != e2.isAllDay()) {
+ if (e2.isAllDay()) {
+ return 1;
+ }
+ return -1;
+ }
+ int result = doCompare(e1, e2);
+ if (result == 0) {
+ return indexCompare(e1, e2);
+ }
+ return result;
+ }
+
+ protected int indexCompare(CalendarEvent e1, CalendarEvent e2) {
+ return ((Integer) e2.getIndex()).compareTo(e1.getIndex());
+ }
+
+ protected abstract int doCompare(CalendarEvent o1, CalendarEvent o2);
+ }
+
+ private static class EventDurationComparator
+ extends AbstractEventComparator {
+
+ EventDurationComparator(boolean ascending) {
+ isAscending = ascending;
+ }
+
+ @Override
+ public int doCompare(CalendarEvent e1, CalendarEvent e2) {
+ int result = durationCompare(e1, e2, isAscending);
+ if (result == 0) {
+ return StartDateComparator.startDateCompare(e1, e2,
+ isAscending);
+ }
+ return result;
+ }
+
+ static int durationCompare(CalendarEvent e1, CalendarEvent e2,
+ boolean ascending) {
+ int result = doDurationCompare(e1, e2);
+ return ascending ? -result : result;
+ }
+
+ private static int doDurationCompare(CalendarEvent e1,
+ CalendarEvent e2) {
+ Long d1 = e1.getRangeInMilliseconds();
+ Long d2 = e2.getRangeInMilliseconds();
+ if (!d1.equals(0L) && !d2.equals(0L)) {
+ return d2.compareTo(d1);
+ }
+
+ if (d2.equals(0L) && d1.equals(0L)) {
+ return 0;
+ } else if (d2.equals(0L) && d1 >= DateConstants.DAYINMILLIS) {
+ return -1;
+ } else if (d2.equals(0L) && d1 < DateConstants.DAYINMILLIS) {
+ return 1;
+ } else if (d1.equals(0L) && d2 >= DateConstants.DAYINMILLIS) {
+ return 1;
+ } else if (d1.equals(0L) && d2 < DateConstants.DAYINMILLIS) {
+ return -1;
+ }
+ return d2.compareTo(d1);
+ }
+
+ private boolean isAscending;
+
+ }
+
+ private static class StartDateComparator extends AbstractEventComparator {
+
+ StartDateComparator(boolean ascending) {
+ isAscending = ascending;
+ }
+
+ @Override
+ public int doCompare(CalendarEvent e1, CalendarEvent e2) {
+ int result = startDateCompare(e1, e2, isAscending);
+ if (result == 0) {
+ // show a longer event after a shorter event
+ return EventDurationComparator.durationCompare(e1, e2,
+ isAscending);
+ }
+ return result;
+ }
+
+ static int startDateCompare(CalendarEvent e1, CalendarEvent e2,
+ boolean ascending) {
+ int result = e1.getStartTime().compareTo(e2.getStartTime());
+ return ascending ? -result : result;
+ }
+
+ private boolean isAscending;
+ }
+
/**
* Default constructor
*/
@@ -262,15 +368,15 @@ public class VCalendar extends Composite implements VHasDropHandler {
e.onselectstart = function() {
return false;
}
-
+
e.ondragstart = function() {
return false;
}
}-*/;
private void updateEventsToWeekGrid(CalendarEvent[] events) {
- List<CalendarEvent> allDayLong = new ArrayList<CalendarEvent>();
- List<CalendarEvent> belowDayLong = new ArrayList<CalendarEvent>();
+ List<CalendarEvent> allDayLong = new ArrayList<>();
+ List<CalendarEvent> belowDayLong = new ArrayList<>();
for (CalendarEvent e : events) {
if (e.isAllDay()) {
@@ -302,7 +408,7 @@ public class VCalendar extends Composite implements VHasDropHandler {
*/
public void updateEventsToMonthGrid(Collection<CalendarEvent> events,
boolean drawImmediately) {
- for (CalendarEvent e : sortEventsByDuration(events)) {
+ for (CalendarEvent e : sortEvents(events)) {
// FIXME Why is drawImmediately not used ?????
addEventToMonthGrid(e, false);
}
@@ -315,8 +421,8 @@ public class VCalendar extends Composite implements VHasDropHandler {
boolean eventAdded = false;
boolean inProgress = false; // Event adding has started
boolean eventMoving = false;
- List<SimpleDayCell> dayCells = new ArrayList<SimpleDayCell>();
- List<SimpleDayCell> timeCells = new ArrayList<SimpleDayCell>();
+ List<SimpleDayCell> dayCells = new ArrayList<>();
+ List<SimpleDayCell> timeCells = new ArrayList<>();
for (int row = 0; row < monthGrid.getRowCount(); row++) {
if (eventAdded) {
break;
@@ -463,12 +569,44 @@ public class VCalendar extends Composite implements VHasDropHandler {
}
/**
+ * Sort the events by current sort order
+ *
+ * @param events
+ * The events to sort
+ * @return An array where the events has been sorted
+ */
+ public CalendarEvent[] sortEvents(Collection<CalendarEvent> events) {
+ if (EventSortOrder.DURATION_DESC.equals(eventSortOrder)) {
+ return sortEventsByDuration(events);
+ } else if (!EventSortOrder.UNSORTED.equals(eventSortOrder)) {
+ CalendarEvent[] sorted = events
+ .toArray(new CalendarEvent[events.size()]);
+ switch (eventSortOrder) {
+ case DURATION_ASC:
+ Arrays.sort(sorted, new EventDurationComparator(true));
+ break;
+ case START_DATE_ASC:
+ Arrays.sort(sorted, new StartDateComparator(true));
+ break;
+ case START_DATE_DESC:
+ Arrays.sort(sorted, new StartDateComparator(false));
+ break;
+ }
+ return sorted;
+ }
+ return events.toArray(new CalendarEvent[events.size()]);
+ }
+
+ /**
* Sort the event by how long they are
- *
+ *
* @param events
* The events to sort
* @return An array where the events has been sorted
+ * @deprecated use {@link #sortEvents(Collection)} method which shorts
+ * events by current sort order.
*/
+ @Deprecated
public CalendarEvent[] sortEventsByDuration(
Collection<CalendarEvent> events) {
CalendarEvent[] sorted = events
@@ -828,49 +966,18 @@ public class VCalendar extends Composite implements VHasDropHandler {
}
/**
- * Returns a comparator which can compare calendar events.
- *
+ * Returns the default comparator which can compare calendar events by
+ * duration.
+ *
+ * @deprecated this returns just one default comparator, but there are
+ * number of comparators that are used to sort events depending
+ * on order.
+ *
* @return
*/
+ @Deprecated
public static Comparator<CalendarEvent> getEventComparator() {
- return new Comparator<CalendarEvent>() {
-
- @Override
- public int compare(CalendarEvent o1, CalendarEvent o2) {
- if (o1.isAllDay() != o2.isAllDay()) {
- if (o2.isAllDay()) {
- return 1;
- }
- return -1;
- }
-
- Long d1 = o1.getRangeInMilliseconds();
- Long d2 = o2.getRangeInMilliseconds();
- int r = 0;
- if (!d1.equals(0L) && !d2.equals(0L)) {
- r = d2.compareTo(d1);
- return (r == 0)
- ? ((Integer) o2.getIndex()).compareTo(o1.getIndex())
- : r;
- }
-
- if (d2.equals(0L) && d1.equals(0L)) {
- return ((Integer) o2.getIndex()).compareTo(o1.getIndex());
- } else if (d2.equals(0L) && d1 >= DateConstants.DAYINMILLIS) {
- return -1;
- } else if (d2.equals(0L) && d1 < DateConstants.DAYINMILLIS) {
- return 1;
- } else if (d1.equals(0L) && d2 >= DateConstants.DAYINMILLIS) {
- return 1;
- } else if (d1.equals(0L) && d2 < DateConstants.DAYINMILLIS) {
- return -1;
- }
- r = d2.compareTo(d1);
- return (r == 0)
- ? ((Integer) o2.getIndex()).compareTo(o1.getIndex())
- : r;
- }
- };
+ return DEFAULT_COMPARATOR;
}
/**
@@ -1086,7 +1193,7 @@ public class VCalendar extends Composite implements VHasDropHandler {
weekGrid = new WeekGrid(this, is24HFormat());
}
updateWeekGrid(daysInMonth, days, today, realDayNames);
- updateEventsToWeekGrid(sortEventsByDuration(events));
+ updateEventsToWeekGrid(sortEvents(events));
outer.add(dayToolbar, DockPanel.NORTH);
outer.add(weeklyLongEvents, DockPanel.NORTH);
outer.add(weekGrid, DockPanel.SOUTH);
@@ -1501,4 +1608,28 @@ public class VCalendar extends Composite implements VHasDropHandler {
public boolean isEventCaptionAsHtml() {
return eventCaptionAsHtml;
}
+
+ /**
+ * Set sort strategy for events.
+ *
+ * @param order
+ * sort order
+ */
+ public void setSortOrder(EventSortOrder order) {
+ if (order == null) {
+ eventSortOrder = EventSortOrder.DURATION_DESC;
+ } else {
+ eventSortOrder = order;
+ }
+ }
+
+ /**
+ * Return currently active sort order.
+ *
+ * @return current sort order
+ */
+ public EventSortOrder getSortOrder() {
+ return eventSortOrder;
+ }
+
}
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/calendar/CalendarConnector.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/calendar/CalendarConnector.java
index 0e50bd639d..456c9f392b 100644
--- a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/calendar/CalendarConnector.java
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/calendar/CalendarConnector.java
@@ -44,6 +44,7 @@ import com.vaadin.client.ui.ActionOwner;
import com.vaadin.client.ui.SimpleManagedLayout;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.Connect.LoadStyle;
+import com.vaadin.shared.util.SharedUtil;
import com.vaadin.v7.client.ui.AbstractLegacyComponentConnector;
import com.vaadin.v7.client.ui.VCalendar;
import com.vaadin.v7.client.ui.VCalendar.BackwardListener;
@@ -71,6 +72,7 @@ import com.vaadin.v7.shared.ui.calendar.CalendarClientRpc;
import com.vaadin.v7.shared.ui.calendar.CalendarEventId;
import com.vaadin.v7.shared.ui.calendar.CalendarServerRpc;
import com.vaadin.v7.shared.ui.calendar.CalendarState;
+import com.vaadin.v7.shared.ui.calendar.CalendarState.EventSortOrder;
import com.vaadin.v7.shared.ui.calendar.DateConstants;
import com.vaadin.v7.ui.Calendar;
@@ -352,6 +354,12 @@ public class CalendarConnector extends AbstractLegacyComponentConnector
widget.setEventCaptionAsHtml(state.eventCaptionAsHtml);
+ EventSortOrder oldOrder = getWidget().getSortOrder();
+ if (!SharedUtil.equals(oldOrder, getState().eventSortOrder)) {
+ getWidget().setSortOrder(getState().eventSortOrder);
+ }
+ updateEventsInView();
+
List<CalendarState.Day> days = state.days;
List<CalendarState.Event> events = state.events;
@@ -449,6 +457,27 @@ public class CalendarConnector extends AbstractLegacyComponentConnector
return true;
}
+ private void updateEventsInView() {
+ CalendarState state = getState();
+ List<CalendarState.Day> days = state.days;
+ List<CalendarState.Event> events = state.events;
+
+ CalendarDropHandler dropHandler = getWidget().getDropHandler();
+ if (showingMonthView()) {
+ updateMonthView(days, events);
+ if (dropHandler != null
+ && !(dropHandler instanceof CalendarMonthDropHandler)) {
+ getWidget().setDropHandler(new CalendarMonthDropHandler(this));
+ }
+ } else {
+ updateWeekView(days, events);
+ if (dropHandler != null
+ && !(dropHandler instanceof CalendarWeekDropHandler)) {
+ getWidget().setDropHandler(new CalendarWeekDropHandler(this));
+ }
+ }
+ }
+
private void updateMonthView(List<CalendarState.Day> days,
List<CalendarState.Event> events) {
CalendarState state = getState();
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/calendar/schedule/DateCell.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/calendar/schedule/DateCell.java
index 31f443cd77..d914de8ff5 100644
--- a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/calendar/schedule/DateCell.java
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/calendar/schedule/DateCell.java
@@ -546,8 +546,7 @@ public class DateCell extends FocusableComplexPanel implements MouseDownHandler,
events.add(dayEvent.getCalendarEvent());
index = 0;
- for (CalendarEvent e : weekgrid.getCalendar()
- .sortEventsByDuration(events)) {
+ for (CalendarEvent e : weekgrid.getCalendar().sortEvents(events)) {
if (e.equals(dayEvent.getCalendarEvent())) {
break;
}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/ui/Calendar.java b/compatibility-server/src/main/java/com/vaadin/v7/ui/Calendar.java
index a33cce6eef..d347028895 100644
--- a/compatibility-server/src/main/java/com/vaadin/v7/ui/Calendar.java
+++ b/compatibility-server/src/main/java/com/vaadin/v7/ui/Calendar.java
@@ -57,6 +57,7 @@ import com.vaadin.v7.data.util.BeanItemContainer;
import com.vaadin.v7.shared.ui.calendar.CalendarEventId;
import com.vaadin.v7.shared.ui.calendar.CalendarServerRpc;
import com.vaadin.v7.shared.ui.calendar.CalendarState;
+import com.vaadin.v7.shared.ui.calendar.CalendarState.EventSortOrder;
import com.vaadin.v7.shared.ui.calendar.DateConstants;
import com.vaadin.v7.ui.components.calendar.CalendarComponentEvent;
import com.vaadin.v7.ui.components.calendar.CalendarComponentEvents;
@@ -999,6 +1000,36 @@ public class Calendar extends AbstractLegacyComponent
}
}
+ /**
+ * Sets sort order for events. By default sort order is
+ * {@link EventSortOrder#DURATION_DESC}.
+ *
+ * @param order
+ * sort strategy for events
+ */
+ public void setEventSortOrder(EventSortOrder order) {
+ if (order == null) {
+ getState().eventSortOrder = EventSortOrder.DURATION_DESC;
+ } else {
+ getState().eventSortOrder = EventSortOrder.values()[order
+ .ordinal()];
+ }
+ }
+
+ /**
+ * Returns sort order for events.
+ *
+ * @return currently active sort strategy
+ */
+ public EventSortOrder getEventSortOrder() {
+ EventSortOrder order = getState(false).eventSortOrder;
+ if (order == null) {
+ return EventSortOrder.DURATION_DESC;
+ } else {
+ return order;
+ }
+ }
+
private DateFormat getWeeklyCaptionFormatter() {
if (weeklyCaptionFormat != null) {
return new SimpleDateFormat(weeklyCaptionFormat, getLocale());
diff --git a/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/calendar/CalendarState.java b/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/calendar/CalendarState.java
index dd15c09b7f..646c7eed44 100644
--- a/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/calendar/CalendarState.java
+++ b/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/calendar/CalendarState.java
@@ -40,6 +40,32 @@ public class CalendarState extends AbstractLegacyComponentState {
public List<CalendarState.Action> actions;
public boolean eventCaptionAsHtml;
+ public EventSortOrder eventSortOrder = EventSortOrder.DURATION_DESC;
+
+ /**
+ * Defines sort strategy for events in calendar month view and week view. In
+ * month view events will be sorted from top to bottom using the order in
+ * day cell. In week view events inside same day will be sorted from left to
+ * right using the order if their intervals are overlapping.
+ * <p>
+ * <ul>
+ * <li>{@code UNSORTED} means no sort. Events will be in the order provided
+ * by com.vaadin.ui.components.calendar.event.CalendarEventProvider.
+ * <li>{@code START_DATE_DESC} means descending sort by events start date
+ * (earlier event are shown first).
+ * <li>{@code DURATION_DESC} means descending sort by duration (longer event
+ * are shown first).
+ * <li>{@code START_DATE_ASC} means ascending sort by events start date
+ * (later event are shown first).
+ * <li>{@code DURATION_ASC} means ascending sort by duration (shorter event
+ * are shown first).
+ *
+ * </ul>
+ */
+ public enum EventSortOrder {
+ UNSORTED, START_DATE_DESC, START_DATE_ASC, DURATION_DESC, DURATION_ASC;
+ }
+
public static class Day implements java.io.Serializable {
public String date;
public String localizedDateFormat;
diff --git a/uitest/src/main/java/com/vaadin/v7/tests/components/calendar/CalendarEventsSort.java b/uitest/src/main/java/com/vaadin/v7/tests/components/calendar/CalendarEventsSort.java
new file mode 100644
index 0000000000..4236aad2c9
--- /dev/null
+++ b/uitest/src/main/java/com/vaadin/v7/tests/components/calendar/CalendarEventsSort.java
@@ -0,0 +1,223 @@
+/*
+ * 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.v7.tests.components.calendar;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.v7.shared.ui.calendar.CalendarState.EventSortOrder;
+import com.vaadin.v7.ui.Calendar;
+import com.vaadin.v7.ui.components.calendar.event.BasicEvent;
+import com.vaadin.v7.ui.components.calendar.event.CalendarEvent;
+import com.vaadin.v7.ui.components.calendar.event.CalendarEventProvider;
+
+/**
+ *
+ * Test UI for event sorting in calendar month and week views.
+ *
+ * @author Vaadin Ltd
+ */
+public class CalendarEventsSort extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ getContent().setSizeFull();
+ final Calendar calendar = new Calendar("Test calendar");
+
+ toMonthView(calendar);
+ calendar.setEventSortOrder(EventSortOrder.UNSORTED);
+
+ calendar.setEventProvider(createEventProvider());
+ addComponent(calendar);
+
+ createSortByDateButton(calendar);
+ createSortByDurationButton(calendar);
+ createSortByProviderButton(calendar);
+ createViewSwitchButton(calendar);
+ }
+
+ private void createViewSwitchButton(final Calendar calendar) {
+ Button toWeek = new Button("Switch to week view", new ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ Button button = event.getButton();
+ Boolean month = (Boolean) button.getData();
+ button.setData(!month);
+ if (month) {
+ button.setCaption("Switch to month view");
+ toWeekView(calendar);
+ } else {
+ button.setCaption("Switch to week view");
+ toMonthView(calendar);
+ }
+ }
+
+ });
+ toWeek.addStyleName("view");
+ toWeek.setData(true);
+ addComponent(toWeek);
+ }
+
+ private Button createSortByProviderButton(final Calendar calendar) {
+ Button byProvider = new Button("Sort by provider", new ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ calendar.setEventSortOrder(EventSortOrder.UNSORTED);
+ }
+ });
+ byProvider.addStyleName("by-provider");
+ addComponent(byProvider);
+ return byProvider;
+ }
+
+ private void createSortByDurationButton(final Calendar calendar) {
+ Button byDuration = new Button("Sort by duration DESC",
+ new ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ Button button = event.getButton();
+ EventSortOrder order = (EventSortOrder) button
+ .getData();
+ if (EventSortOrder.DURATION_DESC.equals(order)) {
+ order = EventSortOrder.DURATION_ASC;
+ button.setCaption("Sort by duration DESC");
+ addSortOrder(true, button);
+ } else {
+ order = EventSortOrder.DURATION_DESC;
+ button.setCaption("Sort by duration ASC");
+ addSortOrder(false, button);
+ }
+ button.setData(order);
+ calendar.setEventSortOrder(order);
+ }
+ });
+ byDuration.addStyleName("by-duration");
+ byDuration.setData(EventSortOrder.DURATION_ASC);
+ addComponent(byDuration);
+ }
+
+ private void createSortByDateButton(final Calendar calendar) {
+ Button byStartDate = new Button("Sort by start date DESC",
+ new ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ Button button = event.getButton();
+ EventSortOrder order = (EventSortOrder) button
+ .getData();
+ if (EventSortOrder.START_DATE_DESC.equals(order)) {
+ order = EventSortOrder.START_DATE_ASC;
+ button.setCaption("Sort by start date DESC");
+ addSortOrder(true, button);
+ } else {
+ order = EventSortOrder.START_DATE_DESC;
+ button.setCaption("Sort by start date ASC");
+ addSortOrder(false, button);
+ }
+ button.setData(order);
+ calendar.setEventSortOrder(order);
+ }
+ });
+ byStartDate.setData(EventSortOrder.START_DATE_ASC);
+ byStartDate.addStyleName("by-start-date");
+ addComponent(byStartDate);
+ }
+
+ private CalendarEventProvider createEventProvider() {
+ CalendarEventProvider provider = new CalendarEventProvider() {
+
+ @Override
+ public List<CalendarEvent> getEvents(Date startDate, Date endDate) {
+ java.util.Calendar cal = java.util.Calendar.getInstance();
+ cal.set(java.util.Calendar.HOUR_OF_DAY, 5);
+ cal.set(java.util.Calendar.MINUTE, 0);
+ cal.set(java.util.Calendar.SECOND, 0);
+ cal.set(java.util.Calendar.MILLISECOND, 0);
+
+ Date start = cal.getTime();
+ cal.add(java.util.Calendar.HOUR_OF_DAY, 2);
+ Date end = cal.getTime();
+
+ CalendarEvent event1 = new BasicEvent("first", "descr1", start,
+ end);
+
+ cal.set(java.util.Calendar.HOUR_OF_DAY, 2);
+ start = cal.getTime();
+ cal.add(java.util.Calendar.HOUR_OF_DAY, 4);
+ end = cal.getTime();
+
+ CalendarEvent event2 = new BasicEvent("second", "descr2", start,
+ end);
+
+ cal.set(java.util.Calendar.HOUR_OF_DAY, 1);
+ start = cal.getTime();
+ cal.add(java.util.Calendar.HOUR_OF_DAY, 2);
+ end = cal.getTime();
+
+ CalendarEvent event3 = new BasicEvent("third", "descr2", start,
+ end);
+
+ return Arrays.asList(event1, event2, event3);
+ }
+
+ };
+ return provider;
+ }
+
+ private void addSortOrder(boolean ascending, Button button) {
+ if (ascending) {
+ button.addStyleName("asc");
+ button.removeStyleName("desc");
+ } else {
+ button.removeStyleName("asc");
+ button.addStyleName("desc");
+ }
+ }
+
+ private void toMonthView(final Calendar calendar) {
+ final java.util.Calendar cal = java.util.Calendar.getInstance();
+
+ cal.add(java.util.Calendar.DAY_OF_YEAR, -2);
+ calendar.setStartDate(cal.getTime());
+ cal.add(java.util.Calendar.DAY_OF_YEAR, 14);
+ calendar.setEndDate(cal.getTime());
+ }
+
+ private void toWeekView(final Calendar calendar) {
+ java.util.Calendar cal = java.util.Calendar.getInstance();
+ cal.add(java.util.Calendar.DAY_OF_YEAR, 2);
+ calendar.setEndDate(cal.getTime());
+ }
+
+ @Override
+ public String getDescription() {
+ return "Make event sorting strategy customizable.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14849;
+ }
+} \ No newline at end of file
diff --git a/uitest/src/test/java/com/vaadin/v7/tests/components/calendar/CalendarEventsSortTest.java b/uitest/src/test/java/com/vaadin/v7/tests/components/calendar/CalendarEventsSortTest.java
new file mode 100644
index 0000000000..27cf549a4f
--- /dev/null
+++ b/uitest/src/test/java/com/vaadin/v7/tests/components/calendar/CalendarEventsSortTest.java
@@ -0,0 +1,183 @@
+/*
+ * 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.v7.tests.components.calendar;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * Check how event sorting works in calendar month and week views.
+ *
+ * @author Vaadin Ltd
+ */
+public class CalendarEventsSortTest extends MultiBrowserTest {
+
+ @Test
+ public void testByDuration() {
+ openTestURL();
+
+ checkSortByDuration(true);
+ }
+
+ @Test
+ public void testByStartDate() {
+ openTestURL();
+
+ checkSortByStartDate(true);
+ }
+
+ @Test
+ public void testByProvider() {
+ openTestURL();
+
+ List<WebElement> events = findElements(
+ By.className("v-calendar-event-month"));
+ checkProviderOrder(events);
+ }
+
+ @Test
+ public void testWeekByDuration() {
+ openTestURL();
+
+ findElement(By.className("view")).click();
+
+ checkSortByDuration(false);
+ }
+
+ @Test
+ public void testWeekByStartDate() {
+ openTestURL();
+
+ findElement(By.className("view")).click();
+
+ checkSortByStartDate(false);
+ }
+
+ @Test
+ public void testWeekByProvider() {
+ openTestURL();
+
+ findElement(By.className("view")).click();
+
+ List<WebElement> events = findElements(
+ By.className("v-calendar-event-caption"));
+ checkProviderOrder(events);
+ }
+
+ private void checkSortByStartDate(boolean month) {
+ sort("by-start-date", false);
+
+ String style = month ? "v-calendar-event-month"
+ : "v-calendar-event-caption";
+ List<WebElement> events = findElements(By.className(style));
+ checkStartDateOrderDesc(events);
+
+ sort("by-start-date", true);
+
+ events = findElements(By.className(style));
+ checkStartDateOrderAsc(events);
+ }
+
+ private void sort(String style, boolean ascending) {
+ findElement(By.className(style)).click();
+
+ if (!isElementPresent(
+ By.cssSelector('.' + style + (ascending ? ".asc" : ".desc")))) {
+ findElement(By.className(style)).click();
+ }
+ }
+
+ private void checkSortByDuration(boolean month) {
+ sort("by-duration", false);
+
+ String style = month ? "v-calendar-event-month"
+ : "v-calendar-event-caption";
+
+ List<WebElement> events = findElements(By.className(style));
+ checkDurationOrderDesc(events);
+
+ sort("by-duration", true);
+ events = findElements(By.className(style));
+ checkDurationOrderAsc(events);
+ }
+
+ private void checkDurationOrderDesc(List<WebElement> events) {
+ Assert.assertTrue(
+ "'Second' event should be the first when sorted by duration",
+ events.get(0).getText().endsWith("second"));
+ Assert.assertTrue(
+ "'Third' event should be the second when sorted by duration",
+ events.get(1).getText().endsWith("third"));
+ Assert.assertTrue(
+ "'First' event should be the third when sorted by duration",
+ events.get(2).getText().endsWith("first"));
+ }
+
+ private void checkDurationOrderAsc(List<WebElement> events) {
+ Assert.assertTrue(
+ "'First' event should be the first when sorted by duration",
+ events.get(0).getText().endsWith("first"));
+ Assert.assertTrue(
+ "'Third' event should be the second when sorted by duration",
+ events.get(1).getText().endsWith("third"));
+ Assert.assertTrue(
+ "'Second' event should be the third when sorted by duration",
+ events.get(2).getText().endsWith("second"));
+ }
+
+ private void checkStartDateOrderDesc(List<WebElement> events) {
+ Assert.assertTrue(
+ "'Third' event should be the first when sorted by start date",
+ events.get(0).getText().endsWith("third"));
+ Assert.assertTrue(
+ "'Second' event should be the second when sorted by start date",
+ events.get(1).getText().endsWith("second"));
+ Assert.assertTrue(
+ "'First' event should be the third when sorted by start date",
+ events.get(2).getText().endsWith("first"));
+ }
+
+ private void checkStartDateOrderAsc(List<WebElement> events) {
+ Assert.assertTrue(
+ "'First' event should be the first when sorted by start date",
+ events.get(0).getText().endsWith("first"));
+ Assert.assertTrue(
+ "'Second' event should be the second when sorted by start date",
+ events.get(1).getText().endsWith("second"));
+ Assert.assertTrue(
+ "'Third' event should be the third when sorted by start date",
+ events.get(2).getText().endsWith("third"));
+ }
+
+ private void checkProviderOrder(List<WebElement> events) {
+ Assert.assertTrue(
+ "'First' event should be the first when sorted by provider",
+ events.get(0).getText().endsWith("first"));
+ Assert.assertTrue(
+ "'Second' event should be the second when sorted by provider",
+ events.get(1).getText().endsWith("second"));
+ Assert.assertTrue(
+ "'Third' event should be the third when sorted by provider",
+ events.get(2).getText().endsWith("third"));
+ }
+
+}