From 7cb49d10de85b038b3f7068bf87b6c10315d3c21 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Patrik=20Lindstr=C3=B6m?= Date: Mon, 29 Jul 2013 15:09:35 +0300 Subject: [PATCH] Fix invisible calendar actions menu #12181 Change-Id: I4cdf3d1e584f1537f0f216ddd6f65c1ec4a2ee6b --- client/src/com/vaadin/client/ui/Action.java | 12 ++ .../client/ui/calendar/CalendarConnector.java | 107 +++++++++---- server/src/com/vaadin/ui/Calendar.java | 1 + .../calendar/CalendarDateRange.java | 11 ++ .../calendar/CalendarActionsMenuTest.html | 71 +++++++++ .../calendar/CalendarActionsMenuTest.java | 141 ++++++++++++++++++ 6 files changed, 314 insertions(+), 29 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/calendar/CalendarActionsMenuTest.html create mode 100644 uitest/src/com/vaadin/tests/components/calendar/CalendarActionsMenuTest.java diff --git a/client/src/com/vaadin/client/ui/Action.java b/client/src/com/vaadin/client/ui/Action.java index ffc3c4c7d4..e1b85dcb82 100644 --- a/client/src/com/vaadin/client/ui/Action.java +++ b/client/src/com/vaadin/client/ui/Action.java @@ -67,4 +67,16 @@ public abstract class Action implements Command { public void setIconUrl(String url) { iconUrl = url; } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "Action [owner=" + owner + ", iconUrl=" + iconUrl + ", caption=" + + caption + "]"; + } + } diff --git a/client/src/com/vaadin/client/ui/calendar/CalendarConnector.java b/client/src/com/vaadin/client/ui/calendar/CalendarConnector.java index 5a83579d46..49cd2386ac 100644 --- a/client/src/com/vaadin/client/ui/calendar/CalendarConnector.java +++ b/client/src/com/vaadin/client/ui/calendar/CalendarConnector.java @@ -17,6 +17,7 @@ package com.vaadin.client.ui.calendar; import java.text.ParseException; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Iterator; @@ -267,6 +268,18 @@ public class CalendarConnector extends AbstractComponentConnector implements return CalendarConnector.this.getActionsBetween( start, end); + + } else if (widget instanceof MonthEventLabel) { + MonthEventLabel mel = (MonthEventLabel) widget; + CalendarEvent event = mel.getCalendarEvent(); + Action[] actions = CalendarConnector.this + .getActionsBetween(event.getStartTime(), + event.getEndTime()); + for (Action action : actions) { + ((VCalendarAction) action).setEvent(event); + } + return actions; + } else if (widget instanceof DateCell) { /* * Week and Day view @@ -284,22 +297,15 @@ public class CalendarConnector extends AbstractComponentConnector implements */ DateCellDayEvent dayEvent = (DateCellDayEvent) widget; CalendarEvent event = dayEvent.getCalendarEvent(); + Action[] actions = CalendarConnector.this .getActionsBetween(event.getStartTime(), event.getEndTime()); + for (Action action : actions) { ((VCalendarAction) action).setEvent(event); } - return actions; - } else if (widget instanceof MonthEventLabel) { - MonthEventLabel mel = (MonthEventLabel) widget; - CalendarEvent event = mel.getCalendarEvent(); - Action[] actions = CalendarConnector.this - .getActionsBetween(event.getStartTime(), - event.getEndTime()); - for (Action action : actions) { - ((VCalendarAction) action).setEvent(event); - } + return actions; } return null; @@ -456,27 +462,55 @@ public class CalendarConnector extends AbstractComponentConnector implements private Action[] getActionsBetween(Date start, Date end) { List actions = new ArrayList(); + List ids = new ArrayList(); + for (int i = 0; i < actionKeys.size(); i++) { - final String actionKey = actionKeys.get(i); - Date actionStartDate; - Date actionEndDate; - try { - actionStartDate = getActionStartDate(actionKey); - actionEndDate = getActionEndDate(actionKey); - } catch (ParseException pe) { - VConsole.error("Failed to parse action date"); - continue; - } + String actionKey = actionKeys.get(i); + String id = getActionID(actionKey); + if (!ids.contains(id)) { + + Date actionStartDate; + Date actionEndDate; + try { + actionStartDate = getActionStartDate(actionKey); + actionEndDate = getActionEndDate(actionKey); + } catch (ParseException pe) { + VConsole.error("Failed to parse action date"); + continue; + } - boolean startIsValid = start.compareTo(actionStartDate) >= 0; - boolean endIsValid = end.compareTo(actionEndDate) <= 0; - if (startIsValid && endIsValid) { - VCalendarAction a = new VCalendarAction(this, rpc, actionKey); - a.setCaption(getActionCaption(actionKey)); - a.setIconUrl(getActionIcon(actionKey)); - a.setActionStartDate(start); - a.setActionEndDate(end); - actions.add(a); + // Case 0: action inside event timeframe + // Action should start AFTER or AT THE SAME TIME as the event, + // and + // Action should end BEFORE or AT THE SAME TIME as the event + boolean test0 = actionStartDate.compareTo(start) >= 0 + && actionEndDate.compareTo(end) <= 0; + + // Case 1: action intersects start of timeframe + // Action end time must be between start and end of event + boolean test1 = actionEndDate.compareTo(start) > 0 + && actionEndDate.compareTo(end) <= 0; + + // Case 2: action intersects end of timeframe + // Action start time must be between start and end of event + boolean test2 = actionStartDate.compareTo(start) >= 0 + && actionStartDate.compareTo(end) < 0; + + // Case 3: event inside action timeframe + // Action should start AND END before the event is complete + boolean test3 = start.compareTo(actionStartDate) >= 0 + && end.compareTo(actionEndDate) <= 0; + + if (test0 || test1 || test2 || test3) { + VCalendarAction a = new VCalendarAction(this, rpc, + actionKey); + a.setCaption(getActionCaption(actionKey)); + a.setIconUrl(getActionIcon(actionKey)); + a.setActionStartDate(start); + a.setActionEndDate(end); + actions.add(a); + ids.add(id); + } } } @@ -496,6 +530,7 @@ public class CalendarConnector extends AbstractComponentConnector implements for (CalendarState.Action action : actions) { String id = action.actionKey + "-" + action.startDate + "-" + action.endDate; + actionMap.put(id + "_k", action.actionKey); actionMap.put(id + "_c", action.caption); actionMap.put(id + "_s", action.startDate); actionMap.put(id + "_e", action.endDate); @@ -507,6 +542,20 @@ public class CalendarConnector extends AbstractComponentConnector implements actionMap.remove(id + "_i"); } } + + Collections.sort(actionKeys); + } + + /** + * Get the original action ID that was passed in from the shared state + * + * @since 7.1.2 + * @param actionKey + * the unique action key + * @return + */ + public String getActionID(String actionKey) { + return actionMap.get(actionKey + "_k"); } /** 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 + "]"; + } + } diff --git a/uitest/src/com/vaadin/tests/components/calendar/CalendarActionsMenuTest.html b/uitest/src/com/vaadin/tests/components/calendar/CalendarActionsMenuTest.html new file mode 100644 index 0000000000..3830faa7de --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/calendar/CalendarActionsMenuTest.html @@ -0,0 +1,71 @@ + + + + + + +New Test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
New Test
open/run/com.vaadin.tests.components.calendar.CalendarActionsMenuTest?restartApplication
contextmenuvaadin=runcomvaadintestscomponentscalendarCalendarActionsMenuTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VCalendar[0]/domChild[0]/domChild[1]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[1]
assertText//td[@id='gwt-uid-5']/divACTION
mouseClickvaadin=runcomvaadintestscomponentscalendarCalendarActionsMenuTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VCalendar[0]/domChild[0]/domChild[1]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[2]127,5
mouseClickvaadin=runcomvaadintestscomponentscalendarCalendarActionsMenuTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VCalendar[0]/domChild[0]/domChild[1]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]155,9
contextmenuvaadin=runcomvaadintestscomponentscalendarCalendarActionsMenuTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VCalendar[0]/domChild[0]/domChild[3]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]/domChild[0]/domChild[34]/domChild[1]
assertText//td[@id='gwt-uid-6']/divACTION
mouseClickvaadin=runcomvaadintestscomponentscalendarCalendarActionsMenuTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VCalendar[0]/domChild[0]/domChild[3]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]/domChild[0]/domChild[13]139,0
contextmenuvaadin=runcomvaadintestscomponentscalendarCalendarActionsMenuTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VCalendar[0]/domChild[0]/domChild[3]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]/domChild[0]/domChild[14]
assertText//td[@id='gwt-uid-14']/divACTION
mouseClickvaadin=runcomvaadintestscomponentscalendarCalendarActionsMenuTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VCalendar[0]/domChild[0]/domChild[3]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]/domChild[0]/domChild[13]139,0
+ + diff --git a/uitest/src/com/vaadin/tests/components/calendar/CalendarActionsMenuTest.java b/uitest/src/com/vaadin/tests/components/calendar/CalendarActionsMenuTest.java new file mode 100644 index 0000000000..77225b2e4c --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/calendar/CalendarActionsMenuTest.java @@ -0,0 +1,141 @@ +/* + * Copyright 2000-2013 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.tests.components.calendar; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import com.vaadin.event.Action; +import com.vaadin.event.Action.Handler; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Calendar; +import com.vaadin.ui.Calendar.TimeFormat; +import com.vaadin.ui.Notification; +import com.vaadin.ui.components.calendar.CalendarComponentEvents.EventClick; +import com.vaadin.ui.components.calendar.CalendarComponentEvents.EventClickHandler; +import com.vaadin.ui.components.calendar.CalendarComponentEvents.EventMoveHandler; +import com.vaadin.ui.components.calendar.CalendarComponentEvents.EventResizeHandler; +import com.vaadin.ui.components.calendar.CalendarComponentEvents.MoveEvent; +import com.vaadin.ui.components.calendar.event.BasicEvent; +import com.vaadin.ui.components.calendar.event.CalendarEvent; +import com.vaadin.ui.components.calendar.event.CalendarEventProvider; + +public class CalendarActionsMenuTest extends AbstractTestUI { + + private Calendar calendar; + + @Override + protected void setup(VaadinRequest request) { + calendar = new Calendar(new CalendarEventProvider() { + + @Override + public List getEvents( + Date startDate, Date endDate) { + + List events = new ArrayList(); + + CalendarEvent event = null; + try { + event = new BasicEvent("NAME", "TOOLTIP", + new SimpleDateFormat("yyyy-MM-dd hh:mm") + .parse("2013-01-01 07:00"), + new SimpleDateFormat("yyyy-MM-dd hh:mm") + .parse("2013-01-01 11:00")); + } catch (ParseException e) { + // Nothing to do + } + events.add(event); + + try { + event = new BasicEvent("NAME 2", "TOOLTIP2", + new SimpleDateFormat("yyyy-MM-dd hh:mm") + .parse("2013-01-03 07:00"), + new SimpleDateFormat("yyyy-MM-dd hh:mm") + .parse("2013-01-04 11:00")); + } catch (ParseException e) { + // Nothing to do + } + events.add(event); + + return events; + } + + }); + try { + calendar.setStartDate(new SimpleDateFormat("yyyy-MM-dd") + .parse("2013-01-01")); + calendar.setEndDate(new SimpleDateFormat("yyyy-MM-dd") + .parse("2013-01-31")); + } catch (ParseException e) { + // Nothing to do + } + calendar.setImmediate(true); + calendar.setFirstVisibleHourOfDay(6); + calendar.setLastVisibleHourOfDay(22); + calendar.setTimeFormat(TimeFormat.Format24H); + calendar.setHandler((EventResizeHandler) null); + + setEnabled(true); + calendar.addActionHandler(new Handler() { + @Override + public void handleAction(Action action, Object sender, Object target) { + Notification.show("ACTION CLICKED"); + + } + + @Override + public Action[] getActions(Object target, Object sender) { + return new Action[] { new Action("ACTION") }; + } + }); + calendar.setHandler(new EventClickHandler() { + private static final long serialVersionUID = -177173530105538438L; + + @Override + public void eventClick(EventClick event) { + Notification.show("EVENT CLICKED"); + } + }); + + calendar.setHandler(new EventMoveHandler() { + @Override + public void eventMove(MoveEvent event) { + Notification.show("EVENT MOVED"); + } + }); + addComponent(calendar); + calendar.setSizeFull(); + setSizeFull(); + + } + + @Override + protected String getTestDescription() { + // TODO Auto-generated method stub + return "The context should appear if you right click on a calendar event regardless of view mode"; + } + + @Override + protected Integer getTicketNumber() { + // TODO Auto-generated method stub + return 12181; + } + +} -- 2.39.5