]> source.dussan.org Git - vaadin-framework.git/commitdiff
Fix invisible calendar actions menu #12181
authorPatrik Lindström <patrik@vaadin.com>
Mon, 29 Jul 2013 12:09:35 +0000 (15:09 +0300)
committerVaadin Code Review <review@vaadin.com>
Tue, 30 Jul 2013 11:33:18 +0000 (11:33 +0000)
Change-Id: I4cdf3d1e584f1537f0f216ddd6f65c1ec4a2ee6b

client/src/com/vaadin/client/ui/Action.java
client/src/com/vaadin/client/ui/calendar/CalendarConnector.java
server/src/com/vaadin/ui/Calendar.java
server/src/com/vaadin/ui/components/calendar/CalendarDateRange.java
uitest/src/com/vaadin/tests/components/calendar/CalendarActionsMenuTest.html [new file with mode: 0644]
uitest/src/com/vaadin/tests/components/calendar/CalendarActionsMenuTest.java [new file with mode: 0644]

index ffc3c4c7d4d8aac84ee4eea4a735a57b0667503a..e1b85dcb829aba51df8c0f733984ab54d32e98a0 100644 (file)
@@ -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 + "]";
+    }
+
 }
index 5a83579d4633c2f057b18859c7374c791a7bf6e3..49cd2386acf071444accc392c8387718add6ebd0 100644 (file)
@@ -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<Action> actions = new ArrayList<Action>();
+        List<String> ids = new ArrayList<String>();
+
         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");
     }
 
     /**
index c3385baa2ce9d87b35f27eaa3bc687ed30034ff8..8b8cc7b4752b238d4e1191168c59ee060d5671c5 100644 (file)
@@ -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);
index 01b766a6dbf4b82441fd6ce561d8df5038a17811..b78fda31369fd26ec1651b04e0e057ad5a84bcc5 100644 (file)
@@ -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 (file)
index 0000000..3830faa
--- /dev/null
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+    <td>open</td>
+    <td>/run/com.vaadin.tests.components.calendar.CalendarActionsMenuTest?restartApplication</td>
+    <td></td>
+</tr>
+<tr>
+    <td>contextmenu</td>
+    <td>vaadin=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]</td>
+    <td></td>
+</tr>
+<tr>
+    <td>assertText</td>
+    <td>//td[@id='gwt-uid-5']/div</td>
+    <td>ACTION</td>
+</tr>
+<tr>
+    <td>mouseClick</td>
+    <td>vaadin=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]</td>
+    <td>127,5</td>
+</tr>
+<tr>
+    <td>mouseClick</td>
+    <td>vaadin=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]</td>
+    <td>155,9</td>
+</tr>
+<tr>
+    <td>contextmenu</td>
+    <td>vaadin=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]</td>
+    <td></td>
+</tr>
+<tr>
+    <td>assertText</td>
+    <td>//td[@id='gwt-uid-6']/div</td>
+    <td>ACTION</td>
+</tr>
+<tr>
+    <td>mouseClick</td>
+    <td>vaadin=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]</td>
+    <td>139,0</td>
+</tr>
+<tr>
+    <td>contextmenu</td>
+    <td>vaadin=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]</td>
+    <td></td>
+</tr>
+<tr>
+    <td>assertText</td>
+    <td>//td[@id='gwt-uid-14']/div</td>
+    <td>ACTION</td>
+</tr>
+<tr>
+    <td>mouseClick</td>
+    <td>vaadin=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]</td>
+    <td>139,0</td>
+</tr>
+</tbody></table>
+</body>
+</html>
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 (file)
index 0000000..77225b2
--- /dev/null
@@ -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<com.vaadin.ui.components.calendar.event.CalendarEvent> getEvents(
+                    Date startDate, Date endDate) {
+
+                List<CalendarEvent> events = new ArrayList<CalendarEvent>();
+
+                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;
+    }
+
+}