diff options
author | Artur Signell <artur@vaadin.com> | 2016-08-18 22:10:47 +0300 |
---|---|---|
committer | Artur Signell <artur@vaadin.com> | 2016-08-20 00:12:18 +0300 |
commit | fe3dca081a64af892a7f4c0416ecc643aec3ec5a (patch) | |
tree | 1901fb377336d3c5a772335322d9c434a4a75e24 /client | |
parent | 65370e12a0605926cb80e205c2b0e74fefe83e5b (diff) | |
download | vaadin-framework-fe3dca081a64af892a7f4c0416ecc643aec3ec5a.tar.gz vaadin-framework-fe3dca081a64af892a7f4c0416ecc643aec3ec5a.zip |
Move remaining selects and container implementations to compatibility package
Because of dependencies also moves
Calendar, ColorPicker, SQLContainer, container filters
Change-Id: I0594cb24f20486ebbca4be578827fea7cdf92108
Diffstat (limited to 'client')
43 files changed, 0 insertions, 14686 deletions
diff --git a/client/src/main/java/com/vaadin/client/ui/VCalendar.java b/client/src/main/java/com/vaadin/client/ui/VCalendar.java deleted file mode 100644 index 8414d7c99c..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/VCalendar.java +++ /dev/null @@ -1,1504 +0,0 @@ -/* - * Copyright 2000-2016 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; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Comparator; -import java.util.Date; -import java.util.List; - -import com.google.gwt.dom.client.Element; -import com.google.gwt.event.dom.client.ContextMenuEvent; -import com.google.gwt.event.dom.client.ContextMenuHandler; -import com.google.gwt.i18n.client.DateTimeFormat; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.DockPanel; -import com.google.gwt.user.client.ui.ScrollPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.ui.calendar.schedule.CalendarDay; -import com.vaadin.client.ui.calendar.schedule.CalendarEvent; -import com.vaadin.client.ui.calendar.schedule.DayToolbar; -import com.vaadin.client.ui.calendar.schedule.MonthGrid; -import com.vaadin.client.ui.calendar.schedule.SimpleDayCell; -import com.vaadin.client.ui.calendar.schedule.SimpleDayToolbar; -import com.vaadin.client.ui.calendar.schedule.SimpleWeekToolbar; -import com.vaadin.client.ui.calendar.schedule.WeekGrid; -import com.vaadin.client.ui.calendar.schedule.WeeklyLongEvents; -import com.vaadin.client.ui.calendar.schedule.dd.CalendarDropHandler; -import com.vaadin.client.ui.dd.VHasDropHandler; -import com.vaadin.shared.ui.calendar.DateConstants; - -/** - * Client side implementation for Calendar - * - * @since 7.1 - * @author Vaadin Ltd. - */ -public class VCalendar extends Composite implements VHasDropHandler { - - public static final String ATTR_FIRSTDAYOFWEEK = "firstDay"; - public static final String ATTR_LASTDAYOFWEEK = "lastDay"; - public static final String ATTR_FIRSTHOUROFDAY = "firstHour"; - public static final String ATTR_LASTHOUROFDAY = "lastHour"; - - // private boolean hideWeekends; - private String[] monthNames; - private String[] dayNames; - private boolean format; - private final DockPanel outer = new DockPanel(); - private int rows; - - private boolean rangeSelectAllowed = true; - private boolean rangeMoveAllowed = true; - private boolean eventResizeAllowed = true; - private boolean eventMoveAllowed = true; - - private final SimpleDayToolbar nameToolbar = new SimpleDayToolbar(); - - private final DayToolbar dayToolbar = new DayToolbar(this); - private final SimpleWeekToolbar weekToolbar; - private WeeklyLongEvents weeklyLongEvents; - private MonthGrid monthGrid; - private WeekGrid weekGrid; - private int intWidth = 0; - private int intHeight = 0; - - protected final DateTimeFormat dateformat_datetime = DateTimeFormat - .getFormat("yyyy-MM-dd HH:mm:ss"); - protected final DateTimeFormat dateformat_date = DateTimeFormat - .getFormat("yyyy-MM-dd"); - protected final DateTimeFormat time12format_date = DateTimeFormat - .getFormat("h:mm a"); - protected final DateTimeFormat time24format_date = DateTimeFormat - .getFormat("HH:mm"); - - private boolean readOnly = false; - private boolean disabled = false; - - private boolean isHeightUndefined = false; - - private boolean isWidthUndefined = false; - private int firstDay; - private int lastDay; - private int firstHour; - private int lastHour; - - private CalendarDropHandler dropHandler; - - /** - * Listener interface for listening to event click events - */ - public interface DateClickListener { - /** - * Triggered when a date was clicked - * - * @param date - * The date and time that was clicked - */ - void dateClick(String date); - } - - /** - * Listener interface for listening to week number click events - */ - public interface WeekClickListener { - /** - * Called when a week number was selected. - * - * @param event - * The format of the vent string is "<year>w<week>" - */ - void weekClick(String event); - } - - /** - * Listener interface for listening to forward events - */ - public interface ForwardListener { - - /** - * Called when the calendar should move one view forward - */ - void forward(); - } - - /** - * Listener interface for listening to backward events - */ - public interface BackwardListener { - - /** - * Called when the calendar should move one view backward - */ - void backward(); - } - - /** - * Listener interface for listening to selection events - */ - public interface RangeSelectListener { - - /** - * Called when a user selected a new event by highlighting an area of - * the calendar. - * - * FIXME Fix the value nonsense. - * - * @param value - * The format of the value string is - * "<year>:<start-minutes>:<end-minutes>" if called from the - * {@link SimpleWeekToolbar} and "<yyyy-MM-dd>TO<yyyy-MM-dd>" - * if called from {@link MonthGrid} - */ - void rangeSelected(String value); - } - - /** - * Listener interface for listening to click events - */ - public interface EventClickListener { - /** - * Called when an event was clicked - * - * @param event - * The event that was clicked - */ - void eventClick(CalendarEvent event); - } - - /** - * Listener interface for listening to event moved events. Occurs when a - * user drags an event to a new position - */ - public interface EventMovedListener { - /** - * Triggered when an event was dragged to a new position and the start - * and end dates was changed - * - * @param event - * The event that was moved - */ - void eventMoved(CalendarEvent event); - } - - /** - * Listener interface for when an event gets resized (its start or end date - * changes) - */ - public interface EventResizeListener { - /** - * Triggers when the time limits for the event was changed. - * - * @param event - * The event that was changed. The new time limits have been - * updated in the event before calling this method - */ - void eventResized(CalendarEvent event); - } - - /** - * Listener interface for listening to scroll events. - */ - public interface ScrollListener { - /** - * Triggered when the calendar is scrolled - * - * @param scrollPosition - * The scroll position in pixels as returned by - * {@link ScrollPanel#getScrollPosition()} - */ - void scroll(int scrollPosition); - } - - /** - * Listener interface for listening to mouse events. - */ - public interface MouseEventListener { - /** - * Triggered when a user wants an context menu - * - * @param event - * The context menu event - * - * @param widget - * The widget that the context menu should be added to - */ - void contextMenu(ContextMenuEvent event, Widget widget); - } - - /** - * Default constructor - */ - public VCalendar() { - weekToolbar = new SimpleWeekToolbar(this); - initWidget(outer); - setStylePrimaryName("v-calendar"); - blockSelect(getElement()); - } - - /** - * Hack for IE to not select text when dragging. - * - * @param e - * The element to apply the hack on - */ - private native void blockSelect(Element e) - /*-{ - 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>(); - - for (CalendarEvent e : events) { - if (e.isAllDay()) { - // Event is set on one "allDay" event or more than one. - allDayLong.add(e); - - } else { - // Event is set only on one day. - belowDayLong.add(e); - } - } - - weeklyLongEvents.addEvents(allDayLong); - - for (CalendarEvent e : belowDayLong) { - weekGrid.addEvent(e); - } - } - - /** - * Adds events to the month grid - * - * @param events - * The events to add - * @param drawImmediately - * Should the grid be rendered immediately. (currently not in - * use) - * - */ - public void updateEventsToMonthGrid(Collection<CalendarEvent> events, - boolean drawImmediately) { - for (CalendarEvent e : sortEventsByDuration(events)) { - // FIXME Why is drawImmediately not used ????? - addEventToMonthGrid(e, false); - } - } - - private void addEventToMonthGrid(CalendarEvent e, - boolean renderImmediately) { - Date when = e.getStart(); - Date to = e.getEnd(); - 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>(); - for (int row = 0; row < monthGrid.getRowCount(); row++) { - if (eventAdded) { - break; - } - for (int cell = 0; cell < monthGrid.getCellCount(row); cell++) { - SimpleDayCell sdc = (SimpleDayCell) monthGrid.getWidget(row, - cell); - if (isEventInDay(when, to, sdc.getDate()) - && isEventInDayWithTime(when, to, sdc.getDate(), - e.getEndTime(), e.isAllDay())) { - if (!eventMoving) { - eventMoving = sdc.getMoveEvent() != null; - } - long d = e.getRangeInMilliseconds(); - if ((d > 0 && d <= DateConstants.DAYINMILLIS) - && !e.isAllDay()) { - timeCells.add(sdc); - } else { - dayCells.add(sdc); - } - inProgress = true; - continue; - } else if (inProgress) { - eventAdded = true; - inProgress = false; - break; - } - } - } - - updateEventSlotIndex(e, dayCells); - updateEventSlotIndex(e, timeCells); - - for (SimpleDayCell sdc : dayCells) { - sdc.addCalendarEvent(e); - } - for (SimpleDayCell sdc : timeCells) { - sdc.addCalendarEvent(e); - } - - if (renderImmediately) { - reDrawAllMonthEvents(!eventMoving); - } - } - - /* - * We must also handle the special case when the event lasts exactly for 24 - * hours, thus spanning two days e.g. from 1.1.2001 00:00 to 2.1.2001 00:00. - * That special case still should span one day when rendered. - */ - @SuppressWarnings("deprecation") - // Date methods are not deprecated in GWT - private boolean isEventInDayWithTime(Date from, Date to, Date date, - Date endTime, boolean isAllDay) { - return (isAllDay || !(to.getDay() == date.getDay() - && from.getDay() != to.getDay() && isMidnight(endTime))); - } - - private void updateEventSlotIndex(CalendarEvent e, - List<SimpleDayCell> cells) { - if (cells.isEmpty()) { - return; - } - - if (e.getSlotIndex() == -1) { - // Update slot index - int newSlot = -1; - for (SimpleDayCell sdc : cells) { - int slot = sdc.getEventCount(); - if (slot > newSlot) { - newSlot = slot; - } - } - newSlot++; - - for (int i = 0; i < newSlot; i++) { - // check for empty slot - if (isSlotEmpty(e, i, cells)) { - newSlot = i; - break; - } - } - e.setSlotIndex(newSlot); - } - } - - private void reDrawAllMonthEvents(boolean clearCells) { - for (int row = 0; row < monthGrid.getRowCount(); row++) { - for (int cell = 0; cell < monthGrid.getCellCount(row); cell++) { - SimpleDayCell sdc = (SimpleDayCell) monthGrid.getWidget(row, - cell); - sdc.reDraw(clearCells); - } - } - } - - private boolean isSlotEmpty(CalendarEvent addedEvent, int slotIndex, - List<SimpleDayCell> cells) { - for (SimpleDayCell sdc : cells) { - CalendarEvent e = sdc.getCalendarEvent(slotIndex); - if (e != null && !e.equals(addedEvent)) { - return false; - } - } - return true; - } - - /** - * Remove a month event from the view - * - * @param target - * The event to remove - * - * @param repaintImmediately - * Should we repaint after the event was removed? - */ - public void removeMonthEvent(CalendarEvent target, - boolean repaintImmediately) { - if (target != null && target.getSlotIndex() >= 0) { - // Remove event - for (int row = 0; row < monthGrid.getRowCount(); row++) { - for (int cell = 0; cell < monthGrid.getCellCount(row); cell++) { - SimpleDayCell sdc = (SimpleDayCell) monthGrid.getWidget(row, - cell); - if (sdc == null) { - return; - } - sdc.removeEvent(target, repaintImmediately); - } - } - } - } - - /** - * Updates an event in the month grid - * - * @param changedEvent - * The event that has changed - */ - public void updateEventToMonthGrid(CalendarEvent changedEvent) { - removeMonthEvent(changedEvent, true); - changedEvent.setSlotIndex(-1); - addEventToMonthGrid(changedEvent, true); - } - - /** - * Sort the event by how long they are - * - * @param events - * The events to sort - * @return An array where the events has been sorted - */ - public CalendarEvent[] sortEventsByDuration( - Collection<CalendarEvent> events) { - CalendarEvent[] sorted = events - .toArray(new CalendarEvent[events.size()]); - Arrays.sort(sorted, getEventComparator()); - return sorted; - } - - /* - * Check if the given event occurs at the given date. - */ - private boolean isEventInDay(Date eventWhen, Date eventTo, Date gridDate) { - if (eventWhen.compareTo(gridDate) <= 0 - && eventTo.compareTo(gridDate) >= 0) { - - return true; - } - - return false; - } - - /** - * Re-render the week grid - * - * @param daysCount - * The amount of days to include in the week - * @param days - * The days - * @param today - * Todays date - * @param realDayNames - * The names of the dates - */ - @SuppressWarnings("deprecation") - public void updateWeekGrid(int daysCount, List<CalendarDay> days, - Date today, String[] realDayNames) { - weekGrid.setFirstHour(getFirstHourOfTheDay()); - weekGrid.setLastHour(getLastHourOfTheDay()); - weekGrid.getTimeBar().updateTimeBar(is24HFormat()); - - dayToolbar.clear(); - dayToolbar.addBackButton(); - dayToolbar.setVerticalSized(isHeightUndefined); - dayToolbar.setHorizontalSized(isWidthUndefined); - weekGrid.clearDates(); - weekGrid.setDisabled(isDisabledOrReadOnly()); - - for (CalendarDay day : days) { - String date = day.getDate(); - String localized_date_format = day.getLocalizedDateFormat(); - Date d = dateformat_date.parse(date); - int dayOfWeek = day.getDayOfWeek(); - if (dayOfWeek < getFirstDayNumber() - || dayOfWeek > getLastDayNumber()) { - continue; - } - boolean isToday = false; - int dayOfMonth = d.getDate(); - if (today.getDate() == dayOfMonth && today.getYear() == d.getYear() - && today.getMonth() == d.getMonth()) { - isToday = true; - } - dayToolbar.add(realDayNames[dayOfWeek - 1], date, - localized_date_format, isToday ? "today" : null); - weeklyLongEvents.addDate(d); - weekGrid.addDate(d); - if (isToday) { - weekGrid.setToday(d, today); - } - } - dayToolbar.addNextButton(); - } - - /** - * Updates the events in the Month view - * - * @param daysCount - * How many days there are - * @param daysUidl - * - * @param today - * Todays date - */ - @SuppressWarnings("deprecation") - public void updateMonthGrid(int daysCount, List<CalendarDay> days, - Date today) { - int columns = getLastDayNumber() - getFirstDayNumber() + 1; - rows = (int) Math.ceil(daysCount / (double) 7); - - monthGrid = new MonthGrid(this, rows, columns); - monthGrid.setEnabled(!isDisabledOrReadOnly()); - weekToolbar.removeAllRows(); - int pos = 0; - boolean monthNameDrawn = true; - boolean firstDayFound = false; - boolean lastDayFound = false; - - for (CalendarDay day : days) { - String date = day.getDate(); - Date d = dateformat_date.parse(date); - int dayOfWeek = day.getDayOfWeek(); - int week = day.getWeek(); - - int dayOfMonth = d.getDate(); - - // reset at start of each month - if (dayOfMonth == 1) { - monthNameDrawn = false; - if (firstDayFound) { - lastDayFound = true; - } - firstDayFound = true; - } - - if (dayOfWeek < getFirstDayNumber() - || dayOfWeek > getLastDayNumber()) { - continue; - } - int y = (pos / columns); - int x = pos - (y * columns); - if (x == 0 && daysCount > 7) { - // Add week to weekToolbar for navigation - weekToolbar.addWeek(week, day.getYearOfWeek()); - } - final SimpleDayCell cell = new SimpleDayCell(this, y, x); - cell.setMonthGrid(monthGrid); - cell.setDate(d); - cell.addDomHandler(new ContextMenuHandler() { - @Override - public void onContextMenu(ContextMenuEvent event) { - if (mouseEventListener != null) { - event.preventDefault(); - event.stopPropagation(); - mouseEventListener.contextMenu(event, cell); - } - } - }, ContextMenuEvent.getType()); - - if (!firstDayFound) { - cell.addStyleDependentName("prev-month"); - } else if (lastDayFound) { - cell.addStyleDependentName("next-month"); - } - - if (dayOfMonth >= 1 && !monthNameDrawn) { - cell.setMonthNameVisible(true); - monthNameDrawn = true; - } - - if (today.getDate() == dayOfMonth && today.getYear() == d.getYear() - && today.getMonth() == d.getMonth()) { - cell.setToday(true); - - } - monthGrid.setWidget(y, x, cell); - pos++; - } - } - - public void setSizeForChildren(int newWidth, int newHeight) { - intWidth = newWidth; - intHeight = newHeight; - isWidthUndefined = intWidth == -1; - dayToolbar.setVerticalSized(isHeightUndefined); - dayToolbar.setHorizontalSized(isWidthUndefined); - recalculateWidths(); - recalculateHeights(); - } - - /** - * Recalculates the heights of the sub-components in the calendar - */ - protected void recalculateHeights() { - if (monthGrid != null) { - - if (intHeight == -1) { - monthGrid.addStyleDependentName("sizedheight"); - } else { - monthGrid.removeStyleDependentName("sizedheight"); - } - - monthGrid.updateCellSizes(intWidth - weekToolbar.getOffsetWidth(), - intHeight - nameToolbar.getOffsetHeight()); - weekToolbar.setHeightPX((intHeight == -1) ? intHeight - : intHeight - nameToolbar.getOffsetHeight()); - - } else if (weekGrid != null) { - weekGrid.setHeightPX((intHeight == -1) ? intHeight - : intHeight - weeklyLongEvents.getOffsetHeight() - - dayToolbar.getOffsetHeight()); - } - } - - /** - * Recalculates the widths of the sub-components in the calendar - */ - protected void recalculateWidths() { - if (!isWidthUndefined) { - nameToolbar.setWidthPX(intWidth); - dayToolbar.setWidthPX(intWidth); - - if (monthGrid != null) { - monthGrid.updateCellSizes( - intWidth - weekToolbar.getOffsetWidth(), - intHeight - nameToolbar.getOffsetHeight()); - } else if (weekGrid != null) { - weekGrid.setWidthPX(intWidth); - weeklyLongEvents.setWidthPX(weekGrid.getInternalWidth()); - } - } else { - dayToolbar.setWidthPX(intWidth); - nameToolbar.setWidthPX(intWidth); - - if (monthGrid != null) { - if (intWidth == -1) { - monthGrid.addStyleDependentName("sizedwidth"); - - } else { - monthGrid.removeStyleDependentName("sizedwidth"); - } - } else if (weekGrid != null) { - weekGrid.setWidthPX(intWidth); - weeklyLongEvents.setWidthPX(weekGrid.getInternalWidth()); - } - } - } - - /** - * Get the date format used to format dates only (excludes time) - * - * @return - */ - public DateTimeFormat getDateFormat() { - return dateformat_date; - } - - /** - * Get the time format used to format time only (excludes date) - * - * @return - */ - public DateTimeFormat getTimeFormat() { - if (is24HFormat()) { - return time24format_date; - } - return time12format_date; - } - - /** - * Get the date and time format to format the dates (includes both date and - * time) - * - * @return - */ - public DateTimeFormat getDateTimeFormat() { - return dateformat_datetime; - } - - /** - * Is the calendar either disabled or readonly - * - * @return - */ - public boolean isDisabledOrReadOnly() { - return disabled || readOnly; - } - - /** - * Is the component disabled - */ - public boolean isDisabled() { - return disabled; - } - - /** - * Is the component disabled - * - * @param disabled - * True if disabled - */ - public void setDisabled(boolean disabled) { - this.disabled = disabled; - } - - /** - * Is the component read-only - */ - public boolean isReadOnly() { - return readOnly; - } - - /** - * Is the component read-only - * - * @param readOnly - * True if component is readonly - */ - public void setReadOnly(boolean readOnly) { - this.readOnly = readOnly; - } - - /** - * Get the month grid component - * - * @return - */ - public MonthGrid getMonthGrid() { - return monthGrid; - } - - /** - * Get he week grid component - * - * @return - */ - public WeekGrid getWeekGrid() { - return weekGrid; - } - - /** - * Calculates correct size for all cells (size / amount of cells ) and - * distributes any overflow over all the cells. - * - * @param totalSize - * the total amount of size reserved for all cells - * @param numberOfCells - * the number of cells - * @param sizeModifier - * a modifier which is applied to all cells before distributing - * the overflow - * @return an integer array that contains the correct size for each cell - */ - public static int[] distributeSize(int totalSize, int numberOfCells, - int sizeModifier) { - int[] cellSizes = new int[numberOfCells]; - int startingSize = totalSize / numberOfCells; - int cellSizeOverFlow = totalSize % numberOfCells; - - for (int i = 0; i < numberOfCells; i++) { - cellSizes[i] = startingSize + sizeModifier; - } - - // distribute size overflow amongst all slots - int j = 0; - while (cellSizeOverFlow > 0) { - cellSizes[j]++; - cellSizeOverFlow--; - j++; - if (j >= numberOfCells) { - j = 0; - } - } - - // cellSizes[numberOfCells - 1] += cellSizeOverFlow; - - return cellSizes; - } - - /** - * Returns a comparator which can compare calendar events. - * - * @return - */ - 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; - } - }; - } - - /** - * Is the date at midnight - * - * @param date - * The date to check - * - * @return - */ - @SuppressWarnings("deprecation") - public static boolean isMidnight(Date date) { - return (date.getHours() == 0 && date.getMinutes() == 0 - && date.getSeconds() == 0); - } - - /** - * Are the dates equal (uses second resolution) - * - * @param date1 - * The first the to compare - * @param date2 - * The second date to compare - * @return - */ - @SuppressWarnings("deprecation") - public static boolean areDatesEqualToSecond(Date date1, Date date2) { - return date1.getYear() == date2.getYear() - && date1.getMonth() == date2.getMonth() - && date1.getDay() == date2.getDay() - && date1.getHours() == date2.getHours() - && date1.getSeconds() == date2.getSeconds(); - } - - /** - * Is the calendar event zero seconds long and is occurring at midnight - * - * @param event - * The event to check - * @return - */ - public static boolean isZeroLengthMidnightEvent(CalendarEvent event) { - return areDatesEqualToSecond(event.getStartTime(), event.getEndTime()) - && isMidnight(event.getEndTime()); - } - - /** - * Should the 24h time format be used - * - * @param format - * True if the 24h format should be used else the 12h format is - * used - */ - public void set24HFormat(boolean format) { - this.format = format; - } - - /** - * Is the 24h time format used - */ - public boolean is24HFormat() { - return format; - } - - /** - * Set the names of the week days - * - * @param names - * The names of the days (Monday, Thursday,...) - */ - public void setDayNames(String[] names) { - assert (names.length == 7); - dayNames = names; - } - - /** - * Get the names of the week days - */ - public String[] getDayNames() { - return dayNames; - } - - /** - * Set the names of the months - * - * @param names - * The names of the months (January, February,...) - */ - public void setMonthNames(String[] names) { - assert (names.length == 12); - monthNames = names; - } - - /** - * Get the month names - */ - public String[] getMonthNames() { - return monthNames; - } - - /** - * Set the number when a week starts - * - * @param dayNumber - * The number of the day - */ - public void setFirstDayNumber(int dayNumber) { - assert (dayNumber >= 1 && dayNumber <= 7); - firstDay = dayNumber; - } - - /** - * Get the number when a week starts - */ - public int getFirstDayNumber() { - return firstDay; - } - - /** - * Set the number when a week ends - * - * @param dayNumber - * The number of the day - */ - public void setLastDayNumber(int dayNumber) { - assert (dayNumber >= 1 && dayNumber <= 7); - lastDay = dayNumber; - } - - /** - * Get the number when a week ends - */ - public int getLastDayNumber() { - return lastDay; - } - - /** - * Set the number when a week starts - * - * @param dayNumber - * The number of the day - */ - public void setFirstHourOfTheDay(int hour) { - assert (hour >= 0 && hour <= 23); - firstHour = hour; - } - - /** - * Get the number when a week starts - */ - public int getFirstHourOfTheDay() { - return firstHour; - } - - /** - * Set the number when a week ends - * - * @param dayNumber - * The number of the day - */ - public void setLastHourOfTheDay(int hour) { - assert (hour >= 0 && hour <= 23); - lastHour = hour; - } - - /** - * Get the number when a week ends - */ - public int getLastHourOfTheDay() { - return lastHour; - } - - /** - * Re-renders the whole week view - * - * @param scroll - * The amount of pixels to scroll the week view - * @param today - * Todays date - * @param daysInMonth - * How many days are there in the month - * @param firstDayOfWeek - * The first day of the week - * @param events - * The events to render - */ - public void updateWeekView(int scroll, Date today, int daysInMonth, - int firstDayOfWeek, Collection<CalendarEvent> events, - List<CalendarDay> days) { - - while (outer.getWidgetCount() > 0) { - outer.remove(0); - } - - monthGrid = null; - String[] realDayNames = new String[getDayNames().length]; - int j = 0; - - if (firstDayOfWeek == 2) { - for (int i = 1; i < getDayNames().length; i++) { - realDayNames[j++] = getDayNames()[i]; - } - realDayNames[j] = getDayNames()[0]; - } else { - for (int i = 0; i < getDayNames().length; i++) { - realDayNames[j++] = getDayNames()[i]; - } - - } - - weeklyLongEvents = new WeeklyLongEvents(this); - if (weekGrid == null) { - weekGrid = new WeekGrid(this, is24HFormat()); - } - updateWeekGrid(daysInMonth, days, today, realDayNames); - updateEventsToWeekGrid(sortEventsByDuration(events)); - outer.add(dayToolbar, DockPanel.NORTH); - outer.add(weeklyLongEvents, DockPanel.NORTH); - outer.add(weekGrid, DockPanel.SOUTH); - weekGrid.setVerticalScrollPosition(scroll); - } - - /** - * Re-renders the whole month view - * - * @param firstDayOfWeek - * The first day of the week - * @param today - * Todays date - * @param daysInMonth - * Amount of days in the month - * @param events - * The events to render - * @param days - * The day information - */ - public void updateMonthView(int firstDayOfWeek, Date today, int daysInMonth, - Collection<CalendarEvent> events, List<CalendarDay> days) { - - // Remove all week numbers from bar - while (outer.getWidgetCount() > 0) { - outer.remove(0); - } - - int firstDay = getFirstDayNumber(); - int lastDay = getLastDayNumber(); - int daysPerWeek = lastDay - firstDay + 1; - int j = 0; - - String[] dayNames = getDayNames(); - String[] realDayNames = new String[daysPerWeek]; - - if (firstDayOfWeek == 2) { - for (int i = firstDay; i < lastDay + 1; i++) { - if (i == 7) { - realDayNames[j++] = dayNames[0]; - } else { - realDayNames[j++] = dayNames[i]; - } - } - } else { - for (int i = firstDay - 1; i < lastDay; i++) { - realDayNames[j++] = dayNames[i]; - } - } - - nameToolbar.setDayNames(realDayNames); - - weeklyLongEvents = null; - weekGrid = null; - - updateMonthGrid(daysInMonth, days, today); - - outer.add(nameToolbar, DockPanel.NORTH); - outer.add(weekToolbar, DockPanel.WEST); - weekToolbar.updateCellHeights(); - outer.add(monthGrid, DockPanel.CENTER); - - updateEventsToMonthGrid(events, false); - } - - private DateClickListener dateClickListener; - - /** - * Sets the listener for listening to event clicks - * - * @param listener - * The listener to use - */ - public void setListener(DateClickListener listener) { - dateClickListener = listener; - } - - /** - * Gets the listener for listening to event clicks - * - * @return - */ - public DateClickListener getDateClickListener() { - return dateClickListener; - } - - private ForwardListener forwardListener; - - /** - * Set the listener which listens to forward events from the calendar - * - * @param listener - * The listener to use - */ - public void setListener(ForwardListener listener) { - forwardListener = listener; - } - - /** - * Get the listener which listens to forward events from the calendar - * - * @return - */ - public ForwardListener getForwardListener() { - return forwardListener; - } - - private BackwardListener backwardListener; - - /** - * Set the listener which listens to backward events from the calendar - * - * @param listener - * The listener to use - */ - public void setListener(BackwardListener listener) { - backwardListener = listener; - } - - /** - * Set the listener which listens to backward events from the calendar - * - * @return - */ - public BackwardListener getBackwardListener() { - return backwardListener; - } - - private WeekClickListener weekClickListener; - - /** - * Set the listener that listens to user clicking on the week numbers - * - * @param listener - * The listener to use - */ - public void setListener(WeekClickListener listener) { - weekClickListener = listener; - } - - /** - * Get the listener that listens to user clicking on the week numbers - * - * @return - */ - public WeekClickListener getWeekClickListener() { - return weekClickListener; - } - - private RangeSelectListener rangeSelectListener; - - /** - * Set the listener that listens to the user highlighting a region in the - * calendar - * - * @param listener - * The listener to use - */ - public void setListener(RangeSelectListener listener) { - rangeSelectListener = listener; - } - - /** - * Get the listener that listens to the user highlighting a region in the - * calendar - * - * @return - */ - public RangeSelectListener getRangeSelectListener() { - return rangeSelectListener; - } - - private EventClickListener eventClickListener; - - /** - * Get the listener that listens to the user clicking on the events - */ - public EventClickListener getEventClickListener() { - return eventClickListener; - } - - /** - * Set the listener that listens to the user clicking on the events - * - * @param listener - * The listener to use - */ - public void setListener(EventClickListener listener) { - eventClickListener = listener; - } - - private EventMovedListener eventMovedListener; - - /** - * Get the listener that listens to when event is dragged to a new location - * - * @return - */ - public EventMovedListener getEventMovedListener() { - return eventMovedListener; - } - - /** - * Set the listener that listens to when event is dragged to a new location - * - * @param eventMovedListener - * The listener to use - */ - public void setListener(EventMovedListener eventMovedListener) { - this.eventMovedListener = eventMovedListener; - } - - private ScrollListener scrollListener; - - /** - * Get the listener that listens to when the calendar widget is scrolled - * - * @return - */ - public ScrollListener getScrollListener() { - return scrollListener; - } - - /** - * Set the listener that listens to when the calendar widget is scrolled - * - * @param scrollListener - * The listener to use - */ - public void setListener(ScrollListener scrollListener) { - this.scrollListener = scrollListener; - } - - private EventResizeListener eventResizeListener; - - /** - * Get the listener that listens to when an events time limits are being - * adjusted - * - * @return - */ - public EventResizeListener getEventResizeListener() { - return eventResizeListener; - } - - /** - * Set the listener that listens to when an events time limits are being - * adjusted - * - * @param eventResizeListener - * The listener to use - */ - public void setListener(EventResizeListener eventResizeListener) { - this.eventResizeListener = eventResizeListener; - } - - private MouseEventListener mouseEventListener; - private boolean forwardNavigationEnabled = true; - private boolean backwardNavigationEnabled = true; - private boolean eventCaptionAsHtml = false; - - /** - * Get the listener that listen to mouse events - * - * @return - */ - public MouseEventListener getMouseEventListener() { - return mouseEventListener; - } - - /** - * Set the listener that listen to mouse events - * - * @param mouseEventListener - * The listener to use - */ - public void setListener(MouseEventListener mouseEventListener) { - this.mouseEventListener = mouseEventListener; - } - - /** - * Is selecting a range allowed? - */ - public boolean isRangeSelectAllowed() { - return rangeSelectAllowed; - } - - /** - * Set selecting a range allowed - * - * @param rangeSelectAllowed - * Should selecting a range be allowed - */ - public void setRangeSelectAllowed(boolean rangeSelectAllowed) { - this.rangeSelectAllowed = rangeSelectAllowed; - } - - /** - * Is moving a range allowed - * - * @return - */ - public boolean isRangeMoveAllowed() { - return rangeMoveAllowed; - } - - /** - * Is moving a range allowed - * - * @param rangeMoveAllowed - * Is it allowed - */ - public void setRangeMoveAllowed(boolean rangeMoveAllowed) { - this.rangeMoveAllowed = rangeMoveAllowed; - } - - /** - * Is resizing an event allowed - */ - public boolean isEventResizeAllowed() { - return eventResizeAllowed; - } - - /** - * Is resizing an event allowed - * - * @param eventResizeAllowed - * True if allowed false if not - */ - public void setEventResizeAllowed(boolean eventResizeAllowed) { - this.eventResizeAllowed = eventResizeAllowed; - } - - /** - * Is moving an event allowed - */ - public boolean isEventMoveAllowed() { - return eventMoveAllowed; - } - - /** - * Is moving an event allowed - * - * @param eventMoveAllowed - * True if moving is allowed, false if not - */ - public void setEventMoveAllowed(boolean eventMoveAllowed) { - this.eventMoveAllowed = eventMoveAllowed; - } - - public boolean isBackwardNavigationEnabled() { - return backwardNavigationEnabled; - } - - public void setBackwardNavigationEnabled(boolean enabled) { - backwardNavigationEnabled = enabled; - } - - public boolean isForwardNavigationEnabled() { - return forwardNavigationEnabled; - } - - public void setForwardNavigationEnabled(boolean enabled) { - forwardNavigationEnabled = enabled; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.client.ui.dd.VHasDropHandler#getDropHandler() - */ - @Override - public CalendarDropHandler getDropHandler() { - return dropHandler; - } - - /** - * Set the drop handler - * - * @param dropHandler - * The drophandler to use - */ - public void setDropHandler(CalendarDropHandler dropHandler) { - this.dropHandler = dropHandler; - } - - /** - * Sets whether the event captions are rendered as HTML. - * <p> - * If set to true, the captions are rendered in the browser as HTML and the - * developer is responsible for ensuring no harmful HTML is used. If set to - * false, the caption is rendered in the browser as plain text. - * <p> - * The default is false, i.e. to render that caption as plain text. - * - * @param captionAsHtml - * true if the captions are rendered as HTML, false if rendered - * as plain text - */ - public void setEventCaptionAsHtml(boolean eventCaptionAsHtml) { - this.eventCaptionAsHtml = eventCaptionAsHtml; - } - - /** - * Checks whether event captions are rendered as HTML - * <p> - * The default is false, i.e. to render that caption as plain text. - * - * @return true if the captions are rendered as HTML, false if rendered as - * plain text - */ - public boolean isEventCaptionAsHtml() { - return eventCaptionAsHtml; - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/VFilterSelect.java b/client/src/main/java/com/vaadin/client/ui/VFilterSelect.java deleted file mode 100644 index 44cbcf28f6..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/VFilterSelect.java +++ /dev/null @@ -1,2772 +0,0 @@ -/* - * Copyright 2000-2016 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; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import com.google.gwt.aria.client.Roles; -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Display; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.dom.client.Style.Visibility; -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyUpEvent; -import com.google.gwt.event.dom.client.KeyUpHandler; -import com.google.gwt.event.dom.client.LoadEvent; -import com.google.gwt.event.dom.client.LoadHandler; -import com.google.gwt.event.logical.shared.CloseEvent; -import com.google.gwt.event.logical.shared.CloseHandler; -import com.google.gwt.i18n.client.HasDirection.Direction; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Timer; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.PopupPanel; -import com.google.gwt.user.client.ui.PopupPanel.PositionCallback; -import com.google.gwt.user.client.ui.SuggestOracle.Suggestion; -import com.google.gwt.user.client.ui.TextBox; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.ApplicationConnection; -import com.vaadin.client.BrowserInfo; -import com.vaadin.client.ComputedStyle; -import com.vaadin.client.DeferredWorker; -import com.vaadin.client.Focusable; -import com.vaadin.client.VConsole; -import com.vaadin.client.WidgetUtil; -import com.vaadin.client.ui.aria.AriaHelper; -import com.vaadin.client.ui.aria.HandlesAriaCaption; -import com.vaadin.client.ui.aria.HandlesAriaInvalid; -import com.vaadin.client.ui.aria.HandlesAriaRequired; -import com.vaadin.client.ui.combobox.ComboBoxConnector; -import com.vaadin.client.ui.menubar.MenuBar; -import com.vaadin.client.ui.menubar.MenuItem; -import com.vaadin.shared.AbstractComponentState; -import com.vaadin.shared.ui.ComponentStateUtil; -import com.vaadin.shared.ui.combobox.FilteringMode; -import com.vaadin.shared.util.SharedUtil; - -/** - * Client side implementation of the Select component. - * - * TODO needs major refactoring (to be extensible etc) - */ -@SuppressWarnings("deprecation") -public class VFilterSelect extends Composite - implements Field, KeyDownHandler, KeyUpHandler, ClickHandler, - FocusHandler, BlurHandler, Focusable, SubPartAware, HandlesAriaCaption, - HandlesAriaInvalid, HandlesAriaRequired, DeferredWorker { - - /** - * Represents a suggestion in the suggestion popup box - */ - public class FilterSelectSuggestion implements Suggestion, Command { - - private final String key; - private final String caption; - private String untranslatedIconUri; - private String style; - - /** - * Constructor - * - * @param key - * item key, empty string for a special null item not in - * container - * @param caption - * item caption - * @param style - * item style name, can be empty string - * @param untranslatedIconUri - * icon URI or null - */ - public FilterSelectSuggestion(String key, String caption, String style, - String untranslatedIconUri) { - this.key = key; - this.caption = caption; - this.style = style; - this.untranslatedIconUri = untranslatedIconUri; - } - - /** - * Gets the visible row in the popup as a HTML string. The string - * contains an image tag with the rows icon (if an icon has been - * specified) and the caption of the item - */ - - @Override - public String getDisplayString() { - final StringBuffer sb = new StringBuffer(); - ApplicationConnection client = connector.getConnection(); - final Icon icon = client - .getIcon(client.translateVaadinUri(untranslatedIconUri)); - if (icon != null) { - sb.append(icon.getElement().getString()); - } - String content; - if ("".equals(caption)) { - // Ensure that empty options use the same height as other - // options and are not collapsed (#7506) - content = " "; - } else { - content = WidgetUtil.escapeHTML(caption); - } - sb.append("<span>" + content + "</span>"); - return sb.toString(); - } - - /** - * Get a string that represents this item. This is used in the text box. - */ - - @Override - public String getReplacementString() { - return caption; - } - - /** - * Get the option key which represents the item on the server side. - * - * @return The key of the item - */ - public String getOptionKey() { - return key; - } - - /** - * Get the URI of the icon. Used when constructing the displayed option. - * - * @return - */ - public String getIconUri() { - ApplicationConnection client = connector.getConnection(); - return client.translateVaadinUri(untranslatedIconUri); - } - - /** - * Gets the style set for this suggestion item. Styles are typically set - * by a server-side {@link com.vaadin.ui.ComboBox.ItemStyleGenerator}. - * The returned style is prefixed by <code>v-filterselect-item-</code>. - * - * @since 7.5.6 - * @return the style name to use, or <code>null</code> to not apply any - * custom style. - */ - public String getStyle() { - return style; - } - - /** - * Executes a selection of this item. - */ - - @Override - public void execute() { - onSuggestionSelected(this); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof FilterSelectSuggestion)) { - return false; - } - FilterSelectSuggestion other = (FilterSelectSuggestion) obj; - if ((key == null && other.key != null) - || (key != null && !key.equals(other.key))) { - return false; - } - if ((caption == null && other.caption != null) - || (caption != null && !caption.equals(other.caption))) { - return false; - } - if (!SharedUtil.equals(untranslatedIconUri, - other.untranslatedIconUri)) { - return false; - } - if (!SharedUtil.equals(style, other.style)) { - return false; - } - return true; - } - } - - /** An inner class that handles all logic related to mouse wheel. */ - private class MouseWheeler extends JsniMousewheelHandler { - - public MouseWheeler() { - super(VFilterSelect.this); - } - - @Override - protected native JavaScriptObject createMousewheelListenerFunction( - Widget widget) - /*-{ - return $entry(function(e) { - var deltaX = e.deltaX ? e.deltaX : -0.5*e.wheelDeltaX; - var deltaY = e.deltaY ? e.deltaY : -0.5*e.wheelDeltaY; - - // IE8 has only delta y - if (isNaN(deltaY)) { - deltaY = -0.5*e.wheelDelta; - } - - @com.vaadin.client.ui.VFilterSelect.JsniUtil::moveScrollFromEvent(*)(widget, deltaX, deltaY, e, e.deltaMode); - }); - }-*/; - - } - - /** - * A utility class that contains utility methods that are usually called - * from JSNI. - * <p> - * The methods are moved in this class to minimize the amount of JSNI code - * as much as feasible. - */ - static class JsniUtil { - private static final int DOM_DELTA_PIXEL = 0; - private static final int DOM_DELTA_LINE = 1; - private static final int DOM_DELTA_PAGE = 2; - - // Rough estimation of item height - private static final int SCROLL_UNIT_PX = 25; - - private static double deltaSum = 0; - - public static void moveScrollFromEvent(final Widget widget, - final double deltaX, final double deltaY, - final NativeEvent event, final int deltaMode) { - - if (!Double.isNaN(deltaY)) { - VFilterSelect filterSelect = (VFilterSelect) widget; - - switch (deltaMode) { - case DOM_DELTA_LINE: - if (deltaY >= 0) { - filterSelect.suggestionPopup.selectNextItem(); - } else { - filterSelect.suggestionPopup.selectPrevItem(); - } - break; - case DOM_DELTA_PAGE: - if (deltaY >= 0) { - filterSelect.selectNextPage(); - } else { - filterSelect.selectPrevPage(); - } - break; - case DOM_DELTA_PIXEL: - default: - // Accumulate dampened deltas - deltaSum += Math.pow(Math.abs(deltaY), 0.7) - * Math.signum(deltaY); - - // "Scroll" if change exceeds item height - while (Math.abs(deltaSum) >= SCROLL_UNIT_PX) { - if (!filterSelect.dataReceivedHandler - .isWaitingForFilteringResponse()) { - // Move selection if page flip is not in progress - if (deltaSum < 0) { - filterSelect.suggestionPopup.selectPrevItem(); - } else { - filterSelect.suggestionPopup.selectNextItem(); - } - } - deltaSum -= SCROLL_UNIT_PX * Math.signum(deltaSum); - } - break; - } - } - } - } - - /** - * Represents the popup box with the selection options. Wraps a suggestion - * menu. - */ - public class SuggestionPopup extends VOverlay - implements PositionCallback, CloseHandler<PopupPanel> { - - private static final int Z_INDEX = 30000; - - /** For internal use only. May be removed or replaced in the future. */ - public final SuggestionMenu menu; - - private final Element up = DOM.createDiv(); - private final Element down = DOM.createDiv(); - private final Element status = DOM.createDiv(); - - private boolean isPagingEnabled = true; - - private long lastAutoClosed; - - private int popupOuterPadding = -1; - - private int topPosition; - - private final MouseWheeler mouseWheeler = new MouseWheeler(); - - /** - * Default constructor - */ - SuggestionPopup() { - super(true, false); - debug("VFS.SP: constructor()"); - setOwner(VFilterSelect.this); - menu = new SuggestionMenu(); - setWidget(menu); - - getElement().getStyle().setZIndex(Z_INDEX); - - final Element root = getContainerElement(); - - up.setInnerHTML("<span>Prev</span>"); - DOM.sinkEvents(up, Event.ONCLICK); - - down.setInnerHTML("<span>Next</span>"); - DOM.sinkEvents(down, Event.ONCLICK); - - root.insertFirst(up); - root.appendChild(down); - root.appendChild(status); - - DOM.sinkEvents(root, Event.ONMOUSEDOWN | Event.ONMOUSEWHEEL); - addCloseHandler(this); - - Roles.getListRole().set(getElement()); - - setPreviewingAllNativeEvents(true); - } - - @Override - protected void onLoad() { - super.onLoad(); - - // Register mousewheel listener on paged select - if (pageLength > 0) { - mouseWheeler.attachMousewheelListener(getElement()); - } - } - - @Override - protected void onUnload() { - mouseWheeler.detachMousewheelListener(getElement()); - super.onUnload(); - } - - /** - * Shows the popup where the user can see the filtered options - * - * @param currentSuggestions - * The filtered suggestions - * @param currentPage - * The current page number - * @param totalSuggestions - * The total amount of suggestions - */ - public void showSuggestions( - final Collection<FilterSelectSuggestion> currentSuggestions, - final int currentPage, final int totalSuggestions) { - - debug("VFS.SP: showSuggestions(" + currentSuggestions + ", " - + currentPage + ", " + totalSuggestions + ")"); - - /* - * We need to defer the opening of the popup so that the parent DOM - * has stabilized so we can calculate an absolute top and left - * correctly. This issue manifests when a Combobox is placed in - * another popupView which also needs to calculate the absoluteTop() - * to position itself. #9768 - * - * After deferring the showSuggestions method, a problem with - * navigating in the combo box occurs. Because of that the method - * navigateItemAfterPageChange in ComboBoxConnector class, which - * navigates to the exact item after page was changed also was - * marked as deferred. #11333 - */ - final SuggestionPopup popup = this; - Scheduler.get().scheduleDeferred(new ScheduledCommand() { - @Override - public void execute() { - // Add TT anchor point - getElement().setId("VAADIN_COMBOBOX_OPTIONLIST"); - - menu.setSuggestions(currentSuggestions); - final int x = VFilterSelect.this.getAbsoluteLeft(); - - topPosition = tb.getAbsoluteTop(); - topPosition += tb.getOffsetHeight(); - - setPopupPosition(x, topPosition); - - int nullOffset = (nullSelectionAllowed - && "".equals(lastFilter) ? 1 : 0); - boolean firstPage = (currentPage == 0); - final int first = currentPage * pageLength + 1 - - (firstPage ? 0 : nullOffset); - final int last = first + currentSuggestions.size() - 1 - - (firstPage && "".equals(lastFilter) ? nullOffset - : 0); - final int matches = totalSuggestions - nullOffset; - if (last > 0) { - // nullsel not counted, as requested by user - status.setInnerText((matches == 0 ? 0 : first) + "-" - + last + "/" + matches); - } else { - status.setInnerText(""); - } - // We don't need to show arrows or statusbar if there is - // only one page - if (totalSuggestions <= pageLength || pageLength == 0) { - setPagingEnabled(false); - } else { - setPagingEnabled(true); - } - setPrevButtonActive(first > 1); - setNextButtonActive(last < matches); - - // clear previously fixed width - menu.setWidth(""); - menu.getElement().getFirstChildElement().getStyle() - .clearWidth(); - - setPopupPositionAndShow(popup); - } - }); - } - - /** - * Should the next page button be visible to the user? - * - * @param active - */ - private void setNextButtonActive(boolean active) { - if (enableDebug) { - debug("VFS.SP: setNextButtonActive(" + active + ")"); - } - if (active) { - DOM.sinkEvents(down, Event.ONCLICK); - down.setClassName( - VFilterSelect.this.getStylePrimaryName() + "-nextpage"); - } else { - DOM.sinkEvents(down, 0); - down.setClassName(VFilterSelect.this.getStylePrimaryName() - + "-nextpage-off"); - } - } - - /** - * Should the previous page button be visible to the user - * - * @param active - */ - private void setPrevButtonActive(boolean active) { - if (enableDebug) { - debug("VFS.SP: setPrevButtonActive(" + active + ")"); - } - - if (active) { - DOM.sinkEvents(up, Event.ONCLICK); - up.setClassName( - VFilterSelect.this.getStylePrimaryName() + "-prevpage"); - } else { - DOM.sinkEvents(up, 0); - up.setClassName(VFilterSelect.this.getStylePrimaryName() - + "-prevpage-off"); - } - - } - - /** - * Selects the next item in the filtered selections - */ - public void selectNextItem() { - debug("VFS.SP: selectNextItem()"); - - final int index = menu.getSelectedIndex() + 1; - if (menu.getItems().size() > index) { - selectItem(menu.getItems().get(index)); - - } else { - selectNextPage(); - } - } - - /** - * Selects the previous item in the filtered selections - */ - public void selectPrevItem() { - debug("VFS.SP: selectPrevItem()"); - - final int index = menu.getSelectedIndex() - 1; - if (index > -1) { - selectItem(menu.getItems().get(index)); - - } else if (index == -1) { - selectPrevPage(); - - } else { - if (!menu.getItems().isEmpty()) { - selectLastItem(); - } - } - } - - /** - * Select the first item of the suggestions list popup. - * - * @since 7.2.6 - */ - public void selectFirstItem() { - debug("VFS.SP: selectFirstItem()"); - selectItem(menu.getFirstItem()); - } - - /** - * Select the last item of the suggestions list popup. - * - * @since 7.2.6 - */ - public void selectLastItem() { - debug("VFS.SP: selectLastItem()"); - selectItem(menu.getLastItem()); - } - - /* - * Sets the selected item in the popup menu. - */ - private void selectItem(final MenuItem newSelectedItem) { - menu.selectItem(newSelectedItem); - - // Set the icon. - FilterSelectSuggestion suggestion = (FilterSelectSuggestion) newSelectedItem - .getCommand(); - setSelectedItemIcon(suggestion.getIconUri()); - - // Set the text. - setText(suggestion.getReplacementString()); - - } - - /* - * Using a timer to scroll up or down the pages so when we receive lots - * of consecutive mouse wheel events the pages does not flicker. - */ - private LazyPageScroller lazyPageScroller = new LazyPageScroller(); - - private class LazyPageScroller extends Timer { - private int pagesToScroll = 0; - - @Override - public void run() { - debug("VFS.SP.LPS: run()"); - if (pagesToScroll != 0) { - if (!dataReceivedHandler.isWaitingForFilteringResponse()) { - /* - * Avoid scrolling while we are waiting for a response - * because otherwise the waiting flag will be reset in - * the first response and the second response will be - * ignored, causing an empty popup... - * - * As long as the scrolling delay is suitable - * double/triple clicks will work by scrolling two or - * three pages at a time and this should not be a - * problem. - */ - filterOptions(currentPage + pagesToScroll, lastFilter); - } - pagesToScroll = 0; - } - } - - public void scrollUp() { - debug("VFS.SP.LPS: scrollUp()"); - if (pageLength > 0 && currentPage + pagesToScroll > 0) { - pagesToScroll--; - cancel(); - schedule(200); - } - } - - public void scrollDown() { - debug("VFS.SP.LPS: scrollDown()"); - if (pageLength > 0 - && totalMatches > (currentPage + pagesToScroll + 1) - * pageLength) { - pagesToScroll++; - cancel(); - schedule(200); - } - } - } - - private void scroll(double deltaY) { - boolean scrollActive = menu.isScrollActive(); - - debug("VFS.SP: scroll() scrollActive: " + scrollActive); - - if (!scrollActive) { - if (deltaY > 0d) { - lazyPageScroller.scrollDown(); - } else { - lazyPageScroller.scrollUp(); - } - } - } - - @Override - public void onBrowserEvent(Event event) { - debug("VFS.SP: onBrowserEvent()"); - - if (event.getTypeInt() == Event.ONCLICK) { - final Element target = DOM.eventGetTarget(event); - if (target == up || target == DOM.getChild(up, 0)) { - lazyPageScroller.scrollUp(); - } else if (target == down || target == DOM.getChild(down, 0)) { - lazyPageScroller.scrollDown(); - } - - } - - /* - * Prevent the keyboard focus from leaving the textfield by - * preventing the default behaviour of the browser. Fixes #4285. - */ - handleMouseDownEvent(event); - } - - /** - * Should paging be enabled. If paging is enabled then only a certain - * amount of items are visible at a time and a scrollbar or buttons are - * visible to change page. If paging is turned of then all options are - * rendered into the popup menu. - * - * @param paging - * Should the paging be turned on? - */ - public void setPagingEnabled(boolean paging) { - debug("VFS.SP: setPagingEnabled(" + paging + ")"); - if (isPagingEnabled == paging) { - return; - } - if (paging) { - down.getStyle().clearDisplay(); - up.getStyle().clearDisplay(); - status.getStyle().clearDisplay(); - } else { - down.getStyle().setDisplay(Display.NONE); - up.getStyle().setDisplay(Display.NONE); - status.getStyle().setDisplay(Display.NONE); - } - isPagingEnabled = paging; - } - - @Override - public void setPosition(int offsetWidth, int offsetHeight) { - debug("VFS.SP: setPosition(" + offsetWidth + ", " + offsetHeight - + ")"); - - int top = topPosition; - int left = getPopupLeft(); - - // reset menu size and retrieve its "natural" size - menu.setHeight(""); - if (currentPage > 0 && !hasNextPage()) { - // fix height to avoid height change when getting to last page - menu.fixHeightTo(pageLength); - } - - final int desiredHeight = offsetHeight = getOffsetHeight(); - final int desiredWidth = getMainWidth(); - - debug("VFS.SP: desired[" + desiredWidth + ", " + desiredHeight - + "]"); - - Element menuFirstChild = menu.getElement().getFirstChildElement(); - int naturalMenuWidth; - if (BrowserInfo.get().isIE() - && BrowserInfo.get().getBrowserMajorVersion() < 10) { - // On IE 8 & 9 visibility is set to hidden and measuring - // elements while they are hidden yields incorrect results - String before = menu.getElement().getParentElement().getStyle() - .getVisibility(); - menu.getElement().getParentElement().getStyle() - .setVisibility(Visibility.VISIBLE); - naturalMenuWidth = WidgetUtil.getRequiredWidth(menuFirstChild); - menu.getElement().getParentElement().getStyle() - .setProperty("visibility", before); - } else { - naturalMenuWidth = WidgetUtil.getRequiredWidth(menuFirstChild); - } - - if (popupOuterPadding == -1) { - popupOuterPadding = WidgetUtil - .measureHorizontalPaddingAndBorder(menu.getElement(), 2) - + WidgetUtil.measureHorizontalPaddingAndBorder( - suggestionPopup.getElement(), 0); - } - - updateMenuWidth(desiredWidth, naturalMenuWidth); - - if (BrowserInfo.get().isIE() - && BrowserInfo.get().getBrowserMajorVersion() < 11) { - // Must take margin,border,padding manually into account for - // menu element as we measure the element child and set width to - // the element parent - - double naturalMenuOuterWidth; - if (BrowserInfo.get().getBrowserMajorVersion() < 10) { - // On IE 8 & 9 visibility is set to hidden and measuring - // elements while they are hidden yields incorrect results - String before = menu.getElement().getParentElement() - .getStyle().getVisibility(); - menu.getElement().getParentElement().getStyle() - .setVisibility(Visibility.VISIBLE); - naturalMenuOuterWidth = WidgetUtil - .getRequiredWidthDouble(menuFirstChild) - + getMarginBorderPaddingWidth(menu.getElement()); - menu.getElement().getParentElement().getStyle() - .setProperty("visibility", before); - } else { - naturalMenuOuterWidth = WidgetUtil - .getRequiredWidthDouble(menuFirstChild) - + getMarginBorderPaddingWidth(menu.getElement()); - } - - /* - * IE requires us to specify the width for the container - * element. Otherwise it will be 100% wide - */ - double rootWidth = Math.max(desiredWidth - popupOuterPadding, - naturalMenuOuterWidth); - getContainerElement().getStyle().setWidth(rootWidth, Unit.PX); - } - - final int textInputHeight = VFilterSelect.this.getOffsetHeight(); - final int textInputTopOnPage = tb.getAbsoluteTop(); - final int viewportOffset = Document.get().getScrollTop(); - final int textInputTopInViewport = textInputTopOnPage - - viewportOffset; - final int textInputBottomInViewport = textInputTopInViewport - + textInputHeight; - - final int spaceAboveInViewport = textInputTopInViewport; - final int spaceBelowInViewport = Window.getClientHeight() - - textInputBottomInViewport; - - if (spaceBelowInViewport < offsetHeight - && spaceBelowInViewport < spaceAboveInViewport) { - // popup on top of input instead - if (offsetHeight > spaceAboveInViewport) { - // Shrink popup height to fit above - offsetHeight = spaceAboveInViewport; - } - top = textInputTopOnPage - offsetHeight; - } else { - // Show below, position calculated in showSuggestions for some - // strange reason - top = topPosition; - offsetHeight = Math.min(offsetHeight, spaceBelowInViewport); - } - - // fetch real width (mac FF bugs here due GWT popups overflow:auto ) - offsetWidth = menuFirstChild.getOffsetWidth(); - - if (offsetHeight < desiredHeight) { - int menuHeight = offsetHeight; - if (isPagingEnabled) { - menuHeight -= up.getOffsetHeight() + down.getOffsetHeight() - + status.getOffsetHeight(); - } else { - final ComputedStyle s = new ComputedStyle( - menu.getElement()); - menuHeight -= s.getIntProperty("marginBottom") - + s.getIntProperty("marginTop"); - } - - // If the available page height is really tiny then this will be - // negative and an exception will be thrown on setHeight. - int menuElementHeight = menu.getItemOffsetHeight(); - if (menuHeight < menuElementHeight) { - menuHeight = menuElementHeight; - } - - menu.setHeight(menuHeight + "px"); - - if (suggestionPopupWidth == null) { - final int naturalMenuWidthPlusScrollBar = naturalMenuWidth - + WidgetUtil.getNativeScrollbarSize(); - if (offsetWidth < naturalMenuWidthPlusScrollBar) { - menu.setWidth(naturalMenuWidthPlusScrollBar + "px"); - } - } - } - - if (offsetWidth + left > Window.getClientWidth()) { - left = VFilterSelect.this.getAbsoluteLeft() - + VFilterSelect.this.getOffsetWidth() - offsetWidth; - if (left < 0) { - left = 0; - menu.setWidth(Window.getClientWidth() + "px"); - - } - } - - setPopupPosition(left, top); - menu.scrollSelectionIntoView(); - } - - /** - * Adds in-line CSS rules to the DOM according to the - * suggestionPopupWidth field - * - * @param desiredWidth - * @param naturalMenuWidth - */ - private void updateMenuWidth(final int desiredWidth, - int naturalMenuWidth) { - /** - * Three different width modes for the suggestion pop-up: - * - * 1. Legacy "null"-mode: width is determined by the longest item - * caption for each page while still maintaining minimum width of - * (desiredWidth - popupOuterPadding) - * - * 2. relative to the component itself - * - * 3. fixed width - */ - String width = "auto"; - if (suggestionPopupWidth == null) { - if (naturalMenuWidth < desiredWidth) { - naturalMenuWidth = desiredWidth - popupOuterPadding; - width = (desiredWidth - popupOuterPadding) + "px"; - } - } else if (isrelativeUnits(suggestionPopupWidth)) { - float mainComponentWidth = desiredWidth - popupOuterPadding; - // convert percentage value to fraction - int widthInPx = Math.round( - mainComponentWidth * asFraction(suggestionPopupWidth)); - width = widthInPx + "px"; - } else { - // use as fixed width CSS definition - width = WidgetUtil.escapeAttribute(suggestionPopupWidth); - } - menu.setWidth(width); - } - - /** - * Returns the percentage value as a fraction, e.g. 42% -> 0.42 - * - * @param percentage - */ - private float asFraction(String percentage) { - String trimmed = percentage.trim(); - String withoutPercentSign = trimmed.substring(0, - trimmed.length() - 1); - float asFraction = Float.parseFloat(withoutPercentSign) / 100; - return asFraction; - } - - /** - * @since 7.7 - * @param suggestionPopupWidth - * @return - */ - private boolean isrelativeUnits(String suggestionPopupWidth) { - return suggestionPopupWidth.trim().endsWith("%"); - } - - /** - * Was the popup just closed? - * - * @return true if popup was just closed - */ - public boolean isJustClosed() { - debug("VFS.SP: justClosed()"); - final long now = (new Date()).getTime(); - return (lastAutoClosed > 0 && (now - lastAutoClosed) < 200); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google - * .gwt.event.logical.shared.CloseEvent) - */ - - @Override - public void onClose(CloseEvent<PopupPanel> event) { - if (enableDebug) { - debug("VFS.SP: onClose(" + event.isAutoClosed() + ")"); - } - if (event.isAutoClosed()) { - lastAutoClosed = (new Date()).getTime(); - } - } - - /** - * Updates style names in suggestion popup to help theme building. - * - * @param componentState - * shared state of the combo box - */ - public void updateStyleNames(AbstractComponentState componentState) { - debug("VFS.SP: updateStyleNames()"); - setStyleName( - VFilterSelect.this.getStylePrimaryName() + "-suggestpopup"); - menu.setStyleName( - VFilterSelect.this.getStylePrimaryName() + "-suggestmenu"); - status.setClassName( - VFilterSelect.this.getStylePrimaryName() + "-status"); - if (ComponentStateUtil.hasStyles(componentState)) { - for (String style : componentState.styles) { - if (!"".equals(style)) { - addStyleDependentName(style); - } - } - } - } - - } - - /** - * The menu where the suggestions are rendered - */ - public class SuggestionMenu extends MenuBar - implements SubPartAware, LoadHandler { - - private VLazyExecutor delayedImageLoadExecutioner = new VLazyExecutor( - 100, new ScheduledCommand() { - - @Override - public void execute() { - debug("VFS.SM: delayedImageLoadExecutioner()"); - if (suggestionPopup.isVisible() - && suggestionPopup.isAttached()) { - setWidth(""); - getElement().getFirstChildElement().getStyle() - .clearWidth(); - suggestionPopup - .setPopupPositionAndShow(suggestionPopup); - } - - } - }); - - /** - * Default constructor - */ - SuggestionMenu() { - super(true); - debug("VFS.SM: constructor()"); - addDomHandler(this, LoadEvent.getType()); - - setScrollEnabled(true); - } - - /** - * Fixes menus height to use same space as full page would use. Needed - * to avoid height changes when quickly "scrolling" to last page. - */ - public void fixHeightTo(int pageItemsCount) { - setHeight(getPreferredHeight(pageItemsCount)); - } - - /* - * Gets the preferred height of the menu including pageItemsCount items. - */ - String getPreferredHeight(int pageItemsCount) { - if (currentSuggestions.size() > 0) { - final int pixels = (getPreferredHeight() - / currentSuggestions.size()) * pageItemsCount; - return pixels + "px"; - } else { - return ""; - } - } - - /** - * Sets the suggestions rendered in the menu - * - * @param suggestions - * The suggestions to be rendered in the menu - */ - public void setSuggestions( - Collection<FilterSelectSuggestion> suggestions) { - if (enableDebug) { - debug("VFS.SM: setSuggestions(" + suggestions + ")"); - } - - clearItems(); - final Iterator<FilterSelectSuggestion> it = suggestions.iterator(); - boolean isFirstIteration = true; - while (it.hasNext()) { - final FilterSelectSuggestion s = it.next(); - final MenuItem mi = new MenuItem(s.getDisplayString(), true, s); - String style = s.getStyle(); - if (style != null) { - mi.addStyleName("v-filterselect-item-" + style); - } - Roles.getListitemRole().set(mi.getElement()); - - WidgetUtil.sinkOnloadForImages(mi.getElement()); - - this.addItem(mi); - - // By default, first item on the list is always highlighted, - // unless adding new items is allowed. - if (isFirstIteration && !allowNewItem) { - selectItem(mi); - } - - // If the filter matches the current selection, highlight that - // instead of the first item. - if (tb.getText().equals(s.getReplacementString()) - && s == currentSuggestion) { - selectItem(mi); - } - - isFirstIteration = false; - } - } - - /** - * Send the current selection to the server. Triggered when a selection - * is made with the ENTER key. - */ - public void doSelectedItemAction() { - debug("VFS.SM: doSelectedItemAction()"); - // do not send a value change event if null was and stays selected - final String enteredItemValue = tb.getText(); - if (nullSelectionAllowed && "".equals(enteredItemValue) - && selectedOptionKey != null - && !"".equals(selectedOptionKey)) { - if (nullSelectItem) { - reset(); - return; - } - // null is not visible on pages != 0, and not visible when - // filtering: handle separately - connector.requestFirstPage(); - - suggestionPopup.hide(); - return; - } - - dataReceivedHandler.doPostFilterWhenReady(); - } - - /** - * Triggered after a selection has been made. - */ - public void doPostFilterSelectedItemAction() { - debug("VFS.SM: doPostFilterSelectedItemAction()"); - final MenuItem item = getSelectedItem(); - final String enteredItemValue = tb.getText(); - - // check for exact match in menu - int p = getItems().size(); - if (p > 0) { - for (int i = 0; i < p; i++) { - final MenuItem potentialExactMatch = getItems().get(i); - if (potentialExactMatch.getText() - .equals(enteredItemValue)) { - selectItem(potentialExactMatch); - // do not send a value change event if null was and - // stays selected - if (!"".equals(enteredItemValue) - || (selectedOptionKey != null - && !"".equals(selectedOptionKey))) { - doItemAction(potentialExactMatch, true); - } - suggestionPopup.hide(); - return; - } - } - } - if (allowNewItem) { - - if (!prompting && !enteredItemValue.equals(lastNewItemString)) { - /* - * Store last sent new item string to avoid double sends - */ - lastNewItemString = enteredItemValue; - connector.sendNewItem(enteredItemValue); - } - } else if (item != null && !"".equals(lastFilter) - && (filteringmode == FilteringMode.CONTAINS - ? item.getText().toLowerCase() - .contains(lastFilter.toLowerCase()) - : item.getText().toLowerCase() - .startsWith(lastFilter.toLowerCase()))) { - doItemAction(item, true); - } else { - // currentSuggestion has key="" for nullselection - if (currentSuggestion != null - && !currentSuggestion.key.equals("")) { - // An item (not null) selected - String text = currentSuggestion.getReplacementString(); - setText(text); - selectedOptionKey = currentSuggestion.key; - } else { - // Null selected - setText(""); - selectedOptionKey = null; - } - } - suggestionPopup.hide(); - } - - private static final String SUBPART_PREFIX = "item"; - - @Override - public com.google.gwt.user.client.Element getSubPartElement( - String subPart) { - int index = Integer - .parseInt(subPart.substring(SUBPART_PREFIX.length())); - - MenuItem item = getItems().get(index); - - return item.getElement(); - } - - @Override - public String getSubPartName( - com.google.gwt.user.client.Element subElement) { - if (!getElement().isOrHasChild(subElement)) { - return null; - } - - Element menuItemRoot = subElement; - while (menuItemRoot != null - && !menuItemRoot.getTagName().equalsIgnoreCase("td")) { - menuItemRoot = menuItemRoot.getParentElement().cast(); - } - // "menuItemRoot" is now the root of the menu item - - final int itemCount = getItems().size(); - for (int i = 0; i < itemCount; i++) { - if (getItems().get(i).getElement() == menuItemRoot) { - String name = SUBPART_PREFIX + i; - return name; - } - } - return null; - } - - @Override - public void onLoad(LoadEvent event) { - debug("VFS.SM: onLoad()"); - // Handle icon onload events to ensure shadow is resized - // correctly - delayedImageLoadExecutioner.trigger(); - - } - - /** - * @deprecated use {@link SuggestionPopup#selectFirstItem()} instead. - */ - @Deprecated - public void selectFirstItem() { - debug("VFS.SM: selectFirstItem()"); - MenuItem firstItem = getItems().get(0); - selectItem(firstItem); - } - - /** - * @deprecated use {@link SuggestionPopup#selectLastItem()} instead. - */ - @Deprecated - public void selectLastItem() { - debug("VFS.SM: selectLastItem()"); - List<MenuItem> items = getItems(); - MenuItem lastItem = items.get(items.size() - 1); - selectItem(lastItem); - } - - /* - * Gets the height of one menu item. - */ - int getItemOffsetHeight() { - List<MenuItem> items = getItems(); - return items != null && items.size() > 0 - ? items.get(0).getOffsetHeight() : 0; - } - - /* - * Gets the width of one menu item. - */ - int getItemOffsetWidth() { - List<MenuItem> items = getItems(); - return items != null && items.size() > 0 - ? items.get(0).getOffsetWidth() : 0; - } - - /** - * Returns true if the scroll is active on the menu element or if the - * menu currently displays the last page with less items then the - * maximum visibility (in which case the scroll is not active, but the - * scroll is active for any other page in general). - * - * @since 7.2.6 - */ - @Override - public boolean isScrollActive() { - String height = getElement().getStyle().getHeight(); - String preferredHeight = getPreferredHeight(pageLength); - - return !(height == null || height.length() == 0 - || height.equals(preferredHeight)); - } - - } - - /** - * TextBox variant used as input element for filter selects, which prevents - * selecting text when disabled. - * - * @since 7.1.5 - */ - public class FilterSelectTextBox extends TextBox { - - /** - * Creates a new filter select text box. - * - * @since 7.6.4 - */ - public FilterSelectTextBox() { - /*- - * Stop the browser from showing its own suggestion popup. - * - * Using an invalid value instead of "off" as suggested by - * https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion - * - * Leaving the non-standard Safari options autocapitalize and - * autocorrect untouched since those do not interfere in the same - * way, and they might be useful in a combo box where new items are - * allowed. - */ - getElement().setAttribute("autocomplete", "nope"); - } - - /** - * Overridden to avoid selecting text when text input is disabled - */ - @Override - public void setSelectionRange(int pos, int length) { - if (textInputEnabled) { - /* - * set selection range with a backwards direction: anchor at the - * back, focus at the front. This means that items that are too - * long to display will display from the start and not the end - * even on Firefox. - * - * We need the JSNI function to set selection range so that we - * can use the optional direction attribute to set the anchor to - * the end and the focus to the start. This makes Firefox work - * the same way as other browsers (#13477) - */ - WidgetUtil.setSelectionRange(getElement(), pos, length, - "backward"); - - } else { - /* - * Setting the selectionrange for an uneditable textbox leads to - * unwanted behaviour when the width of the textbox is narrower - * than the width of the entry: the end of the entry is shown - * instead of the beginning. (see #13477) - * - * To avoid this, we set the caret to the beginning of the line. - */ - - super.setSelectionRange(0, 0); - } - } - - } - - /** - * Handler receiving notifications from the connector and updating the - * widget state accordingly. - * - * This class is still subject to change and should not be considered as - * public stable API. - * - * @since - */ - public class DataReceivedHandler { - - private Runnable navigationCallback = null; - /** - * Set true when popupopened has been clicked. Cleared on each - * UIDL-update. This handles the special case where are not filtering - * yet and the selected value has changed on the server-side. See #2119 - * <p> - * For internal use only. May be removed or replaced in the future. - */ - private boolean popupOpenerClicked = false; - private boolean performPostFilteringOnDataReceived = false; - /** For internal use only. May be removed or replaced in the future. */ - private boolean waitingForFilteringResponse = false; - - /** - * Called by the connector when new data for the last requested filter - * is received from the server. - */ - public void dataReceived() { - suggestionPopup.showSuggestions(currentSuggestions, currentPage, - totalMatches); - - waitingForFilteringResponse = false; - - if (!popupOpenerClicked) { - navigateItemAfterPageChange(); - } - - if (performPostFilteringOnDataReceived) { - performPostFilteringOnDataReceived = false; - suggestionPopup.menu.doPostFilterSelectedItemAction(); - } - - popupOpenerClicked = false; - } - - /* - * This method navigates to the proper item in the combobox page. This - * should be executed after setSuggestions() method which is called from - * vFilterSelect.showSuggestions(). ShowSuggestions() method builds the - * page content. As far as setSuggestions() method is called as - * deferred, navigateItemAfterPageChange method should be also be called - * as deferred. #11333 - */ - private void navigateItemAfterPageChange() { - if (navigationCallback != null) { - // pageChangeCallback is not reset here but after any server - // request in case you are in between two requests both changing - // the page back and forth - - // we're paging w/ arrows - Scheduler.get().scheduleDeferred(new ScheduledCommand() { - @Override - public void execute() { - if (navigationCallback != null) { - navigationCallback.run(); - } - } - }); - } - } - - /** - * Called by the connector when any request has been sent to the server, - * before waiting for a reply. - */ - public void anyRequestSentToServer() { - navigationCallback = null; - } - - /** - * Set a callback that is invoked when a page change occurs if there - * have not been intervening requests to the server. The callback is - * reset when any additional request is made to the server. - * - * @param callback - */ - public void setNavigationCallback(Runnable callback) { - navigationCallback = callback; - } - - /** - * Record that the popup opener has been clicked and the popup should be - * opened on the next request. - * - * This handles the special case where are not filtering yet and the - * selected value has changed on the server-side. See #2119. The flag is - * cleared on each UIDL reply. - */ - public void popupOpenerClicked() { - popupOpenerClicked = true; - } - - /** - * Cancel a pending request to perform post-filtering actions. - */ - private void cancelPendingPostFiltering() { - performPostFilteringOnDataReceived = false; - } - - /** - * Called by the connector when it has finished handling any reply from - * the server, regardless of what was updated. - */ - public void serverReplyHandled() { - popupOpenerClicked = false; - } - - /** - * For internal use only - this method will be removed in the future. - * - * @return true if the combo box is waiting for a reply from the server - * with a new page of data, false otherwise - */ - public boolean isWaitingForFilteringResponse() { - return waitingForFilteringResponse; - } - - /** - * Set a flag that filtering of options is pending a response from the - * server. - */ - private void startWaitingForFilteringResponse() { - waitingForFilteringResponse = true; - } - - /** - * Perform the post-filter action either now (if not waiting for a - * server response) or when a response is received. - */ - private void doPostFilterWhenReady() { - if (isWaitingForFilteringResponse()) { - performPostFilteringOnDataReceived = true; - } else { - performPostFilteringOnDataReceived = false; - suggestionPopup.menu.doPostFilterSelectedItemAction(); - } - } - - /** - * Perform selection (if appropriate) based on a reply from the server. - * When this method is called, the suggestions have been reset if new - * ones (different from the previous list) were received from the - * server. - * - * @param selectedKey - * new selected key or null if none given by the server - * @param selectedCaption - * new selected item caption if sent by the server or null - - * this is used when the selected item is not on the current - * page - * @param oldSuggestionTextMatchTheOldSelection - * true if the old filtering text box contents matched - * exactly the old selection - */ - public void updateSelectionFromServer(String selectedKey, - String selectedCaption, - boolean oldSuggestionTextMatchTheOldSelection) { - // when filtering with empty filter, server sets the selected key - // to "", which we don't select here. Otherwise we won't be able to - // reset back to the item that was selected before filtering - // started. - if (selectedKey != null && !selectedKey.equals("")) { - performSelection(selectedKey, - oldSuggestionTextMatchTheOldSelection, - !isWaitingForFilteringResponse() || popupOpenerClicked); - setSelectedCaption(null); - } else if (!isWaitingForFilteringResponse() - && selectedCaption != null) { - // scrolling to correct page is disabled, caption is passed as a - // special parameter - setSelectedCaption(selectedCaption); - } else { - if (!isWaitingForFilteringResponse() || popupOpenerClicked) { - resetSelection(popupOpenerClicked); - } - } - } - - } - - @Deprecated - public static final FilteringMode FILTERINGMODE_OFF = FilteringMode.OFF; - @Deprecated - public static final FilteringMode FILTERINGMODE_STARTSWITH = FilteringMode.STARTSWITH; - @Deprecated - public static final FilteringMode FILTERINGMODE_CONTAINS = FilteringMode.CONTAINS; - - public static final String CLASSNAME = "v-filterselect"; - private static final String STYLE_NO_INPUT = "no-input"; - - /** For internal use only. May be removed or replaced in the future. */ - public int pageLength = 10; - - private boolean enableDebug = false; - - private final FlowPanel panel = new FlowPanel(); - - /** - * The text box where the filter is written - * <p> - * For internal use only. May be removed or replaced in the future. - */ - public final TextBox tb; - - /** For internal use only. May be removed or replaced in the future. */ - public final SuggestionPopup suggestionPopup; - - /** - * Used when measuring the width of the popup - */ - private final HTML popupOpener = new HTML("") { - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt - * .user.client.Event) - */ - - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - - /* - * Prevent the keyboard focus from leaving the textfield by - * preventing the default behaviour of the browser. Fixes #4285. - */ - handleMouseDownEvent(event); - } - }; - - private class IconWidget extends Widget { - IconWidget(Icon icon) { - setElement(icon.getElement()); - addDomHandler(VFilterSelect.this, ClickEvent.getType()); - } - } - - private IconWidget selectedItemIcon; - - /** For internal use only. May be removed or replaced in the future. */ - public ComboBoxConnector connector; - - /** For internal use only. May be removed or replaced in the future. */ - public int currentPage; - - /** - * A collection of available suggestions (options) as received from the - * server. - * <p> - * For internal use only. May be removed or replaced in the future. - */ - public final List<FilterSelectSuggestion> currentSuggestions = new ArrayList<FilterSelectSuggestion>(); - - /** For internal use only. May be removed or replaced in the future. */ - public String selectedOptionKey; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean initDone = false; - - /** For internal use only. May be removed or replaced in the future. */ - public String lastFilter = ""; - - /** - * The current suggestion selected from the dropdown. This is one of the - * values in currentSuggestions except when filtering, in this case - * currentSuggestion might not be in currentSuggestions. - * <p> - * For internal use only. May be removed or replaced in the future. - */ - public FilterSelectSuggestion currentSuggestion; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean allowNewItem; - - /** For internal use only. May be removed or replaced in the future. */ - public int totalMatches; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean nullSelectionAllowed; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean nullSelectItem; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean enabled; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean readonly; - - /** For internal use only. May be removed or replaced in the future. */ - public FilteringMode filteringmode = FilteringMode.OFF; - - // shown in unfocused empty field, disappears on focus (e.g "Search here") - private static final String CLASSNAME_PROMPT = "prompt"; - - /** For internal use only. May be removed or replaced in the future. */ - public String inputPrompt = ""; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean prompting = false; - - /** For internal use only. May be removed or replaced in the future. */ - public int suggestionPopupMinWidth = 0; - - public String suggestionPopupWidth = null; - - private int popupWidth = -1; - /** - * Stores the last new item string to avoid double submissions. Cleared on - * uidl updates. - * <p> - * For internal use only. May be removed or replaced in the future. - */ - public String lastNewItemString; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean focused = false; - - /** - * If set to false, the component should not allow entering text to the - * field even for filtering. - */ - private boolean textInputEnabled = true; - - private final DataReceivedHandler dataReceivedHandler = new DataReceivedHandler(); - - /** - * Default constructor. - */ - public VFilterSelect() { - tb = createTextBox(); - suggestionPopup = createSuggestionPopup(); - - popupOpener.sinkEvents(Event.ONMOUSEDOWN); - Roles.getButtonRole().setAriaHiddenState(popupOpener.getElement(), - true); - Roles.getButtonRole().set(popupOpener.getElement()); - - panel.add(tb); - panel.add(popupOpener); - initWidget(panel); - Roles.getComboboxRole().set(panel.getElement()); - - tb.addKeyDownHandler(this); - tb.addKeyUpHandler(this); - - tb.addFocusHandler(this); - tb.addBlurHandler(this); - tb.addClickHandler(this); - - popupOpener.addClickHandler(this); - - setStyleName(CLASSNAME); - - sinkEvents(Event.ONPASTE); - } - - private static double getMarginBorderPaddingWidth(Element element) { - final ComputedStyle s = new ComputedStyle(element); - return s.getMarginWidth() + s.getBorderWidth() + s.getPaddingWidth(); - - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.user.client.ui.Composite#onBrowserEvent(com.google.gwt - * .user.client.Event) - */ - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - - if (event.getTypeInt() == Event.ONPASTE) { - if (textInputEnabled) { - Scheduler.get().scheduleDeferred(new ScheduledCommand() { - - @Override - public void execute() { - filterOptions(currentPage); - } - }); - } - } - } - - /** - * This method will create the TextBox used by the VFilterSelect instance. - * It is invoked during the Constructor and should only be overridden if a - * custom TextBox shall be used. The overriding method cannot use any - * instance variables. - * - * @since 7.1.5 - * @return TextBox instance used by this VFilterSelect - */ - protected TextBox createTextBox() { - return new FilterSelectTextBox(); - } - - /** - * This method will create the SuggestionPopup used by the VFilterSelect - * instance. It is invoked during the Constructor and should only be - * overridden if a custom SuggestionPopup shall be used. The overriding - * method cannot use any instance variables. - * - * @since 7.1.5 - * @return SuggestionPopup instance used by this VFilterSelect - */ - protected SuggestionPopup createSuggestionPopup() { - return new SuggestionPopup(); - } - - @Override - public void setStyleName(String style) { - super.setStyleName(style); - updateStyleNames(); - } - - @Override - public void setStylePrimaryName(String style) { - super.setStylePrimaryName(style); - updateStyleNames(); - } - - protected void updateStyleNames() { - tb.setStyleName(getStylePrimaryName() + "-input"); - popupOpener.setStyleName(getStylePrimaryName() + "-button"); - suggestionPopup.setStyleName(getStylePrimaryName() + "-suggestpopup"); - } - - /** - * Does the Select have more pages? - * - * @return true if a next page exists, else false if the current page is the - * last page - */ - public boolean hasNextPage() { - if (pageLength > 0 && totalMatches > (currentPage + 1) * pageLength) { - return true; - } else { - return false; - } - } - - /** - * Filters the options at a certain page. Uses the text box input as a - * filter - * - * @param page - * The page which items are to be filtered - */ - public void filterOptions(int page) { - filterOptions(page, tb.getText()); - } - - /** - * Filters the options at certain page using the given filter - * - * @param page - * The page to filter - * @param filter - * The filter to apply to the components - */ - public void filterOptions(int page, String filter) { - debug("VFS: filterOptions(" + page + ", " + filter + ")"); - - if (filter.equals(lastFilter) && currentPage == page) { - if (!suggestionPopup.isAttached()) { - suggestionPopup.showSuggestions(currentSuggestions, currentPage, - totalMatches); - } - return; - } - if (!filter.equals(lastFilter)) { - // when filtering, let the server decide the page unless we've - // set the filter to empty and explicitly said that we want to see - // the results starting from page 0. - if ("".equals(filter) && page != 0) { - // let server decide - page = -1; - } else { - page = 0; - } - } - - dataReceivedHandler.startWaitingForFilteringResponse(); - connector.requestPage(filter, page); - - lastFilter = filter; - currentPage = page; - } - - /** For internal use only. May be removed or replaced in the future. */ - public void updateReadOnly() { - debug("VFS: updateReadOnly()"); - tb.setReadOnly(readonly || !textInputEnabled); - } - - public void setTextInputEnabled(boolean textInputEnabled) { - debug("VFS: setTextInputEnabled()"); - // Always update styles as they might have been overwritten - if (textInputEnabled) { - removeStyleDependentName(STYLE_NO_INPUT); - Roles.getTextboxRole().removeAriaReadonlyProperty(tb.getElement()); - } else { - addStyleDependentName(STYLE_NO_INPUT); - Roles.getTextboxRole().setAriaReadonlyProperty(tb.getElement(), - true); - } - - if (this.textInputEnabled == textInputEnabled) { - return; - } - - this.textInputEnabled = textInputEnabled; - updateReadOnly(); - } - - /** - * Sets the text in the text box. - * - * @param text - * the text to set in the text box - */ - public void setTextboxText(final String text) { - if (enableDebug) { - debug("VFS: setTextboxText(" + text + ")"); - } - setText(text); - } - - private void setText(final String text) { - /** - * To leave caret in the beginning of the line. SetSelectionRange - * wouldn't work on IE (see #13477) - */ - Direction previousDirection = tb.getDirection(); - tb.setDirection(Direction.RTL); - tb.setText(text); - tb.setDirection(previousDirection); - } - - /** - * Turns prompting on. When prompting is turned on a command prompt is shown - * in the text box if nothing has been entered. - */ - public void setPromptingOn() { - debug("VFS: setPromptingOn()"); - if (!prompting) { - prompting = true; - addStyleDependentName(CLASSNAME_PROMPT); - } - setTextboxText(inputPrompt); - } - - /** - * Turns prompting off. When prompting is turned on a command prompt is - * shown in the text box if nothing has been entered. - * <p> - * For internal use only. May be removed or replaced in the future. - * - * @param text - * The text the text box should contain. - */ - public void setPromptingOff(String text) { - debug("VFS: setPromptingOff()"); - setTextboxText(text); - if (prompting) { - prompting = false; - removeStyleDependentName(CLASSNAME_PROMPT); - } - } - - /** - * Triggered when a suggestion is selected - * - * @param suggestion - * The suggestion that just got selected. - */ - public void onSuggestionSelected(FilterSelectSuggestion suggestion) { - if (enableDebug) { - debug("VFS: onSuggestionSelected(" + suggestion.caption + ": " - + suggestion.key + ")"); - } - dataReceivedHandler.cancelPendingPostFiltering(); - - currentSuggestion = suggestion; - String newKey; - if (suggestion.key.equals("")) { - // "nullselection" - newKey = ""; - } else { - // normal selection - newKey = suggestion.getOptionKey(); - } - - String text = suggestion.getReplacementString(); - if ("".equals(newKey) && !focused) { - setPromptingOn(); - } else { - setPromptingOff(text); - } - setSelectedItemIcon(suggestion.getIconUri()); - - if (!(newKey.equals(selectedOptionKey) - || ("".equals(newKey) && selectedOptionKey == null))) { - selectedOptionKey = newKey; - connector.sendSelection(selectedOptionKey); - - // currentPage = -1; // forget the page - } - - if (getSelectedCaption() != null && newKey.equals("")) { - // In scrollToPage(false) mode selecting null seems to be broken - // if current selection is not on first page. The above clause is so - // hard to interpret that new clause added here :-( - selectedOptionKey = newKey; - explicitSelectedCaption = null; - connector.sendSelection(selectedOptionKey); - } - - suggestionPopup.hide(); - } - - /** - * Sets the icon URI of the selected item. The icon is shown on the left - * side of the item caption text. Set the URI to null to remove the icon. - * - * @param iconUri - * The URI of the icon - */ - public void setSelectedItemIcon(String iconUri) { - - if (iconUri == null || iconUri.length() == 0) { - if (selectedItemIcon != null) { - panel.remove(selectedItemIcon); - selectedItemIcon = null; - afterSelectedItemIconChange(); - } - } else { - if (selectedItemIcon != null) { - panel.remove(selectedItemIcon); - } - selectedItemIcon = new IconWidget( - connector.getConnection().getIcon(iconUri)); - // Older IE versions don't scale icon correctly if DOM - // contains height and width attributes. - selectedItemIcon.getElement().removeAttribute("height"); - selectedItemIcon.getElement().removeAttribute("width"); - selectedItemIcon.addDomHandler(new LoadHandler() { - @Override - public void onLoad(LoadEvent event) { - afterSelectedItemIconChange(); - } - }, LoadEvent.getType()); - panel.insert(selectedItemIcon, 0); - afterSelectedItemIconChange(); - } - } - - private void afterSelectedItemIconChange() { - if (BrowserInfo.get().isWebkit()) { - // Some browsers need a nudge to reposition the text field - forceReflow(); - } - updateRootWidth(); - if (selectedItemIcon != null) { - updateSelectedIconPosition(); - } - } - - /** - * Perform selection based on a message from the server. - * - * This method is called when the server gave a non-empty selected item key, - * whereas null selection is handled by {@link #resetSelection()} and the - * special case where the selected item is not on the current page is - * handled separately by the caller. - * - * @param selectedKey - * non-empty selected item key - * @param oldSuggestionTextMatchTheOldSelection - * true if the suggestion box text matched the previous selection - * before the message from the server updating the selection - * @param updatePromptAndSelectionIfMatchFound - */ - private void performSelection(String selectedKey, - boolean oldSuggestionTextMatchTheOldSelection, - boolean updatePromptAndSelectionIfMatchFound) { - // some item selected - for (FilterSelectSuggestion suggestion : currentSuggestions) { - String suggestionKey = suggestion.getOptionKey(); - if (!suggestionKey.equals(selectedKey)) { - continue; - } - // at this point, suggestion key matches the new selection key - if (updatePromptAndSelectionIfMatchFound) { - if (!suggestionKey.equals(selectedOptionKey) - || suggestion.getReplacementString() - .equals(tb.getText()) - || oldSuggestionTextMatchTheOldSelection) { - // Update text field if we've got a new - // selection - // Also update if we've got the same text to - // retain old text selection behavior - // OR if selected item caption is changed. - setPromptingOff(suggestion.getReplacementString()); - selectedOptionKey = suggestionKey; - } - } - currentSuggestion = suggestion; - setSelectedItemIcon(suggestion.getIconUri()); - // only a single item can be selected - break; - } - } - - /** - * Reset the selection of the combo box to an empty string if focused, the - * input prompt if not. - * - * This method also clears the current suggestion and the selected option - * key. - */ - private void resetSelection(boolean useSelectedCaption) { - // select nulled - if (!focused) { - // TODO it is unclear whether this is really needed anymore - - // client.updateComponent used to overwrite all styles so we had to - // set them again - setPromptingOff(""); - if (enabled && !readonly) { - setPromptingOn(); - } - } else { - // we have focus in field, prompting can't be set on, - // instead just clear the input if the value has changed from - // something else to null - if (selectedOptionKey != null - || (allowNewItem && !tb.getValue().isEmpty())) { - if (useSelectedCaption && getSelectedCaption() != null) { - tb.setValue(getSelectedCaption()); - tb.selectAll(); - } else { - tb.setValue(""); - } - } - } - currentSuggestion = null; // #13217 - setSelectedItemIcon(null); - selectedOptionKey = null; - } - - private void forceReflow() { - WidgetUtil.setStyleTemporarily(tb.getElement(), "zoom", "1"); - } - - /** - * Positions the icon vertically in the middle. Should be called after the - * icon has loaded - */ - private void updateSelectedIconPosition() { - // Position icon vertically to middle - int availableHeight = 0; - availableHeight = getOffsetHeight(); - - int iconHeight = WidgetUtil.getRequiredHeight(selectedItemIcon); - int marginTop = (availableHeight - iconHeight) / 2; - selectedItemIcon.getElement().getStyle().setMarginTop(marginTop, - Unit.PX); - } - - private static Set<Integer> navigationKeyCodes = new HashSet<Integer>(); - static { - navigationKeyCodes.add(KeyCodes.KEY_DOWN); - navigationKeyCodes.add(KeyCodes.KEY_UP); - navigationKeyCodes.add(KeyCodes.KEY_PAGEDOWN); - navigationKeyCodes.add(KeyCodes.KEY_PAGEUP); - navigationKeyCodes.add(KeyCodes.KEY_ENTER); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt - * .event.dom.client.KeyDownEvent) - */ - - @Override - public void onKeyDown(KeyDownEvent event) { - if (enabled && !readonly) { - int keyCode = event.getNativeKeyCode(); - - if (enableDebug) { - debug("VFS: key down: " + keyCode); - } - if (dataReceivedHandler.isWaitingForFilteringResponse() - && navigationKeyCodes.contains(keyCode)) { - /* - * Keyboard navigation events should not be handled while we are - * waiting for a response. This avoids flickering, disappearing - * items, wrongly interpreted responses and more. - */ - if (enableDebug) { - debug("Ignoring " + keyCode - + " because we are waiting for a filtering response"); - } - DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); - event.stopPropagation(); - return; - } - - if (suggestionPopup.isAttached()) { - if (enableDebug) { - debug("Keycode " + keyCode + " target is popup"); - } - popupKeyDown(event); - } else { - if (enableDebug) { - debug("Keycode " + keyCode + " target is text field"); - } - inputFieldKeyDown(event); - } - } - } - - private void debug(String string) { - if (enableDebug) { - VConsole.error(string); - } - } - - /** - * Triggered when a key is pressed in the text box - * - * @param event - * The KeyDownEvent - */ - private void inputFieldKeyDown(KeyDownEvent event) { - if (enableDebug) { - debug("VFS: inputFieldKeyDown(" + event.getNativeKeyCode() + ")"); - } - switch (event.getNativeKeyCode()) { - case KeyCodes.KEY_DOWN: - case KeyCodes.KEY_UP: - case KeyCodes.KEY_PAGEDOWN: - case KeyCodes.KEY_PAGEUP: - // open popup as from gadget - filterOptions(-1, ""); - lastFilter = ""; - tb.selectAll(); - break; - case KeyCodes.KEY_ENTER: - /* - * This only handles the case when new items is allowed, a text is - * entered, the popup opener button is clicked to close the popup - * and enter is then pressed (see #7560). - */ - if (!allowNewItem) { - return; - } - - if (currentSuggestion != null && tb.getText() - .equals(currentSuggestion.getReplacementString())) { - // Retain behavior from #6686 by returning without stopping - // propagation if there's nothing to do - return; - } - suggestionPopup.menu.doSelectedItemAction(); - - event.stopPropagation(); - break; - } - - } - - /** - * Triggered when a key was pressed in the suggestion popup. - * - * @param event - * The KeyDownEvent of the key - */ - private void popupKeyDown(KeyDownEvent event) { - if (enableDebug) { - debug("VFS: popupKeyDown(" + event.getNativeKeyCode() + ")"); - } - // Propagation of handled events is stopped so other handlers such as - // shortcut key handlers do not also handle the same events. - switch (event.getNativeKeyCode()) { - case KeyCodes.KEY_DOWN: - suggestionPopup.selectNextItem(); - - DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); - event.stopPropagation(); - break; - case KeyCodes.KEY_UP: - suggestionPopup.selectPrevItem(); - - DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); - event.stopPropagation(); - break; - case KeyCodes.KEY_PAGEDOWN: - selectNextPage(); - event.stopPropagation(); - break; - case KeyCodes.KEY_PAGEUP: - selectPrevPage(); - event.stopPropagation(); - break; - case KeyCodes.KEY_ESCAPE: - reset(); - DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); - event.stopPropagation(); - break; - case KeyCodes.KEY_TAB: - case KeyCodes.KEY_ENTER: - - if (!allowNewItem) { - int selected = suggestionPopup.menu.getSelectedIndex(); - if (selected != -1) { - onSuggestionSelected(currentSuggestions.get(selected)); - } else { - // The way VFilterSelect is done, it handles enter and tab - // in exactly the same way so we close the popup in both - // cases even though we could leave it open when pressing - // enter - suggestionPopup.hide(); - } - } else { - // Handle addition of new items. - suggestionPopup.menu.doSelectedItemAction(); - } - - event.stopPropagation(); - break; - } - - } - - /* - * Show the prev page. - */ - private void selectPrevPage() { - if (currentPage > 0) { - filterOptions(currentPage - 1, lastFilter); - dataReceivedHandler.setNavigationCallback(new Runnable() { - @Override - public void run() { - suggestionPopup.selectLastItem(); - } - }); - } - } - - /* - * Show the next page. - */ - private void selectNextPage() { - if (hasNextPage()) { - filterOptions(currentPage + 1, lastFilter); - dataReceivedHandler.setNavigationCallback(new Runnable() { - @Override - public void run() { - suggestionPopup.selectFirstItem(); - } - }); - } - } - - /** - * Triggered when a key was depressed - * - * @param event - * The KeyUpEvent of the key depressed - */ - - @Override - public void onKeyUp(KeyUpEvent event) { - if (enableDebug) { - debug("VFS: onKeyUp(" + event.getNativeKeyCode() + ")"); - } - if (enabled && !readonly) { - switch (event.getNativeKeyCode()) { - case KeyCodes.KEY_ENTER: - case KeyCodes.KEY_TAB: - case KeyCodes.KEY_SHIFT: - case KeyCodes.KEY_CTRL: - case KeyCodes.KEY_ALT: - case KeyCodes.KEY_DOWN: - case KeyCodes.KEY_UP: - case KeyCodes.KEY_PAGEDOWN: - case KeyCodes.KEY_PAGEUP: - case KeyCodes.KEY_ESCAPE: - // NOP - break; - default: - if (textInputEnabled) { - // when filtering, we always want to see the results on the - // first page first. - filterOptions(0); - } - break; - } - } - } - - /** - * Resets the Select to its initial state - */ - private void reset() { - debug("VFS: reset()"); - if (currentSuggestion != null) { - String text = currentSuggestion.getReplacementString(); - setPromptingOff(text); - setSelectedItemIcon(currentSuggestion.getIconUri()); - - selectedOptionKey = currentSuggestion.key; - - } else { - if (focused || readonly || !enabled) { - setPromptingOff(""); - } else { - setPromptingOn(); - } - setSelectedItemIcon(null); - - selectedOptionKey = null; - } - - lastFilter = ""; - suggestionPopup.hide(); - } - - /** - * Listener for popupopener - */ - - @Override - public void onClick(ClickEvent event) { - debug("VFS: onClick()"); - if (textInputEnabled && event.getNativeEvent().getEventTarget() - .cast() == tb.getElement()) { - // Don't process clicks on the text field if text input is enabled - return; - } - if (enabled && !readonly) { - // ask suggestionPopup if it was just closed, we are using GWT - // Popup's auto close feature - if (!suggestionPopup.isJustClosed()) { - filterOptions(-1, ""); - dataReceivedHandler.popupOpenerClicked(); - lastFilter = ""; - } - DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); - focus(); - tb.selectAll(); - } - } - - /** - * Update minimum width for FilterSelect textarea based on input prompt and - * suggestions. - * <p> - * For internal use only. May be removed or replaced in the future. - */ - public void updateSuggestionPopupMinWidth() { - // used only to calculate minimum width - String captions = WidgetUtil.escapeHTML(inputPrompt); - - for (FilterSelectSuggestion suggestion : currentSuggestions) { - // Collect captions so we can calculate minimum width for - // textarea - if (captions.length() > 0) { - captions += "|"; - } - captions += WidgetUtil - .escapeHTML(suggestion.getReplacementString()); - } - - // Calculate minimum textarea width - suggestionPopupMinWidth = minWidth(captions); - } - - /** - * Calculate minimum width for FilterSelect textarea. - * <p> - * For internal use only. May be removed or replaced in the future. - */ - public native int minWidth(String captions) - /*-{ - if(!captions || captions.length <= 0) - return 0; - captions = captions.split("|"); - var d = $wnd.document.createElement("div"); - var html = ""; - for(var i=0; i < captions.length; i++) { - html += "<div>" + captions[i] + "</div>"; - // TODO apply same CSS classname as in suggestionmenu - } - d.style.position = "absolute"; - d.style.top = "0"; - d.style.left = "0"; - d.style.visibility = "hidden"; - d.innerHTML = html; - $wnd.document.body.appendChild(d); - var w = d.offsetWidth; - $wnd.document.body.removeChild(d); - return w; - }-*/; - - /** - * A flag which prevents a focus event from taking place - */ - boolean iePreventNextFocus = false; - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event - * .dom.client.FocusEvent) - */ - - @Override - public void onFocus(FocusEvent event) { - debug("VFS: onFocus()"); - - /* - * When we disable a blur event in ie we need to refocus the textfield. - * This will cause a focus event we do not want to process, so in that - * case we just ignore it. - */ - if (BrowserInfo.get().isIE() && iePreventNextFocus) { - iePreventNextFocus = false; - return; - } - - focused = true; - if (prompting && !readonly) { - setPromptingOff(""); - } - addStyleDependentName("focus"); - - connector.sendFocusEvent(); - - connector.getConnection().getVTooltip() - .showAssistive(connector.getTooltipInfo(getElement())); - } - - /** - * A flag which cancels the blur event and sets the focus back to the - * textfield if the Browser is IE - */ - boolean preventNextBlurEventInIE = false; - - private String explicitSelectedCaption; - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event - * .dom.client.BlurEvent) - */ - - @Override - public void onBlur(BlurEvent event) { - debug("VFS: onBlur()"); - - if (BrowserInfo.get().isIE() && preventNextBlurEventInIE) { - /* - * Clicking in the suggestion popup or on the popup button in IE - * causes a blur event to be sent for the field. In other browsers - * this is prevented by canceling/preventing default behavior for - * the focus event, in IE we handle it here by refocusing the text - * field and ignoring the resulting focus event for the textfield - * (in onFocus). - */ - preventNextBlurEventInIE = false; - - Element focusedElement = WidgetUtil.getFocusedElement(); - if (getElement().isOrHasChild(focusedElement) || suggestionPopup - .getElement().isOrHasChild(focusedElement)) { - - // IF the suggestion popup or another part of the VFilterSelect - // was focused, move the focus back to the textfield and prevent - // the triggered focus event (in onFocus). - iePreventNextFocus = true; - tb.setFocus(true); - return; - } - } - - focused = false; - if (!readonly) { - if (selectedOptionKey == null) { - if (explicitSelectedCaption != null) { - setPromptingOff(explicitSelectedCaption); - } else { - setPromptingOn(); - } - } else if (currentSuggestion != null) { - setPromptingOff(currentSuggestion.caption); - } - } - removeStyleDependentName("focus"); - - connector.sendBlurEvent(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.client.Focusable#focus() - */ - - @Override - public void focus() { - debug("VFS: focus()"); - focused = true; - if (prompting && !readonly) { - setPromptingOff(""); - } - tb.setFocus(true); - } - - /** - * Calculates the width of the select if the select has undefined width. - * Should be called when the width changes or when the icon changes. - * <p> - * For internal use only. May be removed or replaced in the future. - */ - public void updateRootWidth() { - if (connector.isUndefinedWidth()) { - - /* - * When the select has a undefined with we need to check that we are - * only setting the text box width relative to the first page width - * of the items. If this is not done the text box width will change - * when the popup is used to view longer items than the text box is - * wide. - */ - int w = WidgetUtil.getRequiredWidth(this); - - if ((!initDone || currentPage + 1 < 0) - && suggestionPopupMinWidth > w) { - /* - * We want to compensate for the paddings just to preserve the - * exact size as in Vaadin 6.x, but we get here before - * MeasuredSize has been initialized. - * Util.measureHorizontalPaddingAndBorder does not work with - * border-box, so we must do this the hard way. - */ - Style style = getElement().getStyle(); - String originalPadding = style.getPadding(); - String originalBorder = style.getBorderWidth(); - style.setPaddingLeft(0, Unit.PX); - style.setBorderWidth(0, Unit.PX); - style.setProperty("padding", originalPadding); - style.setProperty("borderWidth", originalBorder); - - // Use util.getRequiredWidth instead of getOffsetWidth here - - int iconWidth = selectedItemIcon == null ? 0 - : WidgetUtil.getRequiredWidth(selectedItemIcon); - int buttonWidth = popupOpener == null ? 0 - : WidgetUtil.getRequiredWidth(popupOpener); - - /* - * Instead of setting the width of the wrapper, set the width of - * the combobox. Subtract the width of the icon and the - * popupopener - */ - - tb.setWidth((suggestionPopupMinWidth - iconWidth - buttonWidth) - + "px"); - - } - - /* - * Lock the textbox width to its current value if it's not already - * locked - */ - if (!tb.getElement().getStyle().getWidth().endsWith("px")) { - int iconWidth = selectedItemIcon == null ? 0 - : selectedItemIcon.getOffsetWidth(); - tb.setWidth((tb.getOffsetWidth() - iconWidth) + "px"); - } - } - } - - /** - * Get the width of the select in pixels where the text area and icon has - * been included. - * - * @return The width in pixels - */ - private int getMainWidth() { - return getOffsetWidth(); - } - - @Override - public void setWidth(String width) { - super.setWidth(width); - if (width.length() != 0) { - tb.setWidth("100%"); - } - } - - /** - * Handles special behavior of the mouse down event - * - * @param event - */ - private void handleMouseDownEvent(Event event) { - /* - * Prevent the keyboard focus from leaving the textfield by preventing - * the default behaviour of the browser. Fixes #4285. - */ - if (event.getTypeInt() == Event.ONMOUSEDOWN) { - event.preventDefault(); - event.stopPropagation(); - - /* - * In IE the above wont work, the blur event will still trigger. So, - * we set a flag here to prevent the next blur event from happening. - * This is not needed if do not already have focus, in that case - * there will not be any blur event and we should not cancel the - * next blur. - */ - if (BrowserInfo.get().isIE() && focused) { - preventNextBlurEventInIE = true; - debug("VFS: Going to prevent next blur event on IE"); - } - } - } - - @Override - protected void onDetach() { - super.onDetach(); - suggestionPopup.hide(); - } - - @Override - public com.google.gwt.user.client.Element getSubPartElement( - String subPart) { - String[] parts = subPart.split("/"); - if ("textbox".equals(parts[0])) { - return tb.getElement(); - } else if ("button".equals(parts[0])) { - return popupOpener.getElement(); - } else if ("popup".equals(parts[0]) && suggestionPopup.isAttached()) { - if (parts.length == 2) { - return suggestionPopup.menu.getSubPartElement(parts[1]); - } - return suggestionPopup.getElement(); - } - return null; - } - - @Override - public String getSubPartName( - com.google.gwt.user.client.Element subElement) { - if (tb.getElement().isOrHasChild(subElement)) { - return "textbox"; - } else if (popupOpener.getElement().isOrHasChild(subElement)) { - return "button"; - } else if (suggestionPopup.getElement().isOrHasChild(subElement)) { - return "popup"; - } - return null; - } - - @Override - public void setAriaRequired(boolean required) { - AriaHelper.handleInputRequired(tb, required); - } - - @Override - public void setAriaInvalid(boolean invalid) { - AriaHelper.handleInputInvalid(tb, invalid); - } - - @Override - public void bindAriaCaption( - com.google.gwt.user.client.Element captionElement) { - AriaHelper.bindCaption(tb, captionElement); - } - - @Override - public boolean isWorkPending() { - return dataReceivedHandler.isWaitingForFilteringResponse() - || suggestionPopup.lazyPageScroller.isRunning(); - } - - /** - * Sets the caption of selected item, if "scroll to page" is disabled. This - * method is meant for internal use and may change in future versions. - * - * @since 7.7 - * @param selectedCaption - * the caption of selected item - */ - public void setSelectedCaption(String selectedCaption) { - explicitSelectedCaption = selectedCaption; - if (selectedCaption != null) { - setPromptingOff(selectedCaption); - } - } - - /** - * This method is meant for internal use and may change in future versions. - * - * @since 7.7 - * @return the caption of selected item, if "scroll to page" is disabled - */ - public String getSelectedCaption() { - return explicitSelectedCaption; - } - - /** - * Returns a handler receiving notifications from the connector about - * communications. - * - * @return the dataReceivedHandler - */ - public DataReceivedHandler getDataReceivedHandler() { - return dataReceivedHandler; - } - -} diff --git a/client/src/main/java/com/vaadin/client/ui/VTree.java b/client/src/main/java/com/vaadin/client/ui/VTree.java deleted file mode 100644 index f9101a5e30..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/VTree.java +++ /dev/null @@ -1,2267 +0,0 @@ -/* - * Copyright 2000-2016 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; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -import com.google.gwt.aria.client.ExpandedValue; -import com.google.gwt.aria.client.Id; -import com.google.gwt.aria.client.Roles; -import com.google.gwt.aria.client.SelectedValue; -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.dom.client.Node; -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.ContextMenuEvent; -import com.google.gwt.event.dom.client.ContextMenuHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.SimplePanel; -import com.google.gwt.user.client.ui.UIObject; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.ApplicationConnection; -import com.vaadin.client.BrowserInfo; -import com.vaadin.client.ComponentConnector; -import com.vaadin.client.ConnectorMap; -import com.vaadin.client.MouseEventDetailsBuilder; -import com.vaadin.client.UIDL; -import com.vaadin.client.Util; -import com.vaadin.client.WidgetUtil; -import com.vaadin.client.ui.aria.AriaHelper; -import com.vaadin.client.ui.aria.HandlesAriaCaption; -import com.vaadin.client.ui.dd.DDUtil; -import com.vaadin.client.ui.dd.VAbstractDropHandler; -import com.vaadin.client.ui.dd.VAcceptCallback; -import com.vaadin.client.ui.dd.VDragAndDropManager; -import com.vaadin.client.ui.dd.VDragEvent; -import com.vaadin.client.ui.dd.VDropHandler; -import com.vaadin.client.ui.dd.VHasDropHandler; -import com.vaadin.client.ui.dd.VTransferable; -import com.vaadin.client.ui.tree.TreeConnector; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.MouseEventDetails.MouseButton; -import com.vaadin.shared.ui.MultiSelectMode; -import com.vaadin.shared.ui.dd.VerticalDropLocation; -import com.vaadin.shared.ui.tree.TreeConstants; - -/** - * - */ -public class VTree extends FocusElementPanel - implements VHasDropHandler, FocusHandler, BlurHandler, KeyPressHandler, - KeyDownHandler, SubPartAware, ActionOwner, HandlesAriaCaption { - private String lastNodeKey = ""; - - public static final String CLASSNAME = "v-tree"; - - /** - * @deprecated As of 7.0, use {@link MultiSelectMode#DEFAULT} instead. - */ - @Deprecated - public static final MultiSelectMode MULTISELECT_MODE_DEFAULT = MultiSelectMode.DEFAULT; - - /** - * @deprecated As of 7.0, use {@link MultiSelectMode#SIMPLE} instead. - */ - @Deprecated - public static final MultiSelectMode MULTISELECT_MODE_SIMPLE = MultiSelectMode.SIMPLE; - - private static final int CHARCODE_SPACE = 32; - - /** For internal use only. May be removed or replaced in the future. */ - public final FlowPanel body = new FlowPanel(); - - /** For internal use only. May be removed or replaced in the future. */ - public Set<String> selectedIds = new HashSet<String>(); - - /** For internal use only. May be removed or replaced in the future. */ - public ApplicationConnection client; - - /** For internal use only. May be removed or replaced in the future. */ - public String paintableId; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean selectable; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean isMultiselect; - - private String currentMouseOverKey; - - /** For internal use only. May be removed or replaced in the future. */ - public TreeNode lastSelection; - - /** For internal use only. May be removed or replaced in the future. */ - public TreeNode focusedNode; - - /** For internal use only. May be removed or replaced in the future. */ - public MultiSelectMode multiSelectMode = MultiSelectMode.DEFAULT; - - private final HashMap<String, TreeNode> keyToNode = new HashMap<String, TreeNode>(); - - /** - * This map contains captions and icon urls for actions like: * "33_c" -> - * "Edit" * "33_i" -> "http://dom.com/edit.png" - */ - private final HashMap<String, String> actionMap = new HashMap<String, String>(); - - /** For internal use only. May be removed or replaced in the future. */ - public boolean immediate; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean isNullSelectionAllowed = true; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean isHtmlContentAllowed = false; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean disabled = false; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean readonly; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean rendering; - - private VAbstractDropHandler dropHandler; - - /** For internal use only. May be removed or replaced in the future. */ - public int dragMode; - - private boolean selectionHasChanged = false; - - /* - * to fix #14388. The cause of defect #14388: event 'clickEvent' is sent to - * server before updating of "selected" variable, but should be sent after - * it - */ - private boolean clickEventPending = false; - - /** For internal use only. May be removed or replaced in the future. */ - public String[] bodyActionKeys; - - /** For internal use only. May be removed or replaced in the future. */ - public TreeConnector connector; - - public VLazyExecutor iconLoaded = new VLazyExecutor(50, - new ScheduledCommand() { - - @Override - public void execute() { - doLayout(); - } - - }); - - public VTree() { - super(); - setStyleName(CLASSNAME); - - Roles.getTreeRole().set(body.getElement()); - add(body); - - addFocusHandler(this); - addBlurHandler(this); - - /* - * Listen to context menu events on the empty space in the tree - */ - sinkEvents(Event.ONCONTEXTMENU); - addDomHandler(new ContextMenuHandler() { - @Override - public void onContextMenu(ContextMenuEvent event) { - handleBodyContextMenu(event); - } - }, ContextMenuEvent.getType()); - - /* - * Firefox auto-repeat works correctly only if we use a key press - * handler, other browsers handle it correctly when using a key down - * handler - */ - if (BrowserInfo.get().isGecko()) { - addKeyPressHandler(this); - } else { - addKeyDownHandler(this); - } - - /* - * We need to use the sinkEvents method to catch the keyUp events so we - * can cache a single shift. KeyUpHandler cannot do this. At the same - * time we catch the mouse down and up events so we can apply the text - * selection patch in IE - */ - sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP | Event.ONKEYUP); - - /* - * Re-set the tab index to make sure that the FocusElementPanel's - * (super) focus element gets the tab index and not the element - * containing the tree. - */ - setTabIndex(0); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt.user - * .client.Event) - */ - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - if (event.getTypeInt() == Event.ONMOUSEDOWN) { - // Prevent default text selection in IE - if (BrowserInfo.get().isIE()) { - ((Element) event.getEventTarget().cast()).setPropertyJSO( - "onselectstart", applyDisableTextSelectionIEHack()); - } - } else if (event.getTypeInt() == Event.ONMOUSEUP) { - // Remove IE text selection hack - if (BrowserInfo.get().isIE()) { - ((Element) event.getEventTarget().cast()) - .setPropertyJSO("onselectstart", null); - } - } else if (event.getTypeInt() == Event.ONKEYUP) { - if (selectionHasChanged) { - if (event.getKeyCode() == getNavigationDownKey() - && !event.getShiftKey()) { - sendSelectionToServer(); - event.preventDefault(); - } else if (event.getKeyCode() == getNavigationUpKey() - && !event.getShiftKey()) { - sendSelectionToServer(); - event.preventDefault(); - } else if (event.getKeyCode() == KeyCodes.KEY_SHIFT) { - sendSelectionToServer(); - event.preventDefault(); - } else if (event.getKeyCode() == getNavigationSelectKey()) { - sendSelectionToServer(); - event.preventDefault(); - } - } - } - } - - public String getActionCaption(String actionKey) { - return actionMap.get(actionKey + "_c"); - } - - public String getActionIcon(String actionKey) { - return actionMap.get(actionKey + "_i"); - } - - /** - * Returns the first root node of the tree or null if there are no root - * nodes. - * - * @return The first root {@link TreeNode} - */ - protected TreeNode getFirstRootNode() { - if (body.getWidgetCount() == 0) { - return null; - } - return (TreeNode) body.getWidget(0); - } - - /** - * Returns the last root node of the tree or null if there are no root - * nodes. - * - * @return The last root {@link TreeNode} - */ - protected TreeNode getLastRootNode() { - if (body.getWidgetCount() == 0) { - return null; - } - return (TreeNode) body.getWidget(body.getWidgetCount() - 1); - } - - /** - * Returns a list of all root nodes in the Tree in the order they appear in - * the tree. - * - * @return A list of all root {@link TreeNode}s. - */ - protected List<TreeNode> getRootNodes() { - ArrayList<TreeNode> rootNodes = new ArrayList<TreeNode>(); - for (int i = 0; i < body.getWidgetCount(); i++) { - rootNodes.add((TreeNode) body.getWidget(i)); - } - return rootNodes; - } - - private void updateTreeRelatedDragData(VDragEvent drag) { - - currentMouseOverKey = findCurrentMouseOverKey(drag.getElementOver()); - - drag.getDropDetails().put("itemIdOver", currentMouseOverKey); - if (currentMouseOverKey != null) { - TreeNode treeNode = getNodeByKey(currentMouseOverKey); - VerticalDropLocation detail = treeNode - .getDropDetail(drag.getCurrentGwtEvent()); - Boolean overTreeNode = null; - if (treeNode != null && !treeNode.isLeaf() - && detail == VerticalDropLocation.MIDDLE) { - overTreeNode = true; - } - drag.getDropDetails().put("itemIdOverIsNode", overTreeNode); - drag.getDropDetails().put("detail", detail); - } else { - drag.getDropDetails().put("itemIdOverIsNode", null); - drag.getDropDetails().put("detail", null); - } - - } - - private String findCurrentMouseOverKey(Element elementOver) { - TreeNode treeNode = WidgetUtil.findWidget(elementOver, TreeNode.class); - return treeNode == null ? null : treeNode.key; - } - - /** For internal use only. May be removed or replaced in the future. */ - public void updateDropHandler(UIDL childUidl) { - if (dropHandler == null) { - dropHandler = new VAbstractDropHandler() { - - @Override - public void dragEnter(VDragEvent drag) { - } - - @Override - protected void dragAccepted(final VDragEvent drag) { - - } - - @Override - public void dragOver(final VDragEvent currentDrag) { - final Object oldIdOver = currentDrag.getDropDetails() - .get("itemIdOver"); - final VerticalDropLocation oldDetail = (VerticalDropLocation) currentDrag - .getDropDetails().get("detail"); - - updateTreeRelatedDragData(currentDrag); - final VerticalDropLocation detail = (VerticalDropLocation) currentDrag - .getDropDetails().get("detail"); - boolean nodeHasChanged = (currentMouseOverKey != null - && currentMouseOverKey != oldIdOver) - || (currentMouseOverKey == null - && oldIdOver != null); - boolean detailHasChanded = (detail != null - && detail != oldDetail) - || (detail == null && oldDetail != null); - - if (nodeHasChanged || detailHasChanded) { - final String newKey = currentMouseOverKey; - TreeNode treeNode = keyToNode.get(oldIdOver); - if (treeNode != null) { - // clear old styles - treeNode.emphasis(null); - } - if (newKey != null) { - validate(new VAcceptCallback() { - @Override - public void accepted(VDragEvent event) { - VerticalDropLocation curDetail = (VerticalDropLocation) event - .getDropDetails().get("detail"); - if (curDetail == detail && newKey - .equals(currentMouseOverKey)) { - getNodeByKey(newKey).emphasis(detail); - } - /* - * Else drag is already on a different - * node-detail pair, new criteria check is - * going on - */ - } - }, currentDrag); - - } - } - - } - - @Override - public void dragLeave(VDragEvent drag) { - cleanUp(); - } - - private void cleanUp() { - if (currentMouseOverKey != null) { - getNodeByKey(currentMouseOverKey).emphasis(null); - currentMouseOverKey = null; - } - } - - @Override - public boolean drop(VDragEvent drag) { - cleanUp(); - return super.drop(drag); - } - - @Override - public ComponentConnector getConnector() { - return ConnectorMap.get(client).getConnector(VTree.this); - } - - @Override - public ApplicationConnection getApplicationConnection() { - return client; - } - - }; - } - dropHandler.updateAcceptRules(childUidl); - } - - public void setSelected(TreeNode treeNode, boolean selected) { - if (selected) { - if (!isMultiselect) { - while (selectedIds.size() > 0) { - final String id = selectedIds.iterator().next(); - final TreeNode oldSelection = getNodeByKey(id); - if (oldSelection != null) { - // can be null if the node is not visible (parent - // collapsed) - oldSelection.setSelected(false); - } - selectedIds.remove(id); - } - } - treeNode.setSelected(true); - selectedIds.add(treeNode.key); - } else { - if (!isNullSelectionAllowed) { - if (!isMultiselect || selectedIds.size() == 1) { - return; - } - } - selectedIds.remove(treeNode.key); - treeNode.setSelected(false); - } - - sendSelectionToServer(); - } - - /** - * Sends the selection to the server - */ - private void sendSelectionToServer() { - Command command = new Command() { - @Override - public void execute() { - /* - * we should send selection to server immediately in 2 cases: 1) - * 'immediate' property of Tree is true 2) clickEventPending is - * true - */ - client.updateVariable(paintableId, "selected", - selectedIds.toArray(new String[selectedIds.size()]), - clickEventPending || immediate); - clickEventPending = false; - selectionHasChanged = false; - } - }; - - /* - * Delaying the sending of the selection in webkit to ensure the - * selection is always sent when the tree has focus and after click - * events have been processed. This is due to the focusing - * implementation in FocusImplSafari which uses timeouts when focusing - * and blurring. - */ - if (BrowserInfo.get().isWebkit()) { - Scheduler.get().scheduleDeferred(command); - } else { - command.execute(); - } - } - - /** - * Is a node selected in the tree - * - * @param treeNode - * The node to check - * @return - */ - public boolean isSelected(TreeNode treeNode) { - return selectedIds.contains(treeNode.key); - } - - public class TreeNode extends SimplePanel implements ActionOwner { - - public static final String CLASSNAME = "v-tree-node"; - public static final String CLASSNAME_FOCUSED = CLASSNAME + "-focused"; - - public String key; - - /** For internal use only. May be removed or replaced in the future. */ - public String[] actionKeys = null; - - /** For internal use only. May be removed or replaced in the future. */ - public boolean childrenLoaded; - - Element nodeCaptionDiv; - - protected Element nodeCaptionSpan; - - /** For internal use only. May be removed or replaced in the future. */ - public FlowPanel childNodeContainer; - - private boolean open; - - private Icon icon; - - private Event mouseDownEvent; - - private int cachedHeight = -1; - - private boolean focused = false; - - public TreeNode() { - constructDom(); - sinkEvents(Event.ONCLICK | Event.ONDBLCLICK | Event.MOUSEEVENTS - | Event.TOUCHEVENTS | Event.ONCONTEXTMENU); - } - - public VerticalDropLocation getDropDetail(NativeEvent currentGwtEvent) { - if (cachedHeight < 0) { - /* - * Height is cached to avoid flickering (drop hints may change - * the reported offsetheight -> would change the drop detail) - */ - cachedHeight = nodeCaptionDiv.getOffsetHeight(); - } - VerticalDropLocation verticalDropLocation = DDUtil - .getVerticalDropLocation(nodeCaptionDiv, cachedHeight, - currentGwtEvent, 0.15); - return verticalDropLocation; - } - - protected void emphasis(VerticalDropLocation detail) { - String base = "v-tree-node-drag-"; - UIObject.setStyleName(getElement(), base + "top", - VerticalDropLocation.TOP == detail); - UIObject.setStyleName(getElement(), base + "bottom", - VerticalDropLocation.BOTTOM == detail); - UIObject.setStyleName(getElement(), base + "center", - VerticalDropLocation.MIDDLE == detail); - base = "v-tree-node-caption-drag-"; - UIObject.setStyleName(nodeCaptionDiv, base + "top", - VerticalDropLocation.TOP == detail); - UIObject.setStyleName(nodeCaptionDiv, base + "bottom", - VerticalDropLocation.BOTTOM == detail); - UIObject.setStyleName(nodeCaptionDiv, base + "center", - VerticalDropLocation.MIDDLE == detail); - - // also add classname to "folder node" into which the drag is - // targeted - - TreeNode folder = null; - /* Possible parent of this TreeNode will be stored here */ - TreeNode parentFolder = getParentNode(); - - // TODO fix my bugs - if (isLeaf()) { - folder = parentFolder; - // note, parent folder may be null if this is root node => no - // folder target exists - } else { - if (detail == VerticalDropLocation.TOP) { - folder = parentFolder; - } else { - folder = this; - } - // ensure we remove the dragfolder classname from the previous - // folder node - setDragFolderStyleName(this, false); - setDragFolderStyleName(parentFolder, false); - } - if (folder != null) { - setDragFolderStyleName(folder, detail != null); - } - - } - - private TreeNode getParentNode() { - Widget parent2 = getParent().getParent(); - if (parent2 instanceof TreeNode) { - return (TreeNode) parent2; - } - return null; - } - - private void setDragFolderStyleName(TreeNode folder, boolean add) { - if (folder != null) { - UIObject.setStyleName(folder.getElement(), - "v-tree-node-dragfolder", add); - UIObject.setStyleName(folder.nodeCaptionDiv, - "v-tree-node-caption-dragfolder", add); - } - } - - /** - * Handles mouse selection - * - * @param ctrl - * Was the ctrl-key pressed - * @param shift - * Was the shift-key pressed - * @return Returns true if event was handled, else false - */ - private boolean handleClickSelection(final boolean ctrl, - final boolean shift) { - - // always when clicking an item, focus it - setFocusedNode(this, false); - - if (!BrowserInfo.get().isOpera()) { - /* - * Ensure that the tree's focus element also gains focus - * (TreeNodes focus is faked using FocusElementPanel in browsers - * other than Opera). - */ - focus(); - } - - executeEventCommand(new ScheduledCommand() { - - @Override - public void execute() { - - if (multiSelectMode == MultiSelectMode.SIMPLE - || !isMultiselect) { - toggleSelection(); - lastSelection = TreeNode.this; - } else if (multiSelectMode == MultiSelectMode.DEFAULT) { - // Handle ctrl+click - if (isMultiselect && ctrl && !shift) { - toggleSelection(); - lastSelection = TreeNode.this; - - // Handle shift+click - } else if (isMultiselect && !ctrl && shift) { - deselectAll(); - selectNodeRange(lastSelection.key, key); - sendSelectionToServer(); - - // Handle ctrl+shift click - } else if (isMultiselect && ctrl && shift) { - selectNodeRange(lastSelection.key, key); - - // Handle click - } else { - // TODO should happen only if this alone not yet - // selected, - // now sending excess server calls - deselectAll(); - toggleSelection(); - lastSelection = TreeNode.this; - } - } - } - }); - - return true; - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt - * .user.client.Event) - */ - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - final int type = DOM.eventGetType(event); - final Element target = DOM.eventGetTarget(event); - - if (type == Event.ONLOAD && icon != null - && target == icon.getElement()) { - iconLoaded.trigger(); - } - - if (disabled) { - return; - } - - final boolean inCaption = isCaptionElement(target); - if (inCaption && client.hasEventListeners(VTree.this, - TreeConstants.ITEM_CLICK_EVENT_ID) - - && (type == Event.ONDBLCLICK || type == Event.ONMOUSEUP)) { - fireClick(event); - } - if (type == Event.ONCLICK) { - if (getElement() == target) { - // state change - toggleState(); - } else if (!readonly && inCaption) { - if (selectable) { - // caption click = selection change && possible click - // event - if (handleClickSelection( - event.getCtrlKey() || event.getMetaKey(), - event.getShiftKey())) { - event.preventDefault(); - } - } else { - // Not selectable, only focus the node. - setFocusedNode(this); - } - } - event.stopPropagation(); - } else if (type == Event.ONCONTEXTMENU) { - showContextMenu(event); - } - - if (dragMode != 0 || dropHandler != null) { - if (type == Event.ONMOUSEDOWN || type == Event.ONTOUCHSTART) { - if (nodeCaptionDiv.isOrHasChild( - (Node) event.getEventTarget().cast())) { - if (dragMode > 0 && (type == Event.ONTOUCHSTART || event - .getButton() == NativeEvent.BUTTON_LEFT)) { - mouseDownEvent = event; // save event for possible - // dd operation - if (type == Event.ONMOUSEDOWN) { - event.preventDefault(); // prevent text - // selection - } else { - /* - * FIXME We prevent touch start event to be used - * as a scroll start event. Note that we cannot - * easily distinguish whether the user wants to - * drag or scroll. The same issue is in table - * that has scrollable area and has drag and - * drop enable. Some kind of timer might be used - * to resolve the issue. - */ - event.stopPropagation(); - } - } - } - } else if (type == Event.ONMOUSEMOVE || type == Event.ONMOUSEOUT - || type == Event.ONTOUCHMOVE) { - - if (mouseDownEvent != null) { - // start actual drag on slight move when mouse is down - VTransferable t = new VTransferable(); - t.setDragSource(ConnectorMap.get(client) - .getConnector(VTree.this)); - t.setData("itemId", key); - VDragEvent drag = VDragAndDropManager.get().startDrag(t, - mouseDownEvent, true); - - drag.createDragImage(nodeCaptionDiv, true); - event.stopPropagation(); - - mouseDownEvent = null; - } - } else if (type == Event.ONMOUSEUP) { - mouseDownEvent = null; - } - if (type == Event.ONMOUSEOVER) { - mouseDownEvent = null; - currentMouseOverKey = key; - event.stopPropagation(); - } - - } else if (type == Event.ONMOUSEDOWN - && event.getButton() == NativeEvent.BUTTON_LEFT) { - event.preventDefault(); // text selection - } - } - - /** - * Checks if the given element is the caption or the icon. - * - * @param target - * The element to check - * @return true if the element is the caption or the icon - */ - public boolean isCaptionElement( - com.google.gwt.dom.client.Element target) { - return (target == nodeCaptionSpan - || (icon != null && target == icon.getElement())); - } - - private void fireClick(final Event evt) { - /* - * Ensure we have focus in tree before sending variables. Otherwise - * previously modified field may contain dirty variables. - */ - if (!treeHasFocus) { - if (BrowserInfo.get().isOpera()) { - if (focusedNode == null) { - getNodeByKey(key).setFocused(true); - } else { - focusedNode.setFocused(true); - } - } else { - focus(); - } - } - - final MouseEventDetails details = MouseEventDetailsBuilder - .buildMouseEventDetails(evt); - - executeEventCommand(new ScheduledCommand() { - - @Override - public void execute() { - // Determine if we should send the event immediately to the - // server. We do not want to send the event if there is a - // selection event happening after this. In all other cases - // we want to send it immediately. - clickEventPending = false; - if ((details.getButton() == MouseButton.LEFT - || details.getButton() == MouseButton.MIDDLE) - && !details.isDoubleClick() && selectable) { - // Probably a selection that will cause a value change - // event to be sent - clickEventPending = true; - - // The exception is that user clicked on the - // currently selected row and null selection is not - // allowed == no selection event - if (isSelected() && selectedIds.size() == 1 - && !isNullSelectionAllowed) { - clickEventPending = false; - } - } - client.updateVariable(paintableId, "clickedKey", key, - false); - client.updateVariable(paintableId, "clickEvent", - details.toString(), !clickEventPending); - } - }); - } - - /* - * Must wait for Safari to focus before sending click and value change - * events (see #6373, #6374) - */ - private void executeEventCommand(ScheduledCommand command) { - if (BrowserInfo.get().isWebkit() && !treeHasFocus) { - Scheduler.get().scheduleDeferred(command); - } else { - command.execute(); - } - } - - private void toggleSelection() { - if (selectable) { - VTree.this.setSelected(this, !isSelected()); - } - } - - private void toggleState() { - setState(!getState(), true); - } - - protected void constructDom() { - String labelId = DOM.createUniqueId(); - - addStyleName(CLASSNAME); - String treeItemId = DOM.createUniqueId(); - getElement().setId(treeItemId); - Roles.getTreeitemRole().set(getElement()); - Roles.getTreeitemRole().setAriaSelectedState(getElement(), - SelectedValue.FALSE); - Roles.getTreeitemRole().setAriaLabelledbyProperty(getElement(), - Id.of(labelId)); - - nodeCaptionDiv = DOM.createDiv(); - DOM.setElementProperty(nodeCaptionDiv, "className", - CLASSNAME + "-caption"); - Element wrapper = DOM.createDiv(); - wrapper.setId(labelId); - wrapper.setAttribute("for", treeItemId); - - nodeCaptionSpan = DOM.createSpan(); - DOM.appendChild(getElement(), nodeCaptionDiv); - DOM.appendChild(nodeCaptionDiv, wrapper); - DOM.appendChild(wrapper, nodeCaptionSpan); - - if (BrowserInfo.get().isOpera()) { - /* - * Focus the caption div of the node to get keyboard navigation - * to work without scrolling up or down when focusing a node. - */ - nodeCaptionDiv.setTabIndex(-1); - } - - childNodeContainer = new FlowPanel(); - childNodeContainer.setStyleName(CLASSNAME + "-children"); - Roles.getGroupRole().set(childNodeContainer.getElement()); - setWidget(childNodeContainer); - } - - public boolean isLeaf() { - String[] styleNames = getStyleName().split(" "); - for (String styleName : styleNames) { - if (styleName.equals(CLASSNAME + "-leaf")) { - return true; - } - } - return false; - } - - /** For internal use only. May be removed or replaced in the future. */ - public void setState(boolean state, boolean notifyServer) { - if (open == state) { - return; - } - if (state) { - if (!childrenLoaded && notifyServer) { - client.updateVariable(paintableId, "requestChildTree", true, - false); - } - if (notifyServer) { - client.updateVariable(paintableId, "expand", - new String[] { key }, true); - } - addStyleName(CLASSNAME + "-expanded"); - Roles.getTreeitemRole().setAriaExpandedState(getElement(), - ExpandedValue.TRUE); - childNodeContainer.setVisible(true); - } else { - removeStyleName(CLASSNAME + "-expanded"); - Roles.getTreeitemRole().setAriaExpandedState(getElement(), - ExpandedValue.FALSE); - childNodeContainer.setVisible(false); - if (notifyServer) { - client.updateVariable(paintableId, "collapse", - new String[] { key }, true); - } - } - open = state; - - if (!rendering) { - doLayout(); - } - } - - /** For internal use only. May be removed or replaced in the future. */ - public boolean getState() { - return open; - } - - /** For internal use only. May be removed or replaced in the future. */ - public void setText(String text) { - DOM.setInnerText(nodeCaptionSpan, text); - } - - /** For internal use only. May be removed or replaced in the future. */ - public void setHtml(String html) { - nodeCaptionSpan.setInnerHTML(html); - } - - public boolean isChildrenLoaded() { - return childrenLoaded; - } - - /** - * Returns the children of the node - * - * @return A set of tree nodes - */ - public List<TreeNode> getChildren() { - List<TreeNode> nodes = new LinkedList<TreeNode>(); - - if (!isLeaf() && isChildrenLoaded()) { - Iterator<Widget> iter = childNodeContainer.iterator(); - while (iter.hasNext()) { - TreeNode node = (TreeNode) iter.next(); - nodes.add(node); - } - } - return nodes; - } - - @Override - public Action[] getActions() { - if (actionKeys == null) { - return new Action[] {}; - } - final Action[] actions = new Action[actionKeys.length]; - for (int i = 0; i < actions.length; i++) { - final String actionKey = actionKeys[i]; - final TreeAction a = new TreeAction(this, String.valueOf(key), - actionKey); - a.setCaption(getActionCaption(actionKey)); - a.setIconUrl(getActionIcon(actionKey)); - actions[i] = a; - } - return actions; - } - - @Override - public ApplicationConnection getClient() { - return client; - } - - @Override - public String getPaintableId() { - return paintableId; - } - - /** - * Adds/removes Vaadin specific style name. - * <p> - * For internal use only. May be removed or replaced in the future. - * - * @param selected - */ - public void setSelected(boolean selected) { - // add style name to caption dom structure only, not to subtree - setStyleName(nodeCaptionDiv, "v-tree-node-selected", selected); - } - - protected boolean isSelected() { - return VTree.this.isSelected(this); - } - - /** - * Travels up the hierarchy looking for this node - * - * @param child - * The child which grandparent this is or is not - * @return True if this is a grandparent of the child node - */ - public boolean isGrandParentOf(TreeNode child) { - TreeNode currentNode = child; - boolean isGrandParent = false; - while (currentNode != null) { - currentNode = currentNode.getParentNode(); - if (currentNode == this) { - isGrandParent = true; - break; - } - } - return isGrandParent; - } - - public boolean isSibling(TreeNode node) { - return node.getParentNode() == getParentNode(); - } - - public void showContextMenu(Event event) { - if (!readonly && !disabled) { - if (actionKeys != null) { - int left = event.getClientX(); - int top = event.getClientY(); - top += Window.getScrollTop(); - left += Window.getScrollLeft(); - client.getContextMenu().showAt(this, left, top); - - event.stopPropagation(); - event.preventDefault(); - } - } - } - - /* - * (non-Javadoc) - * - * @see com.google.gwt.user.client.ui.Widget#onDetach() - */ - @Override - protected void onDetach() { - super.onDetach(); - client.getContextMenu().ensureHidden(this); - } - - /* - * (non-Javadoc) - * - * @see com.google.gwt.user.client.ui.UIObject#toString() - */ - @Override - public String toString() { - return nodeCaptionSpan.getInnerText(); - } - - /** - * Is the node focused? - * - * @param focused - * True if focused, false if not - */ - public void setFocused(boolean focused) { - if (!this.focused && focused) { - nodeCaptionDiv.addClassName(CLASSNAME_FOCUSED); - - this.focused = focused; - if (BrowserInfo.get().isOpera()) { - nodeCaptionDiv.focus(); - } - treeHasFocus = true; - } else if (this.focused && !focused) { - nodeCaptionDiv.removeClassName(CLASSNAME_FOCUSED); - this.focused = focused; - treeHasFocus = false; - } - } - - /** - * Scrolls the caption into view - */ - public void scrollIntoView() { - WidgetUtil.scrollIntoViewVertically(nodeCaptionDiv); - } - - public void setIcon(String iconUrl, String altText) { - if (icon != null) { - DOM.getFirstChild(nodeCaptionDiv) - .removeChild(icon.getElement()); - } - icon = client.getIcon(iconUrl); - if (icon != null) { - DOM.insertBefore(DOM.getFirstChild(nodeCaptionDiv), - icon.getElement(), nodeCaptionSpan); - icon.setAlternateText(altText); - } - } - - public void setNodeStyleName(String styleName) { - addStyleName(TreeNode.CLASSNAME + "-" + styleName); - setStyleName(nodeCaptionDiv, - TreeNode.CLASSNAME + "-caption-" + styleName, true); - childNodeContainer.addStyleName( - TreeNode.CLASSNAME + "-children-" + styleName); - - } - - } - - @Override - public VDropHandler getDropHandler() { - return dropHandler; - } - - public TreeNode getNodeByKey(String key) { - return keyToNode.get(key); - } - - /** - * Deselects all items in the tree - */ - public void deselectAll() { - for (String key : selectedIds) { - TreeNode node = keyToNode.get(key); - if (node != null) { - node.setSelected(false); - } - } - selectedIds.clear(); - selectionHasChanged = true; - } - - /** - * Selects a range of nodes - * - * @param startNodeKey - * The start node key - * @param endNodeKey - * The end node key - */ - private void selectNodeRange(String startNodeKey, String endNodeKey) { - - TreeNode startNode = keyToNode.get(startNodeKey); - TreeNode endNode = keyToNode.get(endNodeKey); - - // The nodes have the same parent - if (startNode.getParent() == endNode.getParent()) { - doSiblingSelection(startNode, endNode); - - // The start node is a grandparent of the end node - } else if (startNode.isGrandParentOf(endNode)) { - doRelationSelection(startNode, endNode); - - // The end node is a grandparent of the start node - } else if (endNode.isGrandParentOf(startNode)) { - doRelationSelection(endNode, startNode); - - } else { - doNoRelationSelection(startNode, endNode); - } - } - - /** - * Selects a node and deselect all other nodes - * - * @param node - * The node to select - */ - private void selectNode(TreeNode node, boolean deselectPrevious) { - if (deselectPrevious) { - deselectAll(); - } - - if (node != null) { - node.setSelected(true); - selectedIds.add(node.key); - lastSelection = node; - } - selectionHasChanged = true; - } - - /** - * Deselects a node - * - * @param node - * The node to deselect - */ - private void deselectNode(TreeNode node) { - node.setSelected(false); - selectedIds.remove(node.key); - selectionHasChanged = true; - } - - /** - * Selects all the open children to a node - * - * @param node - * The parent node - */ - private void selectAllChildren(TreeNode node, boolean includeRootNode) { - if (includeRootNode) { - node.setSelected(true); - selectedIds.add(node.key); - } - - for (TreeNode child : node.getChildren()) { - if (!child.isLeaf() && child.getState()) { - selectAllChildren(child, true); - } else { - child.setSelected(true); - selectedIds.add(child.key); - } - } - selectionHasChanged = true; - } - - /** - * Selects all children until a stop child is reached - * - * @param root - * The root not to start from - * @param stopNode - * The node to finish with - * @param includeRootNode - * Should the root node be selected - * @param includeStopNode - * Should the stop node be selected - * - * @return Returns false if the stop child was found, else true if all - * children was selected - */ - private boolean selectAllChildrenUntil(TreeNode root, TreeNode stopNode, - boolean includeRootNode, boolean includeStopNode) { - if (includeRootNode) { - root.setSelected(true); - selectedIds.add(root.key); - } - if (root.getState() && root != stopNode) { - for (TreeNode child : root.getChildren()) { - if (!child.isLeaf() && child.getState() && child != stopNode) { - if (!selectAllChildrenUntil(child, stopNode, true, - includeStopNode)) { - return false; - } - } else if (child == stopNode) { - if (includeStopNode) { - child.setSelected(true); - selectedIds.add(child.key); - } - return false; - } else { - child.setSelected(true); - selectedIds.add(child.key); - } - } - } - selectionHasChanged = true; - - return true; - } - - /** - * Select a range between two nodes which have no relation to each other - * - * @param startNode - * The start node to start the selection from - * @param endNode - * The end node to end the selection to - */ - private void doNoRelationSelection(TreeNode startNode, TreeNode endNode) { - - TreeNode commonParent = getCommonGrandParent(startNode, endNode); - TreeNode startBranch = null, endBranch = null; - - // Find the children of the common parent - List<TreeNode> children; - if (commonParent != null) { - children = commonParent.getChildren(); - } else { - children = getRootNodes(); - } - - // Find the start and end branches - for (TreeNode node : children) { - if (nodeIsInBranch(startNode, node)) { - startBranch = node; - } - if (nodeIsInBranch(endNode, node)) { - endBranch = node; - } - } - - // Swap nodes if necessary - if (children.indexOf(startBranch) > children.indexOf(endBranch)) { - TreeNode temp = startBranch; - startBranch = endBranch; - endBranch = temp; - - temp = startNode; - startNode = endNode; - endNode = temp; - } - - // Select all children under the start node - selectAllChildren(startNode, true); - TreeNode startParent = startNode.getParentNode(); - TreeNode currentNode = startNode; - while (startParent != null && startParent != commonParent) { - List<TreeNode> startChildren = startParent.getChildren(); - for (int i = startChildren.indexOf(currentNode) - + 1; i < startChildren.size(); i++) { - selectAllChildren(startChildren.get(i), true); - } - - currentNode = startParent; - startParent = startParent.getParentNode(); - } - - // Select nodes until the end node is reached - for (int i = children.indexOf(startBranch) + 1; i <= children - .indexOf(endBranch); i++) { - selectAllChildrenUntil(children.get(i), endNode, true, true); - } - - // Ensure end node was selected - endNode.setSelected(true); - selectedIds.add(endNode.key); - selectionHasChanged = true; - } - - /** - * Examines the children of the branch node and returns true if a node is in - * that branch - * - * @param node - * The node to search for - * @param branch - * The branch to search in - * @return True if found, false if not found - */ - private boolean nodeIsInBranch(TreeNode node, TreeNode branch) { - if (node == branch) { - return true; - } - for (TreeNode child : branch.getChildren()) { - if (child == node) { - return true; - } - if (!child.isLeaf() && child.getState()) { - if (nodeIsInBranch(node, child)) { - return true; - } - } - } - return false; - } - - /** - * Selects a range of items which are in direct relation with each - * other.<br/> - * NOTE: The start node <b>MUST</b> be before the end node! - * - * @param startNode - * - * @param endNode - */ - private void doRelationSelection(TreeNode startNode, TreeNode endNode) { - TreeNode currentNode = endNode; - while (currentNode != startNode) { - currentNode.setSelected(true); - selectedIds.add(currentNode.key); - - // Traverse children above the selection - List<TreeNode> subChildren = currentNode.getParentNode() - .getChildren(); - if (subChildren.size() > 1) { - selectNodeRange(subChildren.iterator().next().key, - currentNode.key); - } else if (subChildren.size() == 1) { - TreeNode n = subChildren.get(0); - n.setSelected(true); - selectedIds.add(n.key); - } - - currentNode = currentNode.getParentNode(); - } - startNode.setSelected(true); - selectedIds.add(startNode.key); - selectionHasChanged = true; - } - - /** - * Selects a range of items which have the same parent. - * - * @param startNode - * The start node - * @param endNode - * The end node - */ - private void doSiblingSelection(TreeNode startNode, TreeNode endNode) { - TreeNode parent = startNode.getParentNode(); - - List<TreeNode> children; - if (parent == null) { - // Topmost parent - children = getRootNodes(); - } else { - children = parent.getChildren(); - } - - // Swap start and end point if needed - if (children.indexOf(startNode) > children.indexOf(endNode)) { - TreeNode temp = startNode; - startNode = endNode; - endNode = temp; - } - - Iterator<TreeNode> childIter = children.iterator(); - boolean startFound = false; - while (childIter.hasNext()) { - TreeNode node = childIter.next(); - if (node == startNode) { - startFound = true; - } - - if (startFound && node != endNode && node.getState()) { - selectAllChildren(node, true); - } else if (startFound && node != endNode) { - node.setSelected(true); - selectedIds.add(node.key); - } - - if (node == endNode) { - node.setSelected(true); - selectedIds.add(node.key); - break; - } - } - selectionHasChanged = true; - } - - /** - * Returns the first common parent of two nodes - * - * @param node1 - * The first node - * @param node2 - * The second node - * @return The common parent or null - */ - public TreeNode getCommonGrandParent(TreeNode node1, TreeNode node2) { - // If either one does not have a grand parent then return null - if (node1.getParentNode() == null || node2.getParentNode() == null) { - return null; - } - - // If the nodes are parents of each other then return null - if (node1.isGrandParentOf(node2) || node2.isGrandParentOf(node1)) { - return null; - } - - // Get parents of node1 - List<TreeNode> parents1 = new ArrayList<TreeNode>(); - TreeNode parent1 = node1.getParentNode(); - while (parent1 != null) { - parents1.add(parent1); - parent1 = parent1.getParentNode(); - } - - // Get parents of node2 - List<TreeNode> parents2 = new ArrayList<TreeNode>(); - TreeNode parent2 = node2.getParentNode(); - while (parent2 != null) { - parents2.add(parent2); - parent2 = parent2.getParentNode(); - } - - // Search the parents for the first common parent - for (int i = 0; i < parents1.size(); i++) { - parent1 = parents1.get(i); - for (int j = 0; j < parents2.size(); j++) { - parent2 = parents2.get(j); - if (parent1 == parent2) { - return parent1; - } - } - } - - return null; - } - - /** - * Sets the node currently in focus - * - * @param node - * The node to focus or null to remove the focus completely - * @param scrollIntoView - * Scroll the node into view - */ - public void setFocusedNode(TreeNode node, boolean scrollIntoView) { - // Unfocus previously focused node - if (focusedNode != null) { - focusedNode.setFocused(false); - - Roles.getTreeRole().removeAriaActivedescendantProperty( - focusedNode.getElement()); - } - - if (node != null) { - node.setFocused(true); - Roles.getTreeitemRole().setAriaSelectedState(node.getElement(), - SelectedValue.TRUE); - - /* - * FIXME: This code needs to be changed when the keyboard navigation - * doesn't immediately trigger a selection change anymore. - * - * Right now this function is called before and after the Tree is - * rebuilt when up/down arrow keys are pressed. This leads to the - * problem, that the newly selected item is announced too often with - * a screen reader. - * - * Behaviour is different when using the Tree with and without - * screen reader. - */ - if (node.key.equals(lastNodeKey)) { - Roles.getTreeRole().setAriaActivedescendantProperty( - getFocusElement(), Id.of(node.getElement())); - } else { - lastNodeKey = node.key; - } - } - - focusedNode = node; - - if (node != null && scrollIntoView) { - /* - * Delay scrolling the focused node into view if we are still - * rendering. #5396 - */ - if (!rendering) { - node.scrollIntoView(); - } else { - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - focusedNode.scrollIntoView(); - } - }); - } - } - } - - /** - * Focuses a node and scrolls it into view - * - * @param node - * The node to focus - */ - public void setFocusedNode(TreeNode node) { - setFocusedNode(node, true); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event - * .dom.client.FocusEvent) - */ - @Override - public void onFocus(FocusEvent event) { - treeHasFocus = true; - // If no node has focus, focus the first item in the tree - if (focusedNode == null && lastSelection == null && selectable) { - setFocusedNode(getFirstRootNode(), false); - } else if (focusedNode != null && selectable) { - setFocusedNode(focusedNode, false); - } else if (lastSelection != null && selectable) { - setFocusedNode(lastSelection, false); - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event - * .dom.client.BlurEvent) - */ - @Override - public void onBlur(BlurEvent event) { - treeHasFocus = false; - if (focusedNode != null) { - focusedNode.setFocused(false); - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.KeyPressHandler#onKeyPress(com.google - * .gwt.event.dom.client.KeyPressEvent) - */ - @Override - public void onKeyPress(KeyPressEvent event) { - NativeEvent nativeEvent = event.getNativeEvent(); - int keyCode = nativeEvent.getKeyCode(); - if (keyCode == 0 && nativeEvent.getCharCode() == ' ') { - // Provide a keyCode for space to be compatible with FireFox - // keypress event - keyCode = CHARCODE_SPACE; - } - if (handleKeyNavigation(keyCode, - event.isControlKeyDown() || event.isMetaKeyDown(), - event.isShiftKeyDown())) { - event.preventDefault(); - event.stopPropagation(); - } - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt - * .event.dom.client.KeyDownEvent) - */ - @Override - public void onKeyDown(KeyDownEvent event) { - if (handleKeyNavigation(event.getNativeEvent().getKeyCode(), - event.isControlKeyDown() || event.isMetaKeyDown(), - event.isShiftKeyDown())) { - event.preventDefault(); - event.stopPropagation(); - } - } - - /** - * Handles the keyboard navigation - * - * @param keycode - * The keycode of the pressed key - * @param ctrl - * Was ctrl pressed - * @param shift - * Was shift pressed - * @return Returns true if the key was handled, else false - */ - protected boolean handleKeyNavigation(int keycode, boolean ctrl, - boolean shift) { - // Navigate down - if (keycode == getNavigationDownKey()) { - TreeNode node = null; - // If node is open and has children then move in to the children - if (!focusedNode.isLeaf() && focusedNode.getState() - && focusedNode.getChildren().size() > 0) { - node = focusedNode.getChildren().get(0); - } - - // Else move down to the next sibling - else { - node = getNextSibling(focusedNode); - if (node == null) { - // Else jump to the parent and try to select the next - // sibling there - TreeNode current = focusedNode; - while (node == null && current.getParentNode() != null) { - node = getNextSibling(current.getParentNode()); - current = current.getParentNode(); - } - } - } - - if (node != null) { - setFocusedNode(node); - if (selectable) { - if (!ctrl && !shift) { - selectNode(node, true); - } else if (shift && isMultiselect) { - deselectAll(); - selectNodeRange(lastSelection.key, node.key); - } else if (shift) { - selectNode(node, true); - } - } - showTooltipForKeyboardNavigation(node); - } - return true; - } - - // Navigate up - if (keycode == getNavigationUpKey()) { - TreeNode prev = getPreviousSibling(focusedNode); - TreeNode node = null; - if (prev != null) { - node = getLastVisibleChildInTree(prev); - } else if (focusedNode.getParentNode() != null) { - node = focusedNode.getParentNode(); - } - if (node != null) { - setFocusedNode(node); - if (selectable) { - if (!ctrl && !shift) { - selectNode(node, true); - } else if (shift && isMultiselect) { - deselectAll(); - selectNodeRange(lastSelection.key, node.key); - } else if (shift) { - selectNode(node, true); - } - } - showTooltipForKeyboardNavigation(node); - } - return true; - } - - // Navigate left (close branch) - if (keycode == getNavigationLeftKey()) { - if (!focusedNode.isLeaf() && focusedNode.getState()) { - focusedNode.setState(false, true); - } else if (focusedNode.getParentNode() != null - && (focusedNode.isLeaf() || !focusedNode.getState())) { - - if (ctrl || !selectable) { - setFocusedNode(focusedNode.getParentNode()); - } else if (shift) { - doRelationSelection(focusedNode.getParentNode(), - focusedNode); - setFocusedNode(focusedNode.getParentNode()); - } else { - focusAndSelectNode(focusedNode.getParentNode()); - } - } - showTooltipForKeyboardNavigation(focusedNode); - return true; - } - - // Navigate right (open branch) - if (keycode == getNavigationRightKey()) { - if (!focusedNode.isLeaf() && !focusedNode.getState()) { - focusedNode.setState(true, true); - } else if (!focusedNode.isLeaf()) { - if (ctrl || !selectable) { - setFocusedNode(focusedNode.getChildren().get(0)); - } else if (shift) { - setSelected(focusedNode, true); - setFocusedNode(focusedNode.getChildren().get(0)); - setSelected(focusedNode, true); - } else { - focusAndSelectNode(focusedNode.getChildren().get(0)); - } - } - showTooltipForKeyboardNavigation(focusedNode); - return true; - } - - // Selection - if (keycode == getNavigationSelectKey()) { - if (!focusedNode.isSelected()) { - selectNode(focusedNode, - (!isMultiselect - || multiSelectMode == MULTISELECT_MODE_SIMPLE) - && selectable); - } else { - deselectNode(focusedNode); - } - return true; - } - - // Home selection - if (keycode == getNavigationStartKey()) { - TreeNode node = getFirstRootNode(); - if (ctrl || !selectable) { - setFocusedNode(node); - } else if (shift) { - deselectAll(); - selectNodeRange(focusedNode.key, node.key); - } else { - selectNode(node, true); - } - sendSelectionToServer(); - showTooltipForKeyboardNavigation(node); - return true; - } - - // End selection - if (keycode == getNavigationEndKey()) { - TreeNode lastNode = getLastRootNode(); - TreeNode node = getLastVisibleChildInTree(lastNode); - if (ctrl || !selectable) { - setFocusedNode(node); - } else if (shift) { - deselectAll(); - selectNodeRange(focusedNode.key, node.key); - } else { - selectNode(node, true); - } - sendSelectionToServer(); - showTooltipForKeyboardNavigation(node); - return true; - } - - return false; - } - - private void showTooltipForKeyboardNavigation(TreeNode node) { - if (connector != null) { - getClient().getVTooltip().showAssistive( - connector.getTooltipInfo(node.nodeCaptionSpan)); - } - } - - private void focusAndSelectNode(TreeNode node) { - /* - * Keyboard navigation doesn't work reliably if the tree is in - * multiselect mode as well as isNullSelectionAllowed = false. It first - * tries to deselect the old focused node, which fails since there must - * be at least one selection. After this the newly focused node is - * selected and we've ended up with two selected nodes even though we - * only navigated with the arrow keys. - * - * Because of this, we first select the next node and later de-select - * the old one. - */ - TreeNode oldFocusedNode = focusedNode; - setFocusedNode(node); - setSelected(focusedNode, true); - setSelected(oldFocusedNode, false); - } - - /** - * Traverses the tree to the bottom most child - * - * @param root - * The root of the tree - * @return The bottom most child - */ - private TreeNode getLastVisibleChildInTree(TreeNode root) { - if (root.isLeaf() || !root.getState() - || root.getChildren().size() == 0) { - return root; - } - List<TreeNode> children = root.getChildren(); - return getLastVisibleChildInTree(children.get(children.size() - 1)); - } - - /** - * Gets the next sibling in the tree - * - * @param node - * The node to get the sibling for - * @return The sibling node or null if the node is the last sibling - */ - private TreeNode getNextSibling(TreeNode node) { - TreeNode parent = node.getParentNode(); - List<TreeNode> children; - if (parent == null) { - children = getRootNodes(); - } else { - children = parent.getChildren(); - } - - int idx = children.indexOf(node); - if (idx < children.size() - 1) { - return children.get(idx + 1); - } - - return null; - } - - /** - * Returns the previous sibling in the tree - * - * @param node - * The node to get the sibling for - * @return The sibling node or null if the node is the first sibling - */ - private TreeNode getPreviousSibling(TreeNode node) { - TreeNode parent = node.getParentNode(); - List<TreeNode> children; - if (parent == null) { - children = getRootNodes(); - } else { - children = parent.getChildren(); - } - - int idx = children.indexOf(node); - if (idx > 0) { - return children.get(idx - 1); - } - - return null; - } - - /** - * Add this to the element mouse down event by using element.setPropertyJSO - * ("onselectstart",applyDisableTextSelectionIEHack()); Remove it then again - * when the mouse is depressed in the mouse up event. - * - * @return Returns the JSO preventing text selection - */ - private native JavaScriptObject applyDisableTextSelectionIEHack() - /*-{ - return function(){ return false; }; - }-*/; - - /** - * Get the key that moves the selection head upwards. By default it is the - * up arrow key but by overriding this you can change the key to whatever - * you want. - * - * @return The keycode of the key - */ - protected int getNavigationUpKey() { - return KeyCodes.KEY_UP; - } - - /** - * Get the key that moves the selection head downwards. By default it is the - * down arrow key but by overriding this you can change the key to whatever - * you want. - * - * @return The keycode of the key - */ - protected int getNavigationDownKey() { - return KeyCodes.KEY_DOWN; - } - - /** - * Get the key that scrolls to the left in the table. By default it is the - * left arrow key but by overriding this you can change the key to whatever - * you want. - * - * @return The keycode of the key - */ - protected int getNavigationLeftKey() { - return KeyCodes.KEY_LEFT; - } - - /** - * Get the key that scroll to the right on the table. By default it is the - * right arrow key but by overriding this you can change the key to whatever - * you want. - * - * @return The keycode of the key - */ - protected int getNavigationRightKey() { - return KeyCodes.KEY_RIGHT; - } - - /** - * Get the key that selects an item in the table. By default it is the space - * bar key but by overriding this you can change the key to whatever you - * want. - * - * @return - */ - protected int getNavigationSelectKey() { - return CHARCODE_SPACE; - } - - /** - * Get the key the moves the selection one page up in the table. By default - * this is the Page Up key but by overriding this you can change the key to - * whatever you want. - * - * @return - */ - protected int getNavigationPageUpKey() { - return KeyCodes.KEY_PAGEUP; - } - - /** - * Get the key the moves the selection one page down in the table. By - * default this is the Page Down key but by overriding this you can change - * the key to whatever you want. - * - * @return - */ - protected int getNavigationPageDownKey() { - return KeyCodes.KEY_PAGEDOWN; - } - - /** - * Get the key the moves the selection to the beginning of the table. By - * default this is the Home key but by overriding this you can change the - * key to whatever you want. - * - * @return - */ - protected int getNavigationStartKey() { - return KeyCodes.KEY_HOME; - } - - /** - * Get the key the moves the selection to the end of the table. By default - * this is the End key but by overriding this you can change the key to - * whatever you want. - * - * @return - */ - protected int getNavigationEndKey() { - return KeyCodes.KEY_END; - } - - private final String SUBPART_NODE_PREFIX = "n"; - private final String EXPAND_IDENTIFIER = "expand"; - - /* - * In webkit, focus may have been requested for this component but not yet - * gained. Use this to trac if tree has gained the focus on webkit. See - * FocusImplSafari and #6373 - */ - private boolean treeHasFocus; - - /* - * (non-Javadoc) - * - * @see com.vaadin.client.ui.SubPartAware#getSubPartElement(java - * .lang.String) - */ - @Override - public com.google.gwt.user.client.Element getSubPartElement( - String subPart) { - if ("fe".equals(subPart)) { - if (BrowserInfo.get().isOpera() && focusedNode != null) { - return focusedNode.getElement(); - } - return getFocusElement(); - } - - if (subPart.startsWith(SUBPART_NODE_PREFIX + "[")) { - boolean expandCollapse = false; - - // Node - String[] nodes = subPart.split("/"); - TreeNode treeNode = null; - try { - for (String node : nodes) { - if (node.startsWith(SUBPART_NODE_PREFIX)) { - - // skip SUBPART_NODE_PREFIX"[" - node = node.substring(SUBPART_NODE_PREFIX.length() + 1); - // skip "]" - node = node.substring(0, node.length() - 1); - int position = Integer.parseInt(node); - if (treeNode == null) { - treeNode = getRootNodes().get(position); - } else { - treeNode = treeNode.getChildren().get(position); - } - } else if (node.startsWith(EXPAND_IDENTIFIER)) { - expandCollapse = true; - } - } - - if (expandCollapse) { - return treeNode.getElement(); - } else { - return DOM.asOld(treeNode.nodeCaptionSpan); - } - } catch (Exception e) { - // Invalid locator string or node could not be found - return null; - } - } - return null; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.client.ui.SubPartAware#getSubPartName(com.google - * .gwt.user.client.Element) - */ - @Override - public String getSubPartName( - com.google.gwt.user.client.Element subElement) { - // Supported identifiers: - // - // n[index]/n[index]/n[index]{/expand} - // - // Ends with "/expand" if the target is expand/collapse indicator, - // otherwise ends with the node - - boolean isExpandCollapse = false; - - if (!getElement().isOrHasChild(subElement)) { - return null; - } - - if (subElement == getFocusElement()) { - return "fe"; - } - - TreeNode treeNode = WidgetUtil.findWidget(subElement, TreeNode.class); - if (treeNode == null) { - // Did not click on a node, let somebody else take care of the - // locator string - return null; - } - - if (subElement == treeNode.getElement()) { - // Targets expand/collapse arrow - isExpandCollapse = true; - } - - ArrayList<Integer> positions = new ArrayList<Integer>(); - while (treeNode.getParentNode() != null) { - positions.add(0, - treeNode.getParentNode().getChildren().indexOf(treeNode)); - treeNode = treeNode.getParentNode(); - } - positions.add(0, getRootNodes().indexOf(treeNode)); - - String locator = ""; - for (Integer i : positions) { - locator += SUBPART_NODE_PREFIX + "[" + i + "]/"; - } - - locator = locator.substring(0, locator.length() - 1); - if (isExpandCollapse) { - locator += "/" + EXPAND_IDENTIFIER; - } - return locator; - } - - @Override - public Action[] getActions() { - if (bodyActionKeys == null) { - return new Action[] {}; - } - final Action[] actions = new Action[bodyActionKeys.length]; - for (int i = 0; i < actions.length; i++) { - final String actionKey = bodyActionKeys[i]; - final TreeAction a = new TreeAction(this, null, actionKey); - a.setCaption(getActionCaption(actionKey)); - a.setIconUrl(getActionIcon(actionKey)); - actions[i] = a; - } - return actions; - } - - @Override - public ApplicationConnection getClient() { - return client; - } - - @Override - public String getPaintableId() { - return paintableId; - } - - private void handleBodyContextMenu(ContextMenuEvent event) { - if (!readonly && !disabled) { - if (bodyActionKeys != null) { - int left = event.getNativeEvent().getClientX(); - int top = event.getNativeEvent().getClientY(); - top += Window.getScrollTop(); - left += Window.getScrollLeft(); - client.getContextMenu().showAt(this, left, top); - } - event.stopPropagation(); - event.preventDefault(); - } - } - - public void registerAction(String key, String caption, String iconUrl) { - actionMap.put(key + "_c", caption); - if (iconUrl != null) { - actionMap.put(key + "_i", iconUrl); - } else { - actionMap.remove(key + "_i"); - } - - } - - public void registerNode(TreeNode treeNode) { - keyToNode.put(treeNode.key, treeNode); - } - - public void clearNodeToKeyMap() { - keyToNode.clear(); - } - - @Override - public void bindAriaCaption( - com.google.gwt.user.client.Element captionElement) { - AriaHelper.bindCaption(body, captionElement); - } - - /** - * Tell LayoutManager that a layout is needed later for this VTree - */ - private void doLayout() { - // This calls LayoutManager setNeedsMeasure and layoutNow - Util.notifyParentOfSizeChange(this, false); - } -} - diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/CalendarConnector.java b/client/src/main/java/com/vaadin/client/ui/calendar/CalendarConnector.java deleted file mode 100644 index f97ba9d14a..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/CalendarConnector.java +++ /dev/null @@ -1,713 +0,0 @@ -/* - * Copyright 2000-2016 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.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; -import java.util.List; - -import com.google.gwt.core.shared.GWT; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.event.dom.client.ContextMenuEvent; -import com.google.gwt.i18n.client.DateTimeFormat; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.ApplicationConnection; -import com.vaadin.client.Paintable; -import com.vaadin.client.TooltipInfo; -import com.vaadin.client.UIDL; -import com.vaadin.client.VConsole; -import com.vaadin.client.WidgetUtil; -import com.vaadin.client.communication.RpcProxy; -import com.vaadin.client.communication.StateChangeEvent; -import com.vaadin.client.ui.AbstractComponentConnector; -import com.vaadin.client.ui.Action; -import com.vaadin.client.ui.ActionOwner; -import com.vaadin.client.ui.SimpleManagedLayout; -import com.vaadin.client.ui.VCalendar; -import com.vaadin.client.ui.VCalendar.BackwardListener; -import com.vaadin.client.ui.VCalendar.DateClickListener; -import com.vaadin.client.ui.VCalendar.EventClickListener; -import com.vaadin.client.ui.VCalendar.EventMovedListener; -import com.vaadin.client.ui.VCalendar.EventResizeListener; -import com.vaadin.client.ui.VCalendar.ForwardListener; -import com.vaadin.client.ui.VCalendar.MouseEventListener; -import com.vaadin.client.ui.VCalendar.RangeSelectListener; -import com.vaadin.client.ui.VCalendar.WeekClickListener; -import com.vaadin.client.ui.calendar.schedule.CalendarDay; -import com.vaadin.client.ui.calendar.schedule.CalendarEvent; -import com.vaadin.client.ui.calendar.schedule.DateCell; -import com.vaadin.client.ui.calendar.schedule.DateCell.DateCellSlot; -import com.vaadin.client.ui.calendar.schedule.DateCellDayEvent; -import com.vaadin.client.ui.calendar.schedule.DateUtil; -import com.vaadin.client.ui.calendar.schedule.HasTooltipKey; -import com.vaadin.client.ui.calendar.schedule.MonthEventLabel; -import com.vaadin.client.ui.calendar.schedule.SimpleDayCell; -import com.vaadin.client.ui.calendar.schedule.dd.CalendarDropHandler; -import com.vaadin.client.ui.calendar.schedule.dd.CalendarMonthDropHandler; -import com.vaadin.client.ui.calendar.schedule.dd.CalendarWeekDropHandler; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.shared.ui.calendar.CalendarClientRpc; -import com.vaadin.shared.ui.calendar.CalendarEventId; -import com.vaadin.shared.ui.calendar.CalendarServerRpc; -import com.vaadin.shared.ui.calendar.CalendarState; -import com.vaadin.shared.ui.calendar.DateConstants; -import com.vaadin.ui.Calendar; - -/** - * Handles communication between Calendar on the server side and - * {@link VCalendar} on the client side. - * - * @since 7.1 - * @author Vaadin Ltd. - */ -@Connect(value = Calendar.class, loadStyle = LoadStyle.LAZY) -public class CalendarConnector extends AbstractComponentConnector - implements ActionOwner, SimpleManagedLayout, Paintable { - - private CalendarServerRpc rpc = RpcProxy.create(CalendarServerRpc.class, - this); - - private final HashMap<String, String> actionMap = new HashMap<String, String>(); - private HashMap<Object, String> tooltips = new HashMap<Object, String>(); - - private static final String DROPHANDLER_ACCEPT_CRITERIA_PAINT_TAG = "-ac"; - - /** - * - */ - public CalendarConnector() { - - // Listen to events - registerListeners(); - } - - @Override - protected void init() { - super.init(); - registerRpc(CalendarClientRpc.class, new CalendarClientRpc() { - @Override - public void scroll(int scrollPosition) { - // TODO widget scroll - } - }); - getLayoutManager().registerDependency(this, getWidget().getElement()); - } - - @Override - public void onUnregister() { - super.onUnregister(); - getLayoutManager().unregisterDependency(this, getWidget().getElement()); - } - - @Override - public VCalendar getWidget() { - return (VCalendar) super.getWidget(); - } - - @Override - public CalendarState getState() { - return (CalendarState) super.getState(); - } - - /** - * Registers listeners on the calendar so server can be notified of the - * events - */ - protected void registerListeners() { - getWidget().setListener(new DateClickListener() { - @Override - public void dateClick(String date) { - if (!getWidget().isDisabled() - && hasEventListener(CalendarEventId.DATECLICK)) { - rpc.dateClick(date); - } - } - }); - getWidget().setListener(new ForwardListener() { - @Override - public void forward() { - if (hasEventListener(CalendarEventId.FORWARD)) { - rpc.forward(); - } - } - }); - getWidget().setListener(new BackwardListener() { - @Override - public void backward() { - if (hasEventListener(CalendarEventId.BACKWARD)) { - rpc.backward(); - } - } - }); - getWidget().setListener(new RangeSelectListener() { - @Override - public void rangeSelected(String value) { - if (hasEventListener(CalendarEventId.RANGESELECT)) { - rpc.rangeSelect(value); - } - } - }); - getWidget().setListener(new WeekClickListener() { - @Override - public void weekClick(String event) { - if (!getWidget().isDisabled() - && hasEventListener(CalendarEventId.WEEKCLICK)) { - rpc.weekClick(event); - } - } - }); - getWidget().setListener(new EventMovedListener() { - @Override - public void eventMoved(CalendarEvent event) { - if (hasEventListener(CalendarEventId.EVENTMOVE)) { - StringBuilder sb = new StringBuilder(); - sb.append(DateUtil.formatClientSideDate(event.getStart())); - sb.append("-"); - sb.append(DateUtil - .formatClientSideTime(event.getStartTime())); - rpc.eventMove(event.getIndex(), sb.toString()); - } - } - }); - getWidget().setListener(new EventResizeListener() { - @Override - public void eventResized(CalendarEvent event) { - if (hasEventListener(CalendarEventId.EVENTRESIZE)) { - StringBuilder buffer = new StringBuilder(); - - buffer.append( - DateUtil.formatClientSideDate(event.getStart())); - buffer.append("-"); - buffer.append(DateUtil - .formatClientSideTime(event.getStartTime())); - - String newStartDate = buffer.toString(); - - buffer = new StringBuilder(); - buffer.append( - DateUtil.formatClientSideDate(event.getEnd())); - buffer.append("-"); - buffer.append( - DateUtil.formatClientSideTime(event.getEndTime())); - - String newEndDate = buffer.toString(); - - rpc.eventResize(event.getIndex(), newStartDate, newEndDate); - } - } - }); - getWidget().setListener(new VCalendar.ScrollListener() { - @Override - public void scroll(int scrollPosition) { - // This call is @Delayed (== non-immediate) - rpc.scroll(scrollPosition); - } - }); - getWidget().setListener(new EventClickListener() { - @Override - public void eventClick(CalendarEvent event) { - if (hasEventListener(CalendarEventId.EVENTCLICK)) { - rpc.eventClick(event.getIndex()); - } - } - }); - getWidget().setListener(new MouseEventListener() { - @Override - public void contextMenu(ContextMenuEvent event, - final Widget widget) { - final NativeEvent ne = event.getNativeEvent(); - int left = ne.getClientX(); - int top = ne.getClientY(); - top += Window.getScrollTop(); - left += Window.getScrollLeft(); - getClient().getContextMenu().showAt(new ActionOwner() { - @Override - public String getPaintableId() { - return CalendarConnector.this.getPaintableId(); - } - - @Override - public ApplicationConnection getClient() { - return CalendarConnector.this.getClient(); - } - - @Override - @SuppressWarnings("deprecation") - public Action[] getActions() { - if (widget instanceof SimpleDayCell) { - /* - * Month view - */ - SimpleDayCell cell = (SimpleDayCell) widget; - Date start = new Date(cell.getDate().getYear(), - cell.getDate().getMonth(), - cell.getDate().getDate(), 0, 0, 0); - - Date end = new Date(cell.getDate().getYear(), - cell.getDate().getMonth(), - cell.getDate().getDate(), 23, 59, 59); - - 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 - */ - DateCell cell = (DateCell) widget; - int slotIndex = DOM.getChildIndex(cell.getElement(), - (Element) ne.getEventTarget().cast()); - DateCellSlot slot = cell.getSlot(slotIndex); - return CalendarConnector.this.getActionsBetween( - slot.getFrom(), slot.getTo()); - } else if (widget instanceof DateCellDayEvent) { - /* - * Context menu on event - */ - 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; - } - return null; - } - }, left, top); - } - }); - } - - private boolean showingMonthView() { - return getState().days.size() > 7; - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - CalendarState state = getState(); - VCalendar widget = getWidget(); - - // Enable or disable the forward and backward navigation buttons - widget.setForwardNavigationEnabled( - hasEventListener(CalendarEventId.FORWARD)); - widget.setBackwardNavigationEnabled( - hasEventListener(CalendarEventId.BACKWARD)); - - widget.set24HFormat(state.format24H); - widget.setDayNames(state.dayNames); - widget.setMonthNames(state.monthNames); - widget.setFirstDayNumber(state.firstVisibleDayOfWeek); - widget.setLastDayNumber(state.lastVisibleDayOfWeek); - widget.setFirstHourOfTheDay(state.firstHourOfDay); - widget.setLastHourOfTheDay(state.lastHourOfDay); - widget.setReadOnly(state.readOnly); - widget.setDisabled(!state.enabled); - - widget.setRangeSelectAllowed( - hasEventListener(CalendarEventId.RANGESELECT)); - widget.setRangeMoveAllowed(hasEventListener(CalendarEventId.EVENTMOVE)); - widget.setEventMoveAllowed(hasEventListener(CalendarEventId.EVENTMOVE)); - widget.setEventResizeAllowed( - hasEventListener(CalendarEventId.EVENTRESIZE)); - - widget.setEventCaptionAsHtml(state.eventCaptionAsHtml); - - 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)); - } - } - - updateSizes(); - - registerEventToolTips(state.events); - updateActionMap(state.actions); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin. - * terminal .gwt.client.UIDL, - * com.vaadin.terminal.gwt.client.ApplicationConnection) - */ - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - Iterator<Object> childIterator = uidl.getChildIterator(); - while (childIterator.hasNext()) { - UIDL child = (UIDL) childIterator.next(); - if (DROPHANDLER_ACCEPT_CRITERIA_PAINT_TAG.equals(child.getTag())) { - if (getWidget().getDropHandler() == null) { - getWidget().setDropHandler(showingMonthView() - ? new CalendarMonthDropHandler(this) - : new CalendarWeekDropHandler(this)); - } - getWidget().getDropHandler().updateAcceptRules(child); - } else { - getWidget().setDropHandler(null); - } - } - } - - /** - * Returns the ApplicationConnection used to connect to the server side - */ - @Override - public ApplicationConnection getClient() { - return getConnection(); - } - - /** - * Register the description of the events as tooltips. This way, any event - * displaying widget can use the event index as a key to display the - * tooltip. - */ - private void registerEventToolTips(List<CalendarState.Event> events) { - for (CalendarState.Event e : events) { - if (e.description != null && !"".equals(e.description)) { - tooltips.put(e.index, e.description); - } else { - tooltips.remove(e.index); - } - } - } - - @Override - public TooltipInfo getTooltipInfo( - com.google.gwt.dom.client.Element element) { - TooltipInfo tooltipInfo = null; - Widget w = WidgetUtil.findWidget(element, null); - if (w instanceof HasTooltipKey) { - tooltipInfo = GWT.create(TooltipInfo.class); - String title = tooltips.get(((HasTooltipKey) w).getTooltipKey()); - tooltipInfo.setTitle(title != null ? title : ""); - } - if (tooltipInfo == null) { - tooltipInfo = super.getTooltipInfo(element); - } - return tooltipInfo; - } - - @Override - public boolean hasTooltip() { - /* - * Tooltips are not processed until updateFromUIDL, so we can't be sure - * that there are no tooltips during onStateChange when this is used. - */ - return true; - } - - private void updateMonthView(List<CalendarState.Day> days, - List<CalendarState.Event> events) { - CalendarState state = getState(); - getWidget().updateMonthView(state.firstDayOfWeek, - getWidget().getDateTimeFormat().parse(state.now), days.size(), - calendarEventListOf(events, state.format24H), - calendarDayListOf(days)); - } - - private void updateWeekView(List<CalendarState.Day> days, - List<CalendarState.Event> events) { - CalendarState state = getState(); - getWidget().updateWeekView(state.scroll, - getWidget().getDateTimeFormat().parse(state.now), days.size(), - state.firstDayOfWeek, - calendarEventListOf(events, state.format24H), - calendarDayListOf(days)); - } - - 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++) { - 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; - } - - // 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); - } - } - } - - return actions.toArray(new Action[actions.size()]); - } - - private List<String> actionKeys = new ArrayList<String>(); - - private void updateActionMap(List<CalendarState.Action> actions) { - actionMap.clear(); - actionKeys.clear(); - - if (actions == null) { - return; - } - - 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); - actionKeys.add(id); - if (action.iconKey != null) { - actionMap.put(id + "_i", getResourceUrl(action.iconKey)); - - } else { - 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"); - } - - /** - * Get the text that is displayed for a context menu item - * - * @param actionKey - * The unique action key - * @return - */ - public String getActionCaption(String actionKey) { - return actionMap.get(actionKey + "_c"); - } - - /** - * Get the icon url for a context menu item - * - * @param actionKey - * The unique action key - * @return - */ - public String getActionIcon(String actionKey) { - return actionMap.get(actionKey + "_i"); - } - - /** - * Get the start date for an action item - * - * @param actionKey - * The unique action key - * @return - * @throws ParseException - */ - public Date getActionStartDate(String actionKey) throws ParseException { - String dateStr = actionMap.get(actionKey + "_s"); - DateTimeFormat formatter = DateTimeFormat - .getFormat(DateConstants.ACTION_DATE_FORMAT_PATTERN); - return formatter.parse(dateStr); - } - - /** - * Get the end date for an action item - * - * @param actionKey - * The unique action key - * @return - * @throws ParseException - */ - public Date getActionEndDate(String actionKey) throws ParseException { - String dateStr = actionMap.get(actionKey + "_e"); - DateTimeFormat formatter = DateTimeFormat - .getFormat(DateConstants.ACTION_DATE_FORMAT_PATTERN); - return formatter.parse(dateStr); - } - - /** - * Returns ALL currently registered events. Use {@link #getActions(Date)} to - * get the actions for a specific date - */ - @Override - public Action[] getActions() { - List<Action> actions = new ArrayList<Action>(); - for (int i = 0; i < actionKeys.size(); i++) { - final String actionKey = actionKeys.get(i); - final VCalendarAction a = new VCalendarAction(this, rpc, actionKey); - a.setCaption(getActionCaption(actionKey)); - a.setIconUrl(getActionIcon(actionKey)); - - try { - a.setActionStartDate(getActionStartDate(actionKey)); - a.setActionEndDate(getActionEndDate(actionKey)); - } catch (ParseException pe) { - VConsole.error(pe); - } - - actions.add(a); - } - return actions.toArray(new Action[actions.size()]); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.ui.ActionOwner#getPaintableId() - */ - @Override - public String getPaintableId() { - return getConnectorId(); - } - - private List<CalendarEvent> calendarEventListOf( - List<CalendarState.Event> events, boolean format24h) { - List<CalendarEvent> list = new ArrayList<CalendarEvent>(events.size()); - for (CalendarState.Event event : events) { - final String dateFrom = event.dateFrom; - final String dateTo = event.dateTo; - final String timeFrom = event.timeFrom; - final String timeTo = event.timeTo; - CalendarEvent calendarEvent = new CalendarEvent(); - calendarEvent.setAllDay(event.allDay); - calendarEvent.setCaption(event.caption); - calendarEvent.setDescription(event.description); - calendarEvent.setStart(getWidget().getDateFormat().parse(dateFrom)); - calendarEvent.setEnd(getWidget().getDateFormat().parse(dateTo)); - calendarEvent.setFormat24h(format24h); - calendarEvent.setStartTime(getWidget().getDateTimeFormat() - .parse(dateFrom + " " + timeFrom)); - calendarEvent.setEndTime(getWidget().getDateTimeFormat() - .parse(dateTo + " " + timeTo)); - calendarEvent.setStyleName(event.styleName); - calendarEvent.setIndex(event.index); - list.add(calendarEvent); - } - return list; - } - - private List<CalendarDay> calendarDayListOf(List<CalendarState.Day> days) { - List<CalendarDay> list = new ArrayList<CalendarDay>(days.size()); - for (CalendarState.Day day : days) { - CalendarDay d = new CalendarDay(day.date, day.localizedDateFormat, - day.dayOfWeek, day.week, day.yearOfWeek); - - list.add(d); - } - return list; - } - - @Override - public void layout() { - updateSizes(); - } - - private void updateSizes() { - int height = getLayoutManager() - .getOuterHeight(getWidget().getElement()); - int width = getLayoutManager().getOuterWidth(getWidget().getElement()); - - if (isUndefinedWidth()) { - width = -1; - } - if (isUndefinedHeight()) { - height = -1; - } - - getWidget().setSizeForChildren(width, height); - - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/VCalendarAction.java b/client/src/main/java/com/vaadin/client/ui/calendar/VCalendarAction.java deleted file mode 100644 index f16a43fbb2..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/VCalendarAction.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar; - -import java.util.Date; - -import com.google.gwt.i18n.client.DateTimeFormat; -import com.vaadin.client.ui.Action; -import com.vaadin.client.ui.calendar.schedule.CalendarEvent; -import com.vaadin.shared.ui.calendar.CalendarServerRpc; -import com.vaadin.shared.ui.calendar.DateConstants; - -/** - * Action performed by the calendar - * - * @since 7.1 - * @author Vaadin Ltd. - */ -public class VCalendarAction extends Action { - - private CalendarServerRpc rpc; - - private String actionKey = ""; - - private Date actionStartDate; - - private Date actionEndDate; - - private CalendarEvent event; - - private final DateTimeFormat dateformat_datetime = DateTimeFormat - .getFormat(DateConstants.ACTION_DATE_FORMAT_PATTERN); - - /** - * - * @param owner - */ - public VCalendarAction(CalendarConnector owner) { - super(owner); - } - - /** - * Constructor - * - * @param owner - * The owner who trigger this kinds of events - * @param rpc - * The CalendarRpc which is used for executing actions - * @param key - * The unique action key which identifies this particular action - */ - public VCalendarAction(CalendarConnector owner, CalendarServerRpc rpc, - String key) { - this(owner); - this.rpc = rpc; - actionKey = key; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.ui.Action#execute() - */ - @Override - public void execute() { - String startDate = dateformat_datetime.format(actionStartDate); - String endDate = dateformat_datetime.format(actionEndDate); - - if (event == null) { - rpc.actionOnEmptyCell(actionKey.split("-")[0], startDate, endDate); - } else { - rpc.actionOnEvent(actionKey.split("-")[0], startDate, endDate, - event.getIndex()); - } - - owner.getClient().getContextMenu().hide(); - } - - /** - * Get the date and time when the action starts - * - * @return - */ - public Date getActionStartDate() { - return actionStartDate; - } - - /** - * Set the date when the actions start - * - * @param actionStartDate - * The date and time when the action starts - */ - public void setActionStartDate(Date actionStartDate) { - this.actionStartDate = actionStartDate; - } - - /** - * Get the date and time when the action ends - * - * @return - */ - public Date getActionEndDate() { - return actionEndDate; - } - - /** - * Set the date and time when the action ends - * - * @param actionEndDate - * The date and time when the action ends - */ - public void setActionEndDate(Date actionEndDate) { - this.actionEndDate = actionEndDate; - } - - public CalendarEvent getEvent() { - return event; - } - - public void setEvent(CalendarEvent event) { - this.event = event; - } - -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/CalendarDay.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/CalendarDay.java deleted file mode 100644 index c2ade39a6d..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/CalendarDay.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -/** - * Utility class used to represent a day when updating views. Only used - * internally. - * - * @since 7.1 - * @author Vaadin Ltd. - */ -public class CalendarDay { - private String date; - private String localizedDateFormat; - private int dayOfWeek; - private int week; - private int yearOfWeek; - - public CalendarDay(String date, String localizedDateFormat, int dayOfWeek, - int week, int yearOfWeek) { - super(); - this.date = date; - this.localizedDateFormat = localizedDateFormat; - this.dayOfWeek = dayOfWeek; - this.week = week; - this.yearOfWeek = yearOfWeek; - } - - public String getDate() { - return date; - } - - public String getLocalizedDateFormat() { - return localizedDateFormat; - } - - public int getDayOfWeek() { - return dayOfWeek; - } - - public int getWeek() { - return week; - } - - public int getYearOfWeek() { - return yearOfWeek; - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/CalendarEvent.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/CalendarEvent.java deleted file mode 100644 index 937b7c0ccb..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/CalendarEvent.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import java.util.Date; - -import com.google.gwt.i18n.client.DateTimeFormat; -import com.vaadin.shared.ui.calendar.DateConstants; - -/** - * A client side implementation of a calendar event - * - * @since 7.1 - * @author Vaadin Ltd. - */ -public class CalendarEvent { - private int index; - private String caption; - private Date start, end; - private String styleName; - private Date startTime, endTime; - private String description; - private int slotIndex = -1; - private boolean format24h; - - DateTimeFormat dateformat_date = DateTimeFormat.getFormat("h:mm a"); - DateTimeFormat dateformat_date24 = DateTimeFormat.getFormat("H:mm"); - private boolean allDay; - - /** - * @see com.vaadin.addon.calendar.event.CalendarEvent#getStyleName() - */ - public String getStyleName() { - return styleName; - } - - /** - * @see com.vaadin.addon.calendar.event.CalendarEvent#getStart() - */ - public Date getStart() { - return start; - } - - /** - * @see com.vaadin.addon.calendar.event.CalendarEvent#getStyleName() - * @param style - */ - public void setStyleName(String style) { - styleName = style; - } - - /** - * @see com.vaadin.addon.calendar.event.CalendarEvent#getStart() - * @param start - */ - public void setStart(Date start) { - this.start = start; - } - - /** - * @see com.vaadin.addon.calendar.event.CalendarEvent#getEnd() - * @return - */ - public Date getEnd() { - return end; - } - - /** - * @see com.vaadin.addon.calendar.event.CalendarEvent#getEnd() - * @param end - */ - public void setEnd(Date end) { - this.end = end; - } - - /** - * Returns the start time of the event - * - * @return Time embedded in the {@link Date} object - */ - public Date getStartTime() { - return startTime; - } - - /** - * Set the start time of the event - * - * @param startTime - * The time of the event. Use the time fields in the {@link Date} - * object - */ - public void setStartTime(Date startTime) { - this.startTime = startTime; - } - - /** - * Get the end time of the event - * - * @return Time embedded in the {@link Date} object - */ - public Date getEndTime() { - return endTime; - } - - /** - * Set the end time of the event - * - * @param endTime - * Time embedded in the {@link Date} object - */ - public void setEndTime(Date endTime) { - this.endTime = endTime; - } - - /** - * Get the (server side) index of the event - * - * @return - */ - public int getIndex() { - return index; - } - - /** - * Get the index of the slot where the event in rendered - * - * @return - */ - public int getSlotIndex() { - return slotIndex; - } - - /** - * Set the index of the slot where the event in rendered - * - * @param index - * The index of the slot - */ - public void setSlotIndex(int index) { - slotIndex = index; - } - - /** - * Set the (server side) index of the event - * - * @param index - * The index - */ - public void setIndex(int index) { - this.index = index; - } - - /** - * Get the caption of the event. The caption is the text displayed in the - * calendar on the event. - * - * @return - */ - public String getCaption() { - return caption; - } - - /** - * Set the caption of the event. The caption is the text displayed in the - * calendar on the event. - * - * @param caption - * The visible caption of the event - */ - public void setCaption(String caption) { - this.caption = caption; - } - - /** - * Get the description of the event. The description is the text displayed - * when hoovering over the event with the mouse - * - * @return - */ - public String getDescription() { - return description; - } - - /** - * Set the description of the event. The description is the text displayed - * when hoovering over the event with the mouse - * - * @param description - */ - public void setDescription(String description) { - this.description = description; - } - - /** - * Does the event use the 24h time format - * - * @param format24h - * True if it uses the 24h format, false if it uses the 12h time - * format - */ - public void setFormat24h(boolean format24h) { - this.format24h = format24h; - } - - /** - * Is the event an all day event. - * - * @param allDay - * True if the event should be rendered all day - */ - public void setAllDay(boolean allDay) { - this.allDay = allDay; - } - - /** - * Is the event an all day event. - * - * @return - */ - public boolean isAllDay() { - return allDay; - } - - /** - * Get the time as a formatted string - * - * @return - */ - public String getTimeAsText() { - if (format24h) { - return dateformat_date24.format(startTime); - } else { - return dateformat_date.format(startTime); - } - } - - /** - * Get the amount of milliseconds between the start and end of the event - * - * @return - */ - public long getRangeInMilliseconds() { - return getEndTime().getTime() - getStartTime().getTime(); - } - - /** - * Get the amount of minutes between the start and end of the event - * - * @return - */ - public long getRangeInMinutes() { - return (getRangeInMilliseconds() / DateConstants.MINUTEINMILLIS); - } - - /** - * Get the amount of minutes for the event on a specific day. This is useful - * if the event spans several days. - * - * @param targetDay - * The date to check - * @return - */ - public long getRangeInMinutesForDay(Date targetDay) { - long rangeInMinutesForDay = 0; - // we must take into account that here can be not only 1 and 2 days, but - // 1, 2, 3, 4... days first and last days - special cases all another - // days between first and last - have range "ALL DAY" - if (isTimeOnDifferentDays()) { - if (targetDay.compareTo(getStart()) == 0) { // for first day - rangeInMinutesForDay = DateConstants.DAYINMINUTES - - (getStartTime().getTime() - getStart().getTime()) - / DateConstants.MINUTEINMILLIS; - } else if (targetDay.compareTo(getEnd()) == 0) { // for last day - rangeInMinutesForDay = (getEndTime().getTime() - - getEnd().getTime()) / DateConstants.MINUTEINMILLIS; - } else { // for in-between days - rangeInMinutesForDay = DateConstants.DAYINMINUTES; - } - } else { // simple case - period is in one day - rangeInMinutesForDay = getRangeInMinutes(); - } - return rangeInMinutesForDay; - } - - /** - * Does the event span several days - * - * @return - */ - @SuppressWarnings("deprecation") - public boolean isTimeOnDifferentDays() { - boolean isSeveralDays = false; - - // if difference between start and end times is more than day - of - // course it is not one day, but several days - if (getEndTime().getTime() - - getStartTime().getTime() > DateConstants.DAYINMILLIS) { - isSeveralDays = true; - } else { // if difference <= day -> there can be different cases - if (getStart().compareTo(getEnd()) != 0 - && getEndTime().compareTo(getEnd()) != 0) { - isSeveralDays = true; - } - } - return isSeveralDays; - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DateCell.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DateCell.java deleted file mode 100644 index 2590c4ed03..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DateCell.java +++ /dev/null @@ -1,850 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.dom.client.Node; -import com.google.gwt.dom.client.NodeList; -import com.google.gwt.dom.client.Style.Display; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.event.dom.client.ContextMenuEvent; -import com.google.gwt.event.dom.client.ContextMenuHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.MouseDownEvent; -import com.google.gwt.event.dom.client.MouseDownHandler; -import com.google.gwt.event.dom.client.MouseMoveEvent; -import com.google.gwt.event.dom.client.MouseMoveHandler; -import com.google.gwt.event.dom.client.MouseUpEvent; -import com.google.gwt.event.dom.client.MouseUpHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.WidgetUtil; - -public class DateCell extends FocusableComplexPanel implements MouseDownHandler, - MouseMoveHandler, MouseUpHandler, KeyDownHandler, ContextMenuHandler { - private static final String DRAGEMPHASISSTYLE = " dragemphasis"; - private Date date; - private int width; - private int eventRangeStart = -1; - private int eventRangeStop = -1; - final WeekGrid weekgrid; - private boolean disabled = false; - private int height; - private final Element[] slotElements; - private final List<DateCellSlot> slots = new ArrayList<DateCell.DateCellSlot>(); - private int[] slotElementHeights; - private int startingSlotHeight; - private Date today; - private Element todaybar; - private final List<HandlerRegistration> handlers; - private final int numberOfSlots; - private final int firstHour; - private final int lastHour; - - public class DateCellSlot extends Widget { - - private final DateCell cell; - - private final Date from; - - private final Date to; - - public DateCellSlot(DateCell cell, Date from, Date to) { - setElement(DOM.createDiv()); - getElement().setInnerHTML(" "); - this.cell = cell; - this.from = from; - this.to = to; - } - - public Date getFrom() { - return from; - } - - public Date getTo() { - return to; - } - - public DateCell getParentCell() { - return cell; - } - } - - public DateCell(WeekGrid parent, Date date) { - weekgrid = parent; - Element mainElement = DOM.createDiv(); - setElement(mainElement); - makeFocusable(); - setDate(date); - - addStyleName("v-calendar-day-times"); - - handlers = new LinkedList<HandlerRegistration>(); - - // 2 slots / hour - firstHour = weekgrid.getFirstHour(); - lastHour = weekgrid.getLastHour(); - numberOfSlots = (lastHour - firstHour + 1) * 2; - long slotTime = Math.round( - ((lastHour - firstHour + 1) * 3600000.0) / numberOfSlots); - - slotElements = new Element[numberOfSlots]; - slotElementHeights = new int[numberOfSlots]; - - slots.clear(); - long start = getDate().getTime() + firstHour * 3600000; - long end = start + slotTime; - for (int i = 0; i < numberOfSlots; i++) { - DateCellSlot slot = new DateCellSlot(this, new Date(start), - new Date(end)); - if (i % 2 == 0) { - slot.setStyleName("v-datecellslot-even"); - } else { - slot.setStyleName("v-datecellslot"); - } - Event.sinkEvents(slot.getElement(), Event.MOUSEEVENTS); - mainElement.appendChild(slot.getElement()); - slotElements[i] = slot.getElement(); - slots.add(slot); - start = end; - end = start + slotTime; - } - - // Sink events for tooltip handling - Event.sinkEvents(mainElement, Event.MOUSEEVENTS); - } - - public int getFirstHour() { - return firstHour; - } - - public int getLastHour() { - return lastHour; - } - - @Override - protected void onAttach() { - super.onAttach(); - - handlers.add(addHandler(this, MouseDownEvent.getType())); - handlers.add(addHandler(this, MouseUpEvent.getType())); - handlers.add(addHandler(this, MouseMoveEvent.getType())); - handlers.add(addDomHandler(this, ContextMenuEvent.getType())); - handlers.add(addKeyDownHandler(this)); - } - - @Override - protected void onDetach() { - for (HandlerRegistration handler : handlers) { - handler.removeHandler(); - } - handlers.clear(); - - super.onDetach(); - } - - public int getSlotIndex(Element slotElement) { - for (int i = 0; i < slotElements.length; i++) { - if (slotElement == slotElements[i]) { - return i; - } - } - - throw new IllegalArgumentException( - "Element not found in this DateCell"); - } - - public DateCellSlot getSlot(int index) { - return slots.get(index); - } - - public int getNumberOfSlots() { - return numberOfSlots; - } - - public void setTimeBarWidth(int timebarWidth) { - todaybar.getStyle().setWidth(timebarWidth, Unit.PX); - } - - /** - * @param isHorizontalSized - * if true, this DateCell is sized with CSS and not via - * {@link #setWidthPX(int)} - */ - public void setHorizontalSized(boolean isHorizontalSized) { - if (isHorizontalSized) { - addStyleDependentName("Hsized"); - - width = getOffsetWidth() - - WidgetUtil.measureHorizontalBorder(getElement()); - // Update moveWidth for any DateCellDayEvent child - updateEventCellsWidth(); - recalculateEventWidths(); - } else { - removeStyleDependentName("Hsized"); - } - } - - /** - * @param isVerticalSized - * if true, this DateCell is sized with CSS and not via - * {@link #setHeightPX(int)} - */ - public void setVerticalSized(boolean isVerticalSized) { - if (isVerticalSized) { - addStyleDependentName("Vsized"); - - // recalc heights&size for events. all other height sizes come - // from css - startingSlotHeight = slotElements[0].getOffsetHeight(); - // Update slotHeight for each DateCellDayEvent child - updateEventCellsHeight(); - recalculateEventPositions(); - - if (isToday()) { - recalculateTimeBarPosition(); - } - - } else { - removeStyleDependentName("Vsized"); - } - } - - public void setDate(Date date) { - this.date = date; - } - - public void setWidthPX(int cellWidth) { - width = cellWidth; - setWidth(cellWidth + "px"); - recalculateEventWidths(); - } - - public void setHeightPX(int height, int[] cellHeights) { - this.height = height; - slotElementHeights = cellHeights; - setHeight(height + "px"); - recalculateCellHeights(); - recalculateEventPositions(); - if (today != null) { - recalculateTimeBarPosition(); - } - } - - // date methods are not deprecated in GWT - @SuppressWarnings("deprecation") - private void recalculateTimeBarPosition() { - int h = today.getHours(); - int m = today.getMinutes(); - if (h >= firstHour && h <= lastHour) { - int pixelTop = weekgrid.getPixelTopFor(m + 60 * h); - todaybar.getStyle().clearDisplay(); - todaybar.getStyle().setTop(pixelTop, Unit.PX); - } else { - todaybar.getStyle().setDisplay(Display.NONE); - } - } - - private void recalculateEventPositions() { - for (int i = 0; i < getWidgetCount(); i++) { - DateCellDayEvent dayEvent = (DateCellDayEvent) getWidget(i); - updatePositionFor(dayEvent, getDate(), dayEvent.getCalendarEvent()); - } - } - - public void recalculateEventWidths() { - List<DateCellGroup> groups = new ArrayList<DateCellGroup>(); - - int count = getWidgetCount(); - - List<Integer> handled = new ArrayList<Integer>(); - - // Iterate through all events and group them. Events that overlaps - // with each other, are added to the same group. - for (int i = 0; i < count; i++) { - if (handled.contains(i)) { - continue; - } - - DateCellGroup curGroup = getOverlappingEvents(i); - handled.addAll(curGroup.getItems()); - - boolean newGroup = true; - // No need to check other groups, if size equals the count - if (curGroup.getItems().size() != count) { - // Check other groups. When the whole group overlaps with - // other group, the group is merged to the other. - for (DateCellGroup g : groups) { - - if (WeekGridMinuteTimeRange.doesOverlap( - curGroup.getDateRange(), g.getDateRange())) { - newGroup = false; - updateGroup(g, curGroup); - } - } - } else { - if (newGroup) { - groups.add(curGroup); - } - break; - } - - if (newGroup) { - groups.add(curGroup); - } - } - - drawDayEvents(groups); - } - - private void recalculateCellHeights() { - startingSlotHeight = height / numberOfSlots; - - for (int i = 0; i < slotElements.length; i++) { - slotElements[i].getStyle().setHeight(slotElementHeights[i], - Unit.PX); - } - - updateEventCellsHeight(); - } - - public int getSlotHeight() { - return startingSlotHeight; - } - - public int getSlotBorder() { - return WidgetUtil.measureVerticalBorder(slotElements[0]); - } - - private void drawDayEvents(List<DateCellGroup> groups) { - for (DateCellGroup g : groups) { - int col = 0; - int colCount = 0; - List<Integer> order = new ArrayList<Integer>(); - Map<Integer, Integer> columns = new HashMap<Integer, Integer>(); - for (Integer eventIndex : g.getItems()) { - DateCellDayEvent d = (DateCellDayEvent) getWidget(eventIndex); - d.setMoveWidth(width); - - int freeSpaceCol = findFreeColumnSpaceOnLeft( - new WeekGridMinuteTimeRange( - d.getCalendarEvent().getStartTime(), - d.getCalendarEvent().getEndTime()), - order, columns); - if (freeSpaceCol >= 0) { - col = freeSpaceCol; - columns.put(eventIndex, col); - int newOrderindex = 0; - for (Integer i : order) { - if (columns.get(i) >= col) { - newOrderindex = order.indexOf(i); - break; - } - } - order.add(newOrderindex, eventIndex); - } else { - // New column - col = colCount++; - columns.put(eventIndex, col); - order.add(eventIndex); - } - } - - // Update widths and left position - int eventWidth = (width / colCount); - for (Integer index : g.getItems()) { - DateCellDayEvent d = (DateCellDayEvent) getWidget(index); - d.getElement().getStyle().setMarginLeft( - (eventWidth * columns.get(index)), Unit.PX); - d.setWidth(eventWidth + "px"); - d.setSlotHeightInPX(getSlotHeight()); - } - } - } - - private int findFreeColumnSpaceOnLeft(WeekGridMinuteTimeRange dateRange, - List<Integer> order, Map<Integer, Integer> columns) { - int freeSpot = -1; - int skipIndex = -1; - for (Integer eventIndex : order) { - int col = columns.get(eventIndex); - if (col == skipIndex) { - continue; - } - - if (freeSpot != -1 && freeSpot != col) { - // Free spot found - return freeSpot; - } - - DateCellDayEvent d = (DateCellDayEvent) getWidget(eventIndex); - WeekGridMinuteTimeRange nextRange = new WeekGridMinuteTimeRange( - d.getCalendarEvent().getStartTime(), - d.getCalendarEvent().getEndTime()); - - if (WeekGridMinuteTimeRange.doesOverlap(dateRange, nextRange)) { - skipIndex = col; - freeSpot = -1; - } else { - freeSpot = col; - } - } - - return freeSpot; - } - - /* Update top and bottom date range values. Add new index to the group. */ - private void updateGroup(DateCellGroup targetGroup, DateCellGroup byGroup) { - Date newStart = targetGroup.getStart(); - Date newEnd = targetGroup.getEnd(); - if (byGroup.getStart().before(targetGroup.getStart())) { - newStart = byGroup.getEnd(); - } - if (byGroup.getStart().after(targetGroup.getEnd())) { - newStart = byGroup.getStart(); - } - - targetGroup.setDateRange(new WeekGridMinuteTimeRange(newStart, newEnd)); - - for (Integer index : byGroup.getItems()) { - if (!targetGroup.getItems().contains(index)) { - targetGroup.add(index); - } - } - } - - /** - * Returns all overlapping DayEvent indexes in the Group. Including the - * target. - * - * @param targetIndex - * Index of DayEvent in the current DateCell widget. - * @return Group that contains all Overlapping DayEvent indexes - */ - public DateCellGroup getOverlappingEvents(int targetIndex) { - DateCellGroup g = new DateCellGroup(targetIndex); - - int count = getWidgetCount(); - DateCellDayEvent target = (DateCellDayEvent) getWidget(targetIndex); - WeekGridMinuteTimeRange targetRange = new WeekGridMinuteTimeRange( - target.getCalendarEvent().getStartTime(), - target.getCalendarEvent().getEndTime()); - Date groupStart = targetRange.getStart(); - Date groupEnd = targetRange.getEnd(); - - for (int i = 0; i < count; i++) { - if (targetIndex == i) { - continue; - } - - DateCellDayEvent d = (DateCellDayEvent) getWidget(i); - WeekGridMinuteTimeRange nextRange = new WeekGridMinuteTimeRange( - d.getCalendarEvent().getStartTime(), - d.getCalendarEvent().getEndTime()); - if (WeekGridMinuteTimeRange.doesOverlap(targetRange, nextRange)) { - g.add(i); - - // Update top & bottom values to the greatest - if (nextRange.getStart().before(targetRange.getStart())) { - groupStart = targetRange.getStart(); - } - if (nextRange.getEnd().after(targetRange.getEnd())) { - groupEnd = targetRange.getEnd(); - } - } - } - - g.setDateRange(new WeekGridMinuteTimeRange(groupStart, groupEnd)); - return g; - } - - public Date getDate() { - return date; - } - - public void addEvent(Date targetDay, CalendarEvent calendarEvent) { - Element main = getElement(); - DateCellDayEvent dayEvent = new DateCellDayEvent(this, weekgrid, - calendarEvent); - dayEvent.setSlotHeightInPX(getSlotHeight()); - dayEvent.setDisabled(isDisabled()); - - if (startingSlotHeight > 0) { - updatePositionFor(dayEvent, targetDay, calendarEvent); - } - - add(dayEvent, main); - } - - // date methods are not deprecated in GWT - @SuppressWarnings("deprecation") - private void updatePositionFor(DateCellDayEvent dayEvent, Date targetDay, - CalendarEvent calendarEvent) { - - if (shouldDisplay(calendarEvent)) { - dayEvent.getElement().getStyle().clearDisplay(); - - Date fromDt = calendarEvent.getStartTime(); - int h = fromDt.getHours(); - int m = fromDt.getMinutes(); - long range = calendarEvent.getRangeInMinutesForDay(targetDay); - - boolean onDifferentDays = calendarEvent.isTimeOnDifferentDays(); - if (onDifferentDays) { - if (calendarEvent.getStart().compareTo(targetDay) != 0) { - // Current day slot is for the end date and all in-between - // days. Lets fix also the start & end times. - h = 0; - m = 0; - } - } - - int startFromMinutes = (h * 60) + m; - dayEvent.updatePosition(startFromMinutes, range); - } else { - dayEvent.getElement().getStyle().setDisplay(Display.NONE); - } - } - - public void addEvent(DateCellDayEvent dayEvent) { - Element main = getElement(); - int index = 0; - List<CalendarEvent> events = new ArrayList<CalendarEvent>(); - - // events are the only widgets in this panel - // slots are just elements - for (; index < getWidgetCount(); index++) { - DateCellDayEvent dc = (DateCellDayEvent) getWidget(index); - dc.setDisabled(isDisabled()); - events.add(dc.getCalendarEvent()); - } - events.add(dayEvent.getCalendarEvent()); - - index = 0; - for (CalendarEvent e : weekgrid.getCalendar() - .sortEventsByDuration(events)) { - if (e.equals(dayEvent.getCalendarEvent())) { - break; - } - index++; - } - this.insert(dayEvent, main, index, true); - } - - public void removeEvent(DateCellDayEvent dayEvent) { - remove(dayEvent); - } - - /** - * - * @param event - * @return - * - * This method is not necessary in the long run.. Or here can be - * various types of implementations.. - */ - // Date methods not deprecated in GWT - @SuppressWarnings("deprecation") - private boolean shouldDisplay(CalendarEvent event) { - boolean display = true; - if (event.isTimeOnDifferentDays()) { - display = true; - } else { // only in case of one-day event we are able not to display - // event - // which is placed in unpublished parts on calendar - Date eventStart = event.getStartTime(); - Date eventEnd = event.getEndTime(); - - int eventStartHours = eventStart.getHours(); - int eventEndHours = eventEnd.getHours(); - - display = !(eventEndHours < firstHour - || eventStartHours > lastHour); - } - return display; - } - - @Override - public void onKeyDown(KeyDownEvent event) { - int keycode = event.getNativeEvent().getKeyCode(); - if (keycode == KeyCodes.KEY_ESCAPE && eventRangeStart > -1) { - cancelRangeSelect(); - } - } - - @Override - public void onMouseDown(MouseDownEvent event) { - if (event.getNativeButton() == NativeEvent.BUTTON_LEFT) { - Element e = Element.as(event.getNativeEvent().getEventTarget()); - if (e.getClassName().contains("reserved") || isDisabled() - || !weekgrid.getParentCalendar().isRangeSelectAllowed()) { - eventRangeStart = -1; - } else { - eventRangeStart = event.getY(); - eventRangeStop = eventRangeStart; - Event.setCapture(getElement()); - setFocus(true); - } - } - } - - @Override - @SuppressWarnings("deprecation") - public void onMouseUp(MouseUpEvent event) { - if (event.getNativeButton() != NativeEvent.BUTTON_LEFT) { - return; - } - Event.releaseCapture(getElement()); - setFocus(false); - int dragDistance = Math.abs(eventRangeStart - event.getY()); - if (dragDistance > 0 && eventRangeStart >= 0) { - Element main = getElement(); - if (eventRangeStart > eventRangeStop) { - if (eventRangeStop <= -1) { - eventRangeStop = 0; - } - int temp = eventRangeStart; - eventRangeStart = eventRangeStop; - eventRangeStop = temp; - } - - NodeList<Node> nodes = main.getChildNodes(); - - int slotStart = -1; - int slotEnd = -1; - - // iterate over all child nodes, until we find first the start, - // and then the end - for (int i = 0; i < nodes.getLength(); i++) { - Element element = (Element) nodes.getItem(i); - boolean isRangeElement = element.getClassName() - .contains("v-daterange"); - - if (isRangeElement && slotStart == -1) { - slotStart = i; - slotEnd = i; // to catch one-slot selections - - } else if (isRangeElement) { - slotEnd = i; - - } else if (slotStart != -1 && slotEnd != -1) { - break; - } - } - - clearSelectionRange(); - - int startMinutes = firstHour * 60 + slotStart * 30; - int endMinutes = (firstHour * 60) + (slotEnd + 1) * 30; - Date currentDate = getDate(); - String yr = (currentDate.getYear() + 1900) + "-" - + (currentDate.getMonth() + 1) + "-" - + currentDate.getDate(); - if (weekgrid.getCalendar().getRangeSelectListener() != null) { - weekgrid.getCalendar().getRangeSelectListener().rangeSelected( - yr + ":" + startMinutes + ":" + endMinutes); - } - eventRangeStart = -1; - } else { - // Click event - eventRangeStart = -1; - cancelRangeSelect(); - - } - } - - @Override - public void onMouseMove(MouseMoveEvent event) { - if (event.getNativeButton() != NativeEvent.BUTTON_LEFT) { - return; - } - - if (eventRangeStart >= 0) { - int newY = event.getY(); - int fromY = 0; - int toY = 0; - if (newY < eventRangeStart) { - fromY = newY; - toY = eventRangeStart; - } else { - fromY = eventRangeStart; - toY = newY; - } - Element main = getElement(); - eventRangeStop = newY; - NodeList<Node> nodes = main.getChildNodes(); - for (int i = 0; i < nodes.getLength(); i++) { - Element c = (Element) nodes.getItem(i); - - if (todaybar != c) { - - int elemStart = c.getOffsetTop(); - int elemStop = elemStart + getSlotHeight(); - if (elemStart >= fromY && elemStart <= toY) { - c.addClassName("v-daterange"); - } else if (elemStop >= fromY && elemStop <= toY) { - c.addClassName("v-daterange"); - } else if (elemStop >= fromY && elemStart <= toY) { - c.addClassName("v-daterange"); - } else { - c.removeClassName("v-daterange"); - } - } - } - } - - event.preventDefault(); - } - - public void cancelRangeSelect() { - Event.releaseCapture(getElement()); - setFocus(false); - - clearSelectionRange(); - } - - private void clearSelectionRange() { - if (eventRangeStart > -1) { - // clear all "selected" class names - Element main = getElement(); - NodeList<Node> nodes = main.getChildNodes(); - - for (int i = 0; i <= 47; i++) { - Element c = (Element) nodes.getItem(i); - if (c == null) { - continue; - } - c.removeClassName("v-daterange"); - } - - eventRangeStart = -1; - } - } - - public void setToday(Date today, int width) { - this.today = today; - addStyleDependentName("today"); - Element lastChild = (Element) getElement().getLastChild(); - if (lastChild.getClassName().equals("v-calendar-current-time")) { - todaybar = lastChild; - } else { - todaybar = DOM.createDiv(); - todaybar.setClassName("v-calendar-current-time"); - getElement().appendChild(todaybar); - } - - if (width != -1) { - todaybar.getStyle().setWidth(width, Unit.PX); - } - - // position is calculated later, when we know the cell heights - } - - public Element getTodaybarElement() { - return todaybar; - } - - public void setDisabled(boolean disabled) { - this.disabled = disabled; - } - - public boolean isDisabled() { - return disabled; - } - - public void setDateColor(String styleName) { - this.setStyleName("v-calendar-datecell " + styleName); - } - - public boolean isToday() { - return today != null; - } - - /** - * @deprecated As of 7.2, call or override - * {@link #addEmphasisStyle(Element)} instead - */ - @Deprecated - public void addEmphasisStyle( - com.google.gwt.user.client.Element elementOver) { - String originalStylename = getStyleName(elementOver); - setStyleName(elementOver, originalStylename + DRAGEMPHASISSTYLE); - } - - /** - * @since 7.2 - */ - public void addEmphasisStyle(Element elementOver) { - addEmphasisStyle(DOM.asOld(elementOver)); - } - - /** - * @deprecated As of 7.2, call or override - * {@link #removeEmphasisStyle(Element)} instead - */ - @Deprecated - public void removeEmphasisStyle( - com.google.gwt.user.client.Element elementOver) { - String originalStylename = getStyleName(elementOver); - setStyleName(elementOver, originalStylename.substring(0, - originalStylename.length() - DRAGEMPHASISSTYLE.length())); - } - - /** - * @since 7.2 - */ - public void removeEmphasisStyle(Element elementOver) { - removeEmphasisStyle(DOM.asOld(elementOver)); - } - - @Override - public void onContextMenu(ContextMenuEvent event) { - if (weekgrid.getCalendar().getMouseEventListener() != null) { - event.preventDefault(); - event.stopPropagation(); - weekgrid.getCalendar().getMouseEventListener().contextMenu(event, - DateCell.this); - } - } - - private void updateEventCellsWidth() { - for (Widget widget : getChildren()) { - if (widget instanceof DateCellDayEvent) { - ((DateCellDayEvent) widget).setMoveWidth(width); - } - } - } - - private void updateEventCellsHeight() { - for (Widget widget : getChildren()) { - if (widget instanceof DateCellDayEvent) { - ((DateCellDayEvent) widget).setSlotHeightInPX(getSlotHeight()); - } - } - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DateCellContainer.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DateCellContainer.java deleted file mode 100644 index 92c39c0791..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DateCellContainer.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import java.util.Date; - -import com.google.gwt.event.dom.client.MouseDownEvent; -import com.google.gwt.event.dom.client.MouseDownHandler; -import com.google.gwt.event.dom.client.MouseUpEvent; -import com.google.gwt.event.dom.client.MouseUpHandler; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.WidgetUtil; -import com.vaadin.client.ui.VCalendar; - -/** - * Internally used class by the Calendar - * - * since 7.1 - */ -public class DateCellContainer extends FlowPanel - implements MouseDownHandler, MouseUpHandler { - - private Date date; - - private Widget clickTargetWidget; - - private VCalendar calendar; - - private static int borderWidth = -1; - - public DateCellContainer() { - setStylePrimaryName("v-calendar-datecell"); - } - - public static int measureBorderWidth(DateCellContainer dc) { - if (borderWidth == -1) { - borderWidth = WidgetUtil.measureHorizontalBorder(dc.getElement()); - } - return borderWidth; - } - - public void setCalendar(VCalendar calendar) { - this.calendar = calendar; - } - - public void setDate(Date date) { - this.date = date; - } - - public Date getDate() { - return date; - } - - public boolean hasEvent(int slotIndex) { - return hasDateCell(slotIndex) - && ((WeeklyLongEventsDateCell) getChildren().get(slotIndex)) - .getEvent() != null; - } - - public boolean hasDateCell(int slotIndex) { - return (getChildren().size() - 1) >= slotIndex; - } - - public WeeklyLongEventsDateCell getDateCell(int slotIndex) { - if (!hasDateCell(slotIndex)) { - addEmptyEventCells(slotIndex - (getChildren().size() - 1)); - } - return (WeeklyLongEventsDateCell) getChildren().get(slotIndex); - } - - public void addEmptyEventCells(int eventCount) { - for (int i = 0; i < eventCount; i++) { - addEmptyEventCell(); - } - } - - public void addEmptyEventCell() { - WeeklyLongEventsDateCell dateCell = new WeeklyLongEventsDateCell(); - dateCell.addMouseDownHandler(this); - dateCell.addMouseUpHandler(this); - add(dateCell); - } - - @Override - public void onMouseDown(MouseDownEvent event) { - clickTargetWidget = (Widget) event.getSource(); - - event.stopPropagation(); - } - - @Override - public void onMouseUp(MouseUpEvent event) { - if (event.getSource() == clickTargetWidget - && clickTargetWidget instanceof WeeklyLongEventsDateCell - && !calendar.isDisabledOrReadOnly()) { - CalendarEvent calendarEvent = ((WeeklyLongEventsDateCell) clickTargetWidget) - .getEvent(); - if (calendar.getEventClickListener() != null) { - calendar.getEventClickListener().eventClick(calendarEvent); - } - } - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DateCellDayEvent.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DateCellDayEvent.java deleted file mode 100644 index 7404f557a8..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DateCellDayEvent.java +++ /dev/null @@ -1,664 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import java.util.Date; -import java.util.LinkedList; -import java.util.List; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.EventTarget; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Position; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.event.dom.client.ContextMenuEvent; -import com.google.gwt.event.dom.client.ContextMenuHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.MouseDownEvent; -import com.google.gwt.event.dom.client.MouseDownHandler; -import com.google.gwt.event.dom.client.MouseMoveEvent; -import com.google.gwt.event.dom.client.MouseMoveHandler; -import com.google.gwt.event.dom.client.MouseUpEvent; -import com.google.gwt.event.dom.client.MouseUpHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.HorizontalPanel; -import com.vaadin.client.WidgetUtil; -import com.vaadin.shared.ui.calendar.DateConstants; - -/** - * Internally used by the calendar - * - * @since 7.1 - */ -public class DateCellDayEvent extends FocusableHTML - implements MouseDownHandler, MouseUpHandler, MouseMoveHandler, - KeyDownHandler, ContextMenuHandler, HasTooltipKey { - - private final DateCell dateCell; - private Element caption = null; - private final Element eventContent; - private CalendarEvent calendarEvent = null; - private HandlerRegistration moveRegistration; - private int startY = -1; - private int startX = -1; - private String moveWidth; - public static final int halfHourInMilliSeconds = 1800 * 1000; - private Date startDatetimeFrom; - private Date startDatetimeTo; - private boolean mouseMoveStarted; - private int top; - private int startYrelative; - private int startXrelative; - private boolean disabled; - private final WeekGrid weekGrid; - private Element topResizeBar; - private Element bottomResizeBar; - private Element clickTarget; - private final Integer eventIndex; - private int slotHeight; - private final List<HandlerRegistration> handlers; - private boolean mouseMoveCanceled; - - public DateCellDayEvent(DateCell dateCell, WeekGrid parent, - CalendarEvent event) { - super(); - this.dateCell = dateCell; - - handlers = new LinkedList<HandlerRegistration>(); - - setStylePrimaryName("v-calendar-event"); - setCalendarEvent(event); - - weekGrid = parent; - - Style s = getElement().getStyle(); - if (event.getStyleName().length() > 0) { - addStyleDependentName(event.getStyleName()); - } - s.setPosition(Position.ABSOLUTE); - - caption = DOM.createDiv(); - caption.addClassName("v-calendar-event-caption"); - getElement().appendChild(caption); - - eventContent = DOM.createDiv(); - eventContent.addClassName("v-calendar-event-content"); - getElement().appendChild(eventContent); - - if (weekGrid.getCalendar().isEventResizeAllowed()) { - topResizeBar = DOM.createDiv(); - bottomResizeBar = DOM.createDiv(); - - topResizeBar.addClassName("v-calendar-event-resizetop"); - bottomResizeBar.addClassName("v-calendar-event-resizebottom"); - - getElement().appendChild(topResizeBar); - getElement().appendChild(bottomResizeBar); - } - - eventIndex = event.getIndex(); - } - - @Override - protected void onAttach() { - super.onAttach(); - handlers.add(addMouseDownHandler(this)); - handlers.add(addMouseUpHandler(this)); - handlers.add(addKeyDownHandler(this)); - handlers.add(addDomHandler(this, ContextMenuEvent.getType())); - } - - @Override - protected void onDetach() { - for (HandlerRegistration handler : handlers) { - handler.removeHandler(); - } - handlers.clear(); - super.onDetach(); - } - - public void setSlotHeightInPX(int slotHeight) { - this.slotHeight = slotHeight; - } - - public void updatePosition(long startFromMinutes, long durationInMinutes) { - if (startFromMinutes < 0) { - startFromMinutes = 0; - } - top = weekGrid.getPixelTopFor((int) startFromMinutes); - - getElement().getStyle().setTop(top, Unit.PX); - if (durationInMinutes > 0) { - int heightMinutes = weekGrid.getPixelLengthFor( - (int) startFromMinutes, (int) durationInMinutes); - setHeight(heightMinutes); - } else { - setHeight(-1); - } - - boolean multiRowCaption = (durationInMinutes > 30); - updateCaptions(multiRowCaption); - } - - public int getTop() { - return top; - } - - public void setMoveWidth(int width) { - moveWidth = width + "px"; - } - - public void setHeight(int h) { - if (h == -1) { - getElement().getStyle().setProperty("height", ""); - eventContent.getStyle().setProperty("height", ""); - } else { - getElement().getStyle().setHeight(h, Unit.PX); - // FIXME measure the border height (2px) from the DOM - eventContent.getStyle().setHeight(h - 2, Unit.PX); - } - } - - /** - * @param bigMode - * If false, event is so small that caption must be in time-row - */ - private void updateCaptions(boolean bigMode) { - String innerHtml; - String timeAsText = calendarEvent.getTimeAsText(); - String htmlOrText; - - if (dateCell.weekgrid.getCalendar().isEventCaptionAsHtml()) { - htmlOrText = calendarEvent.getCaption(); - } else { - htmlOrText = WidgetUtil.escapeHTML(calendarEvent.getCaption()); - } - - if (bigMode) { - innerHtml = "<span>" + timeAsText + "</span><br />" + htmlOrText; - } else { - innerHtml = "<span>" + timeAsText + "<span>:</span></span> " - + htmlOrText; - } - caption.setInnerHTML(innerHtml); - eventContent.setInnerHTML(""); - } - - @Override - public void onKeyDown(KeyDownEvent event) { - int keycode = event.getNativeEvent().getKeyCode(); - if (keycode == KeyCodes.KEY_ESCAPE && mouseMoveStarted) { - cancelMouseMove(); - } - } - - @Override - public void onMouseDown(MouseDownEvent event) { - startX = event.getClientX(); - startY = event.getClientY(); - if (isDisabled() - || event.getNativeButton() != NativeEvent.BUTTON_LEFT) { - return; - } - - clickTarget = Element.as(event.getNativeEvent().getEventTarget()); - mouseMoveCanceled = false; - - if (weekGrid.getCalendar().isEventMoveAllowed() - || clickTargetsResize()) { - moveRegistration = addMouseMoveHandler(this); - setFocus(true); - try { - startYrelative = (int) ((double) event.getRelativeY(caption) - % slotHeight); - startXrelative = (event.getRelativeX(weekGrid.getElement()) - - weekGrid.timebar.getOffsetWidth()) - % getDateCellWidth(); - } catch (Exception e) { - GWT.log("Exception calculating relative start position", e); - } - mouseMoveStarted = false; - Style s = getElement().getStyle(); - s.setZIndex(1000); - startDatetimeFrom = (Date) calendarEvent.getStartTime().clone(); - startDatetimeTo = (Date) calendarEvent.getEndTime().clone(); - Event.setCapture(getElement()); - } - - // make sure the right cursor is always displayed - if (clickTargetsResize()) { - addGlobalResizeStyle(); - } - - /* - * We need to stop the event propagation or else the WeekGrid range - * select will kick in - */ - event.stopPropagation(); - event.preventDefault(); - } - - @Override - public void onMouseUp(MouseUpEvent event) { - if (mouseMoveCanceled - || event.getNativeButton() != NativeEvent.BUTTON_LEFT) { - return; - } - - Event.releaseCapture(getElement()); - setFocus(false); - if (moveRegistration != null) { - moveRegistration.removeHandler(); - moveRegistration = null; - } - int endX = event.getClientX(); - int endY = event.getClientY(); - int xDiff = 0, yDiff = 0; - if (startX != -1 && startY != -1) { - // Drag started - xDiff = startX - endX; - yDiff = startY - endY; - } - - startX = -1; - startY = -1; - mouseMoveStarted = false; - Style s = getElement().getStyle(); - s.setZIndex(1); - if (!clickTargetsResize()) { - // check if mouse has moved over threshold of 3 pixels - boolean mouseMoved = (xDiff < -3 || xDiff > 3 || yDiff < -3 - || yDiff > 3); - - if (!weekGrid.getCalendar().isDisabledOrReadOnly() && mouseMoved) { - // Event Move: - // - calendar must be enabled - // - calendar must not be in read-only mode - weekGrid.eventMoved(this); - } else if (!weekGrid.getCalendar().isDisabled()) { - // Event Click: - // - calendar must be enabled (read-only is allowed) - EventTarget et = event.getNativeEvent().getEventTarget(); - Element e = Element.as(et); - if (e == caption || e == eventContent - || e.getParentElement() == caption) { - if (weekGrid.getCalendar() - .getEventClickListener() != null) { - weekGrid.getCalendar().getEventClickListener() - .eventClick(calendarEvent); - } - } - } - - } else { // click targeted resize bar - removeGlobalResizeStyle(); - if (weekGrid.getCalendar().getEventResizeListener() != null) { - weekGrid.getCalendar().getEventResizeListener() - .eventResized(calendarEvent); - } - dateCell.recalculateEventWidths(); - } - } - - @Override - @SuppressWarnings("deprecation") - public void onMouseMove(MouseMoveEvent event) { - if (startY < 0 && startX < 0) { - return; - } - if (isDisabled()) { - Event.releaseCapture(getElement()); - mouseMoveStarted = false; - startY = -1; - startX = -1; - removeGlobalResizeStyle(); - return; - } - int currentY = event.getClientY(); - int currentX = event.getClientX(); - int moveY = (currentY - startY); - int moveX = (currentX - startX); - if ((moveY < 5 && moveY > -6) && (moveX < 5 && moveX > -6)) { - return; - } - if (!mouseMoveStarted) { - setWidth(moveWidth); - getElement().getStyle().setMarginLeft(0, Unit.PX); - mouseMoveStarted = true; - } - - HorizontalPanel parent = (HorizontalPanel) getParent().getParent(); - int relativeX = event.getRelativeX(parent.getElement()) - - weekGrid.timebar.getOffsetWidth(); - int halfHourDiff = 0; - if (moveY > 0) { - halfHourDiff = (startYrelative + moveY) / slotHeight; - } else { - halfHourDiff = (moveY - startYrelative) / slotHeight; - } - - int dateCellWidth = getDateCellWidth(); - long dayDiff = 0; - if (moveX >= 0) { - dayDiff = (startXrelative + moveX) / dateCellWidth; - } else { - dayDiff = (moveX - (dateCellWidth - startXrelative)) - / dateCellWidth; - } - - int dayOffset = relativeX / dateCellWidth; - - // sanity check for right side overflow - int dateCellCount = weekGrid.getDateCellCount(); - if (dayOffset >= dateCellCount) { - dayOffset--; - dayDiff--; - } - - int dayOffsetPx = calculateDateCellOffsetPx(dayOffset) - + weekGrid.timebar.getOffsetWidth(); - - GWT.log("DateCellWidth: " + dateCellWidth + " dayDiff: " + dayDiff - + " dayOffset: " + dayOffset + " dayOffsetPx: " + dayOffsetPx - + " startXrelative: " + startXrelative + " moveX: " + moveX); - - if (relativeX < 0 || relativeX >= getDatesWidth()) { - return; - } - - Style s = getElement().getStyle(); - - Date from = calendarEvent.getStartTime(); - Date to = calendarEvent.getEndTime(); - long duration = to.getTime() - from.getTime(); - - if (!clickTargetsResize() - && weekGrid.getCalendar().isEventMoveAllowed()) { - long daysMs = dayDiff * DateConstants.DAYINMILLIS; - from.setTime(startDatetimeFrom.getTime() + daysMs); - from.setTime(from.getTime() - + ((long) halfHourInMilliSeconds * halfHourDiff)); - to.setTime((from.getTime() + duration)); - - calendarEvent.setStartTime(from); - calendarEvent.setEndTime(to); - calendarEvent.setStart(new Date(from.getTime())); - calendarEvent.setEnd(new Date(to.getTime())); - - // Set new position for the event - long startFromMinutes = (from.getHours() * 60) + from.getMinutes(); - long range = calendarEvent.getRangeInMinutes(); - startFromMinutes = calculateStartFromMinute(startFromMinutes, from, - to, dayOffsetPx); - if (startFromMinutes < 0) { - range += startFromMinutes; - } - updatePosition(startFromMinutes, range); - - s.setLeft(dayOffsetPx, Unit.PX); - - if (weekGrid.getDateCellWidths() != null) { - s.setWidth(weekGrid.getDateCellWidths()[dayOffset], Unit.PX); - } else { - setWidth(moveWidth); - } - - } else if (clickTarget == topResizeBar) { - long oldStartTime = startDatetimeFrom.getTime(); - long newStartTime = oldStartTime - + ((long) halfHourInMilliSeconds * halfHourDiff); - - if (!isTimeRangeTooSmall(newStartTime, startDatetimeTo.getTime())) { - newStartTime = startDatetimeTo.getTime() - getMinTimeRange(); - } - - from.setTime(newStartTime); - - calendarEvent.setStartTime(from); - calendarEvent.setStart(new Date(from.getTime())); - - // Set new position for the event - long startFromMinutes = (from.getHours() * 60) + from.getMinutes(); - long range = calendarEvent.getRangeInMinutes(); - - updatePosition(startFromMinutes, range); - - } else if (clickTarget == bottomResizeBar) { - long oldEndTime = startDatetimeTo.getTime(); - long newEndTime = oldEndTime - + ((long) halfHourInMilliSeconds * halfHourDiff); - - if (!isTimeRangeTooSmall(startDatetimeFrom.getTime(), newEndTime)) { - newEndTime = startDatetimeFrom.getTime() + getMinTimeRange(); - } - - to.setTime(newEndTime); - - calendarEvent.setEndTime(to); - calendarEvent.setEnd(new Date(to.getTime())); - - // Set new position for the event - long startFromMinutes = (startDatetimeFrom.getHours() * 60) - + startDatetimeFrom.getMinutes(); - long range = calendarEvent.getRangeInMinutes(); - startFromMinutes = calculateStartFromMinute(startFromMinutes, from, - to, dayOffsetPx); - if (startFromMinutes < 0) { - range += startFromMinutes; - } - updatePosition(startFromMinutes, range); - } - } - - private void cancelMouseMove() { - mouseMoveCanceled = true; - - // reset and remove everything related to the event handling - Event.releaseCapture(getElement()); - setFocus(false); - - if (moveRegistration != null) { - moveRegistration.removeHandler(); - moveRegistration = null; - } - - mouseMoveStarted = false; - removeGlobalResizeStyle(); - - Style s = getElement().getStyle(); - s.setZIndex(1); - - // reset the position of the event - int dateCellWidth = getDateCellWidth(); - int dayOffset = startXrelative / dateCellWidth; - s.clearLeft(); - - calendarEvent.setStartTime(startDatetimeFrom); - calendarEvent.setEndTime(startDatetimeTo); - - long startFromMinutes = (startDatetimeFrom.getHours() * 60) - + startDatetimeFrom.getMinutes(); - long range = calendarEvent.getRangeInMinutes(); - - startFromMinutes = calculateStartFromMinute(startFromMinutes, - startDatetimeFrom, startDatetimeTo, dayOffset); - if (startFromMinutes < 0) { - range += startFromMinutes; - } - - updatePosition(startFromMinutes, range); - - startY = -1; - startX = -1; - - // to reset the event width - ((DateCell) getParent()).recalculateEventWidths(); - } - - // date methods are not deprecated in GWT - @SuppressWarnings("deprecation") - private long calculateStartFromMinute(long startFromMinutes, Date from, - Date to, int dayOffset) { - boolean eventStartAtDifferentDay = from.getDate() != to.getDate(); - if (eventStartAtDifferentDay) { - long minutesOnPrevDay = (getTargetDateByCurrentPosition(dayOffset) - .getTime() - from.getTime()) / DateConstants.MINUTEINMILLIS; - startFromMinutes = -1 * minutesOnPrevDay; - } - - return startFromMinutes; - } - - /** - * @param dateOffset - * @return the amount of pixels the given date is from the left side - */ - private int calculateDateCellOffsetPx(int dateOffset) { - int dateCellOffset = 0; - int[] dateWidths = weekGrid.getDateCellWidths(); - - if (dateWidths != null) { - for (int i = 0; i < dateOffset; i++) { - dateCellOffset += dateWidths[i] + 1; - } - } else { - dateCellOffset = dateOffset * weekGrid.getDateCellWidth(); - } - - return dateCellOffset; - } - - /** - * Check if the given time range is too small for events - * - * @param start - * @param end - * @return - */ - private boolean isTimeRangeTooSmall(long start, long end) { - return (end - start) >= getMinTimeRange(); - } - - /** - * @return the minimum amount of ms that an event must last when resized - */ - private long getMinTimeRange() { - return DateConstants.MINUTEINMILLIS * 30; - } - - /** - * Build the string for sending resize events to server - * - * @param event - * @return - */ - private String buildResizeString(CalendarEvent event) { - StringBuilder buffer = new StringBuilder(); - buffer.append(event.getIndex()); - buffer.append(","); - buffer.append(DateUtil.formatClientSideDate(event.getStart())); - buffer.append("-"); - buffer.append(DateUtil.formatClientSideTime(event.getStartTime())); - buffer.append(","); - buffer.append(DateUtil.formatClientSideDate(event.getEnd())); - buffer.append("-"); - buffer.append(DateUtil.formatClientSideTime(event.getEndTime())); - - return buffer.toString(); - } - - private Date getTargetDateByCurrentPosition(int left) { - DateCell newParent = (DateCell) weekGrid.content - .getWidget((left / getDateCellWidth()) + 1); - Date targetDate = newParent.getDate(); - return targetDate; - } - - private int getDateCellWidth() { - return weekGrid.getDateCellWidth(); - } - - /* Returns total width of all date cells. */ - private int getDatesWidth() { - if (weekGrid.width == -1) { - // Undefined width. Needs to be calculated by the known cell - // widths. - int count = weekGrid.content.getWidgetCount() - 1; - return count * getDateCellWidth(); - } - - return weekGrid.getInternalWidth(); - } - - /** - * @return true if the current mouse movement is resizing - */ - private boolean clickTargetsResize() { - return weekGrid.getCalendar().isEventResizeAllowed() - && (clickTarget == topResizeBar - || clickTarget == bottomResizeBar); - } - - private void addGlobalResizeStyle() { - if (clickTarget == topResizeBar) { - weekGrid.getCalendar().addStyleDependentName("nresize"); - } else if (clickTarget == bottomResizeBar) { - weekGrid.getCalendar().addStyleDependentName("sresize"); - } - } - - private void removeGlobalResizeStyle() { - weekGrid.getCalendar().removeStyleDependentName("nresize"); - weekGrid.getCalendar().removeStyleDependentName("sresize"); - } - - public void setCalendarEvent(CalendarEvent calendarEvent) { - this.calendarEvent = calendarEvent; - } - - public CalendarEvent getCalendarEvent() { - return calendarEvent; - } - - public void setDisabled(boolean disabled) { - this.disabled = disabled; - } - - public boolean isDisabled() { - return disabled; - } - - @Override - public void onContextMenu(ContextMenuEvent event) { - if (dateCell.weekgrid.getCalendar().getMouseEventListener() != null) { - event.preventDefault(); - event.stopPropagation(); - dateCell.weekgrid.getCalendar().getMouseEventListener() - .contextMenu(event, this); - } - } - - @Override - public Object getTooltipKey() { - return eventIndex; - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DateCellGroup.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DateCellGroup.java deleted file mode 100644 index 907a71c449..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DateCellGroup.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -/** - * Internally used by the calendar - * - * @since 7.1 - */ -public class DateCellGroup { - private WeekGridMinuteTimeRange range; - private final List<Integer> items; - - public DateCellGroup(Integer index) { - items = new ArrayList<Integer>(); - items.add(index); - } - - public WeekGridMinuteTimeRange getDateRange() { - return range; - } - - public Date getStart() { - return range.getStart(); - } - - public Date getEnd() { - return range.getEnd(); - } - - public void setDateRange(WeekGridMinuteTimeRange range) { - this.range = range; - } - - public List<Integer> getItems() { - return items; - } - - public void add(Integer index) { - items.add(index); - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DateUtil.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DateUtil.java deleted file mode 100644 index 4a11e95245..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DateUtil.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import java.util.Date; - -import com.google.gwt.i18n.client.DateTimeFormat; -import com.vaadin.shared.ui.calendar.DateConstants; - -/** - * Utility class for {@link Date} operations - * - * @since 7.1 - * @author Vaadin Ltd. - */ -public class DateUtil { - - /** - * Checks if dates are same day without checking datetimes. - * - * @param date1 - * @param date2 - * @return - */ - @SuppressWarnings("deprecation") - public static boolean compareDate(Date date1, Date date2) { - if (date1.getDate() == date2.getDate() - && date1.getYear() == date2.getYear() - && date1.getMonth() == date2.getMonth()) { - return true; - } - return false; - } - - /** - * @param date - * the date to format - * - * @return given Date as String, for communicating to server-side - */ - public static String formatClientSideDate(Date date) { - DateTimeFormat dateformat_date = DateTimeFormat - .getFormat(DateConstants.CLIENT_DATE_FORMAT); - return dateformat_date.format(date); - } - - /** - * @param date - * the date to format - * @return given Date as String, for communicating to server-side - */ - public static String formatClientSideTime(Date date) { - DateTimeFormat dateformat_date = DateTimeFormat - .getFormat(DateConstants.CLIENT_TIME_FORMAT); - return dateformat_date.format(date); - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DayToolbar.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DayToolbar.java deleted file mode 100644 index 0ba1023945..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/DayToolbar.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import java.util.Iterator; - -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.HorizontalPanel; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.ui.VCalendar; - -/** - * - * @since 7.1 - * @author Vaadin Ltd. - * - */ -public class DayToolbar extends HorizontalPanel implements ClickHandler { - private int width = 0; - protected static final int MARGINLEFT = 50; - protected static final int MARGINRIGHT = 20; - protected Button backLabel; - protected Button nextLabel; - private boolean verticalSized; - private boolean horizontalSized; - private VCalendar calendar; - - public DayToolbar(VCalendar vcalendar) { - calendar = vcalendar; - - setStylePrimaryName("v-calendar-header-week"); - backLabel = new Button(); - backLabel.setStylePrimaryName("v-calendar-back"); - nextLabel = new Button(); - nextLabel.addClickHandler(this); - nextLabel.setStylePrimaryName("v-calendar-next"); - backLabel.addClickHandler(this); - setBorderWidth(0); - setSpacing(0); - } - - public void setWidthPX(int width) { - this.width = (width - MARGINLEFT) - MARGINRIGHT; - // super.setWidth(this.width + "px"); - if (getWidgetCount() == 0) { - return; - } - updateCellWidths(); - } - - public void updateCellWidths() { - int count = getWidgetCount(); - if (count > 0) { - setCellWidth(backLabel, MARGINLEFT + "px"); - setCellWidth(nextLabel, MARGINRIGHT + "px"); - setCellHorizontalAlignment(nextLabel, ALIGN_RIGHT); - int cellw = width / (count - 2); - if (cellw > 0) { - int[] cellWidths = VCalendar.distributeSize(width, count - 2, - 0); - for (int i = 1; i < count - 1; i++) { - Widget widget = getWidget(i); - // if (remain > 0) { - // setCellWidth(widget, cellw2 + "px"); - // remain--; - // } else { - // setCellWidth(widget, cellw + "px"); - // } - setCellWidth(widget, cellWidths[i - 1] + "px"); - widget.setWidth(cellWidths[i - 1] + "px"); - } - } - } - } - - public void add(String dayName, final String date, - String localized_date_format, String extraClass) { - Label l = new Label(dayName + " " + localized_date_format); - l.setStylePrimaryName("v-calendar-header-day"); - - if (extraClass != null) { - l.addStyleDependentName(extraClass); - } - - if (verticalSized) { - l.addStyleDependentName("Vsized"); - } - if (horizontalSized) { - l.addStyleDependentName("Hsized"); - } - - l.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - if (calendar.getDateClickListener() != null) { - calendar.getDateClickListener().dateClick(date); - } - } - }); - - add(l); - } - - public void addBackButton() { - if (!calendar.isBackwardNavigationEnabled()) { - nextLabel.getElement().getStyle().setHeight(0, Unit.PX); - } - add(backLabel); - } - - public void addNextButton() { - if (!calendar.isForwardNavigationEnabled()) { - backLabel.getElement().getStyle().setHeight(0, Unit.PX); - } - add(nextLabel); - } - - @Override - public void onClick(ClickEvent event) { - if (!calendar.isDisabled()) { - if (event.getSource() == nextLabel) { - if (calendar.getForwardListener() != null) { - calendar.getForwardListener().forward(); - } - } else if (event.getSource() == backLabel) { - if (calendar.getBackwardListener() != null) { - calendar.getBackwardListener().backward(); - } - } - } - } - - public void setVerticalSized(boolean sized) { - verticalSized = sized; - updateDayLabelSizedStyleNames(); - } - - public void setHorizontalSized(boolean sized) { - horizontalSized = sized; - updateDayLabelSizedStyleNames(); - } - - private void updateDayLabelSizedStyleNames() { - Iterator<Widget> it = iterator(); - while (it.hasNext()) { - updateWidgetSizedStyleName(it.next()); - } - } - - private void updateWidgetSizedStyleName(Widget w) { - if (verticalSized) { - w.addStyleDependentName("Vsized"); - } else { - w.removeStyleDependentName("VSized"); - } - if (horizontalSized) { - w.addStyleDependentName("Hsized"); - } else { - w.removeStyleDependentName("HSized"); - } - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/FocusableComplexPanel.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/FocusableComplexPanel.java deleted file mode 100644 index a498525c92..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/FocusableComplexPanel.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.HasBlurHandlers; -import com.google.gwt.event.dom.client.HasFocusHandlers; -import com.google.gwt.event.dom.client.HasKeyDownHandlers; -import com.google.gwt.event.dom.client.HasKeyPressHandlers; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.ui.ComplexPanel; -import com.google.gwt.user.client.ui.impl.FocusImpl; -import com.vaadin.client.Focusable; - -/** - * A ComplexPanel that can be focused - * - * @since 7.1 - * @author Vaadin Ltd. - * - */ -public class FocusableComplexPanel extends ComplexPanel - implements HasFocusHandlers, HasBlurHandlers, HasKeyDownHandlers, - HasKeyPressHandlers, Focusable { - - protected void makeFocusable() { - // make focusable, as we don't need access key magic we don't need to - // use FocusImpl.createFocusable - getElement().setTabIndex(0); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasFocusHandlers#addFocusHandler(com. - * google.gwt.event.dom.client.FocusHandler) - */ - @Override - public HandlerRegistration addFocusHandler(FocusHandler handler) { - return addDomHandler(handler, FocusEvent.getType()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasBlurHandlers#addBlurHandler(com.google - * .gwt.event.dom.client.BlurHandler) - */ - @Override - public HandlerRegistration addBlurHandler(BlurHandler handler) { - return addDomHandler(handler, BlurEvent.getType()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasKeyDownHandlers#addKeyDownHandler( - * com.google.gwt.event.dom.client.KeyDownHandler) - */ - @Override - public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) { - return addDomHandler(handler, KeyDownEvent.getType()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasKeyPressHandlers#addKeyPressHandler - * (com.google.gwt.event.dom.client.KeyPressHandler) - */ - @Override - public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) { - return addDomHandler(handler, KeyPressEvent.getType()); - } - - /** - * Sets/Removes the keyboard focus to the panel. - * - * @param focus - * If set to true then the focus is moved to the panel, if set to - * false the focus is removed - */ - public void setFocus(boolean focus) { - if (focus) { - FocusImpl.getFocusImplForPanel().focus(getElement()); - } else { - FocusImpl.getFocusImplForPanel().blur(getElement()); - } - } - - /** - * Focus the panel - */ - @Override - public void focus() { - setFocus(true); - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/FocusableGrid.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/FocusableGrid.java deleted file mode 100644 index fd46f5553b..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/FocusableGrid.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.HasBlurHandlers; -import com.google.gwt.event.dom.client.HasFocusHandlers; -import com.google.gwt.event.dom.client.HasKeyDownHandlers; -import com.google.gwt.event.dom.client.HasKeyPressHandlers; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.ui.Grid; -import com.google.gwt.user.client.ui.impl.FocusImpl; -import com.vaadin.client.Focusable; - -/** - * A Grid that can be focused - * - * @since 7.1 - * @author Vaadin Ltd. - * - */ -public class FocusableGrid extends Grid implements HasFocusHandlers, - HasBlurHandlers, HasKeyDownHandlers, HasKeyPressHandlers, Focusable { - - /** - * Constructor - */ - public FocusableGrid() { - super(); - makeFocusable(); - } - - public FocusableGrid(int rows, int columns) { - super(rows, columns); - makeFocusable(); - } - - protected void makeFocusable() { - // make focusable, as we don't need access key magic we don't need to - // use FocusImpl.createFocusable - getElement().setTabIndex(0); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasFocusHandlers#addFocusHandler(com. - * google.gwt.event.dom.client.FocusHandler) - */ - @Override - public HandlerRegistration addFocusHandler(FocusHandler handler) { - return addDomHandler(handler, FocusEvent.getType()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasBlurHandlers#addBlurHandler(com.google - * .gwt.event.dom.client.BlurHandler) - */ - @Override - public HandlerRegistration addBlurHandler(BlurHandler handler) { - return addDomHandler(handler, BlurEvent.getType()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasKeyDownHandlers#addKeyDownHandler( - * com.google.gwt.event.dom.client.KeyDownHandler) - */ - @Override - public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) { - return addDomHandler(handler, KeyDownEvent.getType()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasKeyPressHandlers#addKeyPressHandler - * (com.google.gwt.event.dom.client.KeyPressHandler) - */ - @Override - public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) { - return addDomHandler(handler, KeyPressEvent.getType()); - } - - /** - * Sets/Removes the keyboard focus to the panel. - * - * @param focus - * If set to true then the focus is moved to the panel, if set to - * false the focus is removed - */ - public void setFocus(boolean focus) { - if (focus) { - FocusImpl.getFocusImplForPanel().focus(getElement()); - } else { - FocusImpl.getFocusImplForPanel().blur(getElement()); - } - } - - /** - * Focus the panel - */ - @Override - public void focus() { - setFocus(true); - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/FocusableHTML.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/FocusableHTML.java deleted file mode 100644 index 3a838a58a3..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/FocusableHTML.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import com.google.gwt.event.dom.client.BlurEvent; -import com.google.gwt.event.dom.client.BlurHandler; -import com.google.gwt.event.dom.client.FocusEvent; -import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.event.dom.client.HasBlurHandlers; -import com.google.gwt.event.dom.client.HasFocusHandlers; -import com.google.gwt.event.dom.client.HasKeyDownHandlers; -import com.google.gwt.event.dom.client.HasKeyPressHandlers; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyPressEvent; -import com.google.gwt.event.dom.client.KeyPressHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.impl.FocusImpl; -import com.vaadin.client.Focusable; - -/** - * A HTML widget that can be focused - * - * @since 7.1 - * @author Vaadin Ltd. - * - */ -public class FocusableHTML extends HTML implements HasFocusHandlers, - HasBlurHandlers, HasKeyDownHandlers, HasKeyPressHandlers, Focusable { - - /** - * Constructor - */ - public FocusableHTML() { - // make focusable, as we don't need access key magic we don't need to - // use FocusImpl.createFocusable - getElement().setTabIndex(0); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasFocusHandlers#addFocusHandler(com. - * google.gwt.event.dom.client.FocusHandler) - */ - @Override - public HandlerRegistration addFocusHandler(FocusHandler handler) { - return addDomHandler(handler, FocusEvent.getType()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasBlurHandlers#addBlurHandler(com.google - * .gwt.event.dom.client.BlurHandler) - */ - @Override - public HandlerRegistration addBlurHandler(BlurHandler handler) { - return addDomHandler(handler, BlurEvent.getType()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasKeyDownHandlers#addKeyDownHandler( - * com.google.gwt.event.dom.client.KeyDownHandler) - */ - @Override - public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) { - return addDomHandler(handler, KeyDownEvent.getType()); - } - - /* - * (non-Javadoc) - * - * @see - * com.google.gwt.event.dom.client.HasKeyPressHandlers#addKeyPressHandler - * (com.google.gwt.event.dom.client.KeyPressHandler) - */ - @Override - public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) { - return addDomHandler(handler, KeyPressEvent.getType()); - } - - /** - * Sets/Removes the keyboard focus to the panel. - * - * @param focus - * If set to true then the focus is moved to the panel, if set to - * false the focus is removed - */ - public void setFocus(boolean focus) { - if (focus) { - FocusImpl.getFocusImplForPanel().focus(getElement()); - } else { - FocusImpl.getFocusImplForPanel().blur(getElement()); - } - } - - /** - * Focus the panel - */ - @Override - public void focus() { - setFocus(true); - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/HasTooltipKey.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/HasTooltipKey.java deleted file mode 100644 index 936f978abb..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/HasTooltipKey.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -/** - * For Calendar client-side internal use only. - * - * @since 7.1 - * @author Vaadin Ltd. - * - */ -public interface HasTooltipKey { - /** - * Gets the key associated for the Widget implementing this interface. This - * key is used for getting a tooltip title identified by the key - * - * @return the tooltip key - */ - Object getTooltipKey(); -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/MonthEventLabel.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/MonthEventLabel.java deleted file mode 100644 index c62b21592a..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/MonthEventLabel.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import java.util.Date; - -import com.google.gwt.event.dom.client.ContextMenuEvent; -import com.google.gwt.event.dom.client.ContextMenuHandler; -import com.google.gwt.user.client.ui.HTML; -import com.vaadin.client.Util; -import com.vaadin.client.ui.VCalendar; - -/** - * The label in a month cell - * - * @since 7.1 - */ -public class MonthEventLabel extends HTML implements HasTooltipKey { - - private static final String STYLENAME = "v-calendar-event"; - - private boolean timeSpecificEvent = false; - private Integer eventIndex; - private VCalendar calendar; - private String caption; - private Date time; - - private CalendarEvent calendarEvent; - - /** - * Default constructor - */ - public MonthEventLabel() { - setStylePrimaryName(STYLENAME); - - addDomHandler(new ContextMenuHandler() { - @Override - public void onContextMenu(ContextMenuEvent event) { - calendar.getMouseEventListener().contextMenu(event, - MonthEventLabel.this); - event.stopPropagation(); - event.preventDefault(); - } - }, ContextMenuEvent.getType()); - } - - public void setCalendarEvent(CalendarEvent e) { - calendarEvent = e; - } - - /** - * Set the time of the event label - * - * @param date - * The date object that specifies the time - */ - public void setTime(Date date) { - time = date; - renderCaption(); - } - - /** - * Set the caption of the event label - * - * @param caption - * The caption string, can be HTML if - * {@link VCalendar#isEventCaptionAsHtml()} is true - */ - public void setCaption(String caption) { - this.caption = caption; - renderCaption(); - } - - /** - * Renders the caption in the DIV element - */ - private void renderCaption() { - StringBuilder html = new StringBuilder(); - String textOrHtml; - if (calendar.isEventCaptionAsHtml()) { - textOrHtml = caption; - } else { - textOrHtml = Util.escapeHTML(caption); - } - - if (caption != null && time != null) { - html.append("<span class=\"" + STYLENAME + "-time\">"); - html.append(calendar.getTimeFormat().format(time)); - html.append("</span> "); - html.append(textOrHtml); - } else if (caption != null) { - html.append(textOrHtml); - } else if (time != null) { - html.append("<span class=\"" + STYLENAME + "-time\">"); - html.append(calendar.getTimeFormat().format(time)); - html.append("</span>"); - } - super.setHTML(html.toString()); - } - - /** - * Set the (server side) index of the event - * - * @param index - * The integer index - */ - public void setEventIndex(int index) { - eventIndex = index; - } - - /** - * Set the Calendar instance this label belongs to - * - * @param calendar - * The calendar instance - */ - public void setCalendar(VCalendar calendar) { - this.calendar = calendar; - } - - /** - * Is the event bound to a specific time - * - * @return - */ - public boolean isTimeSpecificEvent() { - return timeSpecificEvent; - } - - /** - * Is the event bound to a specific time - * - * @param timeSpecificEvent - * True if the event is bound to a time, false if it is only - * bound to the day - */ - public void setTimeSpecificEvent(boolean timeSpecificEvent) { - this.timeSpecificEvent = timeSpecificEvent; - } - - /* - * (non-Javadoc) - * - * @see com.google.gwt.user.client.ui.HTML#setHTML(java.lang.String) - */ - @Override - public void setHTML(String html) { - throw new UnsupportedOperationException( - "Use setCaption() and setTime() instead"); - } - - @Override - public Object getTooltipKey() { - return eventIndex; - } - - public CalendarEvent getCalendarEvent() { - return calendarEvent; - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/MonthGrid.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/MonthGrid.java deleted file mode 100644 index 119fe27992..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/MonthGrid.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import java.util.Date; - -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.vaadin.client.ui.VCalendar; - -/** - * - * @since 7.1 - * @author Vaadin Ltd. - * - */ -public class MonthGrid extends FocusableGrid implements KeyDownHandler { - - private SimpleDayCell selectionStart; - private SimpleDayCell selectionEnd; - private final VCalendar calendar; - private boolean rangeSelectDisabled; - private boolean enabled = true; - private final HandlerRegistration keyDownHandler; - - public MonthGrid(VCalendar parent, int rows, int columns) { - super(rows, columns); - calendar = parent; - setCellSpacing(0); - setCellPadding(0); - setStylePrimaryName("v-calendar-month"); - - keyDownHandler = addKeyDownHandler(this); - } - - @Override - protected void onUnload() { - keyDownHandler.removeHandler(); - super.onUnload(); - } - - public void setSelectionEnd(SimpleDayCell simpleDayCell) { - selectionEnd = simpleDayCell; - updateSelection(); - } - - public void setSelectionStart(SimpleDayCell simpleDayCell) { - if (!rangeSelectDisabled && isEnabled()) { - selectionStart = simpleDayCell; - setFocus(true); - } - - } - - private void updateSelection() { - if (selectionStart == null) { - return; - } - if (selectionStart != null && selectionEnd != null) { - Date startDate = selectionStart.getDate(); - Date endDate = selectionEnd.getDate(); - for (int row = 0; row < getRowCount(); row++) { - for (int cell = 0; cell < getCellCount(row); cell++) { - SimpleDayCell sdc = (SimpleDayCell) getWidget(row, cell); - if (sdc == null) { - return; - } - Date d = sdc.getDate(); - if (startDate.compareTo(d) <= 0 - && endDate.compareTo(d) >= 0) { - sdc.addStyleDependentName("selected"); - } else if (startDate.compareTo(d) >= 0 - && endDate.compareTo(d) <= 0) { - sdc.addStyleDependentName("selected"); - } else { - sdc.removeStyleDependentName("selected"); - } - } - } - } - } - - public void setSelectionReady() { - if (selectionStart != null && selectionEnd != null) { - String value = ""; - Date startDate = selectionStart.getDate(); - Date endDate = selectionEnd.getDate(); - if (startDate.compareTo(endDate) > 0) { - Date temp = startDate; - startDate = endDate; - endDate = temp; - } - - if (calendar.getRangeSelectListener() != null) { - value = calendar.getDateFormat().format(startDate) + "TO" - + calendar.getDateFormat().format(endDate); - calendar.getRangeSelectListener().rangeSelected(value); - } - selectionStart = null; - selectionEnd = null; - setFocus(false); - } - } - - public void cancelRangeSelection() { - if (selectionStart != null && selectionEnd != null) { - for (int row = 0; row < getRowCount(); row++) { - for (int cell = 0; cell < getCellCount(row); cell++) { - SimpleDayCell sdc = (SimpleDayCell) getWidget(row, cell); - if (sdc == null) { - return; - } - sdc.removeStyleDependentName("selected"); - } - } - } - setFocus(false); - selectionStart = null; - } - - public void updateCellSizes(int totalWidthPX, int totalHeightPX) { - boolean setHeight = totalHeightPX > 0; - boolean setWidth = totalWidthPX > 0; - int rows = getRowCount(); - int cells = getCellCount(0); - int cellWidth = (totalWidthPX / cells) - 1; - int widthRemainder = totalWidthPX % cells; - // Division for cells might not be even. Distribute it evenly to - // will whole space. - int heightPX = totalHeightPX; - int cellHeight = heightPX / rows; - int heightRemainder = heightPX % rows; - - for (int i = 0; i < rows; i++) { - for (int j = 0; j < cells; j++) { - SimpleDayCell sdc = (SimpleDayCell) getWidget(i, j); - - if (setWidth) { - if (widthRemainder > 0) { - sdc.setWidth(cellWidth + 1 + "px"); - widthRemainder--; - - } else { - sdc.setWidth(cellWidth + "px"); - } - } - - if (setHeight) { - if (heightRemainder > 0) { - sdc.setHeightPX(cellHeight + 1, true); - - } else { - sdc.setHeightPX(cellHeight, true); - } - } else { - sdc.setHeightPX(-1, true); - } - } - heightRemainder--; - } - } - - /** - * Disable or enable possibility to select ranges - */ - public void setRangeSelect(boolean b) { - rangeSelectDisabled = !b; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public boolean isEnabled() { - return enabled; - } - - @Override - public void onKeyDown(KeyDownEvent event) { - int keycode = event.getNativeKeyCode(); - if (KeyCodes.KEY_ESCAPE == keycode && selectionStart != null) { - cancelRangeSelection(); - } - } - - public int getDayCellIndex(SimpleDayCell dayCell) { - int rows = getRowCount(); - int cells = getCellCount(0); - for (int i = 0; i < rows; i++) { - for (int j = 0; j < cells; j++) { - SimpleDayCell sdc = (SimpleDayCell) getWidget(i, j); - if (dayCell == sdc) { - return i * cells + j; - } - } - } - - return -1; - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java deleted file mode 100644 index 45ae5ed8e5..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java +++ /dev/null @@ -1,736 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import java.util.Date; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.NativeEvent; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.MouseDownEvent; -import com.google.gwt.event.dom.client.MouseDownHandler; -import com.google.gwt.event.dom.client.MouseMoveEvent; -import com.google.gwt.event.dom.client.MouseMoveHandler; -import com.google.gwt.event.dom.client.MouseOverEvent; -import com.google.gwt.event.dom.client.MouseOverHandler; -import com.google.gwt.event.dom.client.MouseUpEvent; -import com.google.gwt.event.dom.client.MouseUpHandler; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.ui.FocusableFlowPanel; -import com.vaadin.client.ui.VCalendar; -import com.vaadin.shared.ui.calendar.DateConstants; - -/** - * A class representing a single cell within the calendar in month-view - * - * @since 7.1 - * @author Vaadin Ltd. - */ -public class SimpleDayCell extends FocusableFlowPanel implements MouseUpHandler, - MouseDownHandler, MouseOverHandler, MouseMoveHandler { - - private static int BOTTOMSPACERHEIGHT = -1; - private static int EVENTHEIGHT = -1; - private static final int BORDERPADDINGSIZE = 1; - - private final VCalendar calendar; - private Date date; - private int intHeight; - private final HTML bottomspacer; - private final Label caption; - private final CalendarEvent[] events = new CalendarEvent[10]; - private final int cell; - private final int row; - private boolean monthNameVisible; - private HandlerRegistration mouseUpRegistration; - private HandlerRegistration mouseDownRegistration; - private HandlerRegistration mouseOverRegistration; - private boolean monthEventMouseDown; - private boolean labelMouseDown; - private int eventCount = 0; - - private int startX = -1; - private int startY = -1; - private int startYrelative; - private int startXrelative; - // "from" date of date which is source of Dnd - private Date dndSourceDateFrom; - // "to" date of date which is source of Dnd - private Date dndSourceDateTo; - // "from" time of date which is source of Dnd - private Date dndSourceStartDateTime; - // "to" time of date which is source of Dnd - private Date dndSourceEndDateTime; - - private int prevDayDiff = 0; - private int prevWeekDiff = 0; - private HandlerRegistration moveRegistration; - private CalendarEvent moveEvent; - private Widget clickedWidget; - private HandlerRegistration bottomSpacerMouseDownHandler; - private boolean scrollable = false; - private MonthGrid monthGrid; - private HandlerRegistration keyDownHandler; - - public SimpleDayCell(VCalendar calendar, int row, int cell) { - this.calendar = calendar; - this.row = row; - this.cell = cell; - setStylePrimaryName("v-calendar-month-day"); - caption = new Label(); - bottomspacer = new HTML(); - bottomspacer.setStyleName("v-calendar-bottom-spacer-empty"); - bottomspacer.setWidth(3 + "em"); - caption.setStyleName("v-calendar-day-number"); - add(caption); - add(bottomspacer); - caption.addMouseDownHandler(this); - caption.addMouseUpHandler(this); - } - - @Override - public void onLoad() { - BOTTOMSPACERHEIGHT = bottomspacer.getOffsetHeight(); - EVENTHEIGHT = BOTTOMSPACERHEIGHT; - } - - public void setMonthGrid(MonthGrid monthGrid) { - this.monthGrid = monthGrid; - } - - public MonthGrid getMonthGrid() { - return monthGrid; - } - - @SuppressWarnings("deprecation") - public void setDate(Date date) { - int dateOfMonth = date.getDate(); - if (monthNameVisible) { - caption.setText(dateOfMonth + " " - + calendar.getMonthNames()[date.getMonth()]); - } else { - caption.setText("" + dateOfMonth); - } - this.date = date; - } - - public Date getDate() { - return date; - } - - public void reDraw(boolean clear) { - setHeightPX(intHeight + BORDERPADDINGSIZE, clear); - } - - /* - * Events and whole cell content are drawn by this method. By the - * clear-argument, you can choose to clear all old content. Notice that - * clearing will also remove all element's event handlers. - */ - public void setHeightPX(int px, boolean clear) { - // measure from DOM if needed - if (px < 0) { - intHeight = getOffsetHeight() - BORDERPADDINGSIZE; - } else { - intHeight = px - BORDERPADDINGSIZE; - } - - // Couldn't measure height or it ended up negative. Don't bother - // continuing - if (intHeight == -1) { - return; - } - - if (clear) { - while (getWidgetCount() > 1) { - remove(1); - } - } - - // How many events can be shown in UI - int slots = 0; - if (scrollable) { - for (int i = 0; i < events.length; i++) { - if (events[i] != null) { - slots = i + 1; - } - } - setHeight(intHeight + "px"); // Fixed height - } else { - // Dynamic height by the content - DOM.removeElementAttribute(getElement(), "height"); - slots = (intHeight - caption.getOffsetHeight() - BOTTOMSPACERHEIGHT) - / EVENTHEIGHT; - if (slots > 10) { - slots = 10; - } - } - - updateEvents(slots, clear); - - } - - public void updateEvents(int slots, boolean clear) { - int eventsAdded = 0; - - for (int i = 0; i < slots; i++) { - CalendarEvent e = events[i]; - if (e == null) { - // Empty slot - HTML slot = new HTML(); - slot.setStyleName("v-calendar-spacer"); - if (!clear) { - remove(i + 1); - insert(slot, i + 1); - } else { - add(slot); - } - } else { - // Event slot - eventsAdded++; - if (!clear) { - Widget w = getWidget(i + 1); - if (!(w instanceof MonthEventLabel)) { - remove(i + 1); - insert(createMonthEventLabel(e), i + 1); - } - } else { - add(createMonthEventLabel(e)); - } - } - } - - int remainingSpace = intHeight - ((slots * EVENTHEIGHT) - + BOTTOMSPACERHEIGHT + caption.getOffsetHeight()); - int newHeight = remainingSpace + BOTTOMSPACERHEIGHT; - if (newHeight < 0) { - newHeight = EVENTHEIGHT; - } - bottomspacer.setHeight(newHeight + "px"); - - if (clear) { - add(bottomspacer); - } - - int more = eventCount - eventsAdded; - if (more > 0) { - if (bottomSpacerMouseDownHandler == null) { - bottomSpacerMouseDownHandler = bottomspacer - .addMouseDownHandler(this); - } - bottomspacer.setStyleName("v-calendar-bottom-spacer"); - bottomspacer.setText("+ " + more); - } else { - if (!scrollable && bottomSpacerMouseDownHandler != null) { - bottomSpacerMouseDownHandler.removeHandler(); - bottomSpacerMouseDownHandler = null; - } - - if (scrollable) { - bottomspacer.setText("[ - ]"); - } else { - bottomspacer.setStyleName("v-calendar-bottom-spacer-empty"); - bottomspacer.setText(""); - } - } - } - - private MonthEventLabel createMonthEventLabel(CalendarEvent e) { - long rangeInMillis = e.getRangeInMilliseconds(); - boolean timeEvent = rangeInMillis <= DateConstants.DAYINMILLIS - && !e.isAllDay(); - Date fromDatetime = e.getStartTime(); - - // Create a new MonthEventLabel - MonthEventLabel eventDiv = new MonthEventLabel(); - eventDiv.addStyleDependentName("month"); - eventDiv.addMouseDownHandler(this); - eventDiv.addMouseUpHandler(this); - eventDiv.setCalendar(calendar); - eventDiv.setEventIndex(e.getIndex()); - eventDiv.setCalendarEvent(e); - - if (timeEvent) { - eventDiv.setTimeSpecificEvent(true); - if (e.getStyleName() != null) { - eventDiv.addStyleDependentName(e.getStyleName()); - } - eventDiv.setCaption(e.getCaption()); - eventDiv.setTime(fromDatetime); - - } else { - eventDiv.setTimeSpecificEvent(false); - Date from = e.getStart(); - Date to = e.getEnd(); - if (e.getStyleName().length() > 0) { - eventDiv.addStyleName("month-event " + e.getStyleName()); - } else { - eventDiv.addStyleName("month-event"); - } - int fromCompareToDate = from.compareTo(date); - int toCompareToDate = to.compareTo(date); - eventDiv.addStyleDependentName("all-day"); - if (fromCompareToDate == 0) { - eventDiv.addStyleDependentName("start"); - eventDiv.setCaption(e.getCaption()); - - } else if (fromCompareToDate < 0 && cell == 0) { - eventDiv.addStyleDependentName("continued-from"); - eventDiv.setCaption(e.getCaption()); - } - if (toCompareToDate == 0) { - eventDiv.addStyleDependentName("end"); - } else if (toCompareToDate > 0 - && (cell + 1) == getMonthGrid().getCellCount(row)) { - eventDiv.addStyleDependentName("continued-to"); - } - if (e.getStyleName() != null) { - eventDiv.addStyleDependentName(e.getStyleName() + "-all-day"); - } - } - - return eventDiv; - } - - private void setUnlimitedCellHeight() { - scrollable = true; - addStyleDependentName("scrollable"); - } - - private void setLimitedCellHeight() { - scrollable = false; - removeStyleDependentName("scrollable"); - } - - public void addCalendarEvent(CalendarEvent e) { - eventCount++; - int slot = e.getSlotIndex(); - if (slot == -1) { - for (int i = 0; i < events.length; i++) { - if (events[i] == null) { - events[i] = e; - e.setSlotIndex(i); - break; - } - } - } else { - events[slot] = e; - } - } - - @SuppressWarnings("deprecation") - public void setMonthNameVisible(boolean b) { - monthNameVisible = b; - int dateOfMonth = date.getDate(); - caption.setText( - dateOfMonth + " " + calendar.getMonthNames()[date.getMonth()]); - } - - public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) { - return addDomHandler(handler, MouseMoveEvent.getType()); - } - - @Override - protected void onAttach() { - super.onAttach(); - mouseUpRegistration = addDomHandler(this, MouseUpEvent.getType()); - mouseDownRegistration = addDomHandler(this, MouseDownEvent.getType()); - mouseOverRegistration = addDomHandler(this, MouseOverEvent.getType()); - } - - @Override - protected void onDetach() { - mouseUpRegistration.removeHandler(); - mouseDownRegistration.removeHandler(); - mouseOverRegistration.removeHandler(); - super.onDetach(); - } - - @Override - public void onMouseUp(MouseUpEvent event) { - if (event.getNativeButton() != NativeEvent.BUTTON_LEFT) { - return; - } - - Widget w = (Widget) event.getSource(); - if (moveRegistration != null) { - Event.releaseCapture(getElement()); - moveRegistration.removeHandler(); - moveRegistration = null; - keyDownHandler.removeHandler(); - keyDownHandler = null; - } - - if (w == bottomspacer && monthEventMouseDown) { - GWT.log("Mouse up over bottomspacer"); - - } else if (clickedWidget instanceof MonthEventLabel - && monthEventMouseDown) { - MonthEventLabel mel = (MonthEventLabel) clickedWidget; - - int endX = event.getClientX(); - int endY = event.getClientY(); - int xDiff = 0, yDiff = 0; - if (startX != -1 && startY != -1) { - xDiff = startX - endX; - yDiff = startY - endY; - } - startX = -1; - startY = -1; - prevDayDiff = 0; - prevWeekDiff = 0; - - if (xDiff < -3 || xDiff > 3 || yDiff < -3 || yDiff > 3) { - eventMoved(moveEvent); - - } else if (calendar.getEventClickListener() != null) { - CalendarEvent e = getEventByWidget(mel); - calendar.getEventClickListener().eventClick(e); - } - - moveEvent = null; - } else if (w == this) { - getMonthGrid().setSelectionReady(); - - } else if (w instanceof Label && labelMouseDown) { - String clickedDate = calendar.getDateFormat().format(date); - if (calendar.getDateClickListener() != null) { - calendar.getDateClickListener().dateClick(clickedDate); - } - } - monthEventMouseDown = false; - labelMouseDown = false; - clickedWidget = null; - } - - @Override - public void onMouseDown(MouseDownEvent event) { - if (calendar.isDisabled() - || event.getNativeButton() != NativeEvent.BUTTON_LEFT) { - return; - } - - Widget w = (Widget) event.getSource(); - clickedWidget = w; - - if (w instanceof MonthEventLabel) { - // event clicks should be allowed even when read-only - monthEventMouseDown = true; - - if (calendar.isEventMoveAllowed()) { - startCalendarEventDrag(event, (MonthEventLabel) w); - } - } else if (w == bottomspacer) { - if (scrollable) { - setLimitedCellHeight(); - } else { - setUnlimitedCellHeight(); - } - reDraw(true); - } else if (w instanceof Label) { - labelMouseDown = true; - } else if (w == this && !scrollable) { - MonthGrid grid = getMonthGrid(); - if (grid.isEnabled() && calendar.isRangeSelectAllowed()) { - grid.setSelectionStart(this); - grid.setSelectionEnd(this); - } - } - - event.stopPropagation(); - event.preventDefault(); - } - - @Override - public void onMouseOver(MouseOverEvent event) { - event.preventDefault(); - getMonthGrid().setSelectionEnd(this); - } - - @Override - public void onMouseMove(MouseMoveEvent event) { - if (clickedWidget instanceof MonthEventLabel && !monthEventMouseDown - || (startY < 0 && startX < 0)) { - return; - } - - MonthEventLabel w = (MonthEventLabel) clickedWidget; - - if (calendar.isDisabledOrReadOnly()) { - Event.releaseCapture(getElement()); - monthEventMouseDown = false; - startY = -1; - startX = -1; - return; - } - - int currentY = event.getClientY(); - int currentX = event.getClientX(); - int moveY = (currentY - startY); - int moveX = (currentX - startX); - if ((moveY < 5 && moveY > -6) && (moveX < 5 && moveX > -6)) { - return; - } - - int dateCellWidth = getWidth(); - int dateCellHeigth = getHeigth(); - - Element parent = getMonthGrid().getElement(); - int relativeX = event.getRelativeX(parent); - int relativeY = event.getRelativeY(parent); - int weekDiff = 0; - if (moveY > 0) { - weekDiff = (startYrelative + moveY) / dateCellHeigth; - } else { - weekDiff = (moveY - (dateCellHeigth - startYrelative)) - / dateCellHeigth; - } - - int dayDiff = 0; - if (moveX >= 0) { - dayDiff = (startXrelative + moveX) / dateCellWidth; - } else { - dayDiff = (moveX - (dateCellWidth - startXrelative)) - / dateCellWidth; - } - // Check boundaries - if (relativeY < 0 - || relativeY >= (calendar.getMonthGrid().getRowCount() - * dateCellHeigth) - || relativeX < 0 - || relativeX >= (calendar.getMonthGrid().getColumnCount() - * dateCellWidth)) { - return; - } - - GWT.log("Event moving delta: " + weekDiff + " weeks " + dayDiff - + " days" + " (" + getCell() + "," + getRow() + ")"); - - CalendarEvent e = moveEvent; - if (e == null) { - e = getEventByWidget(w); - } - - Date from = e.getStart(); - Date to = e.getEnd(); - - long daysMs = dayDiff * DateConstants.DAYINMILLIS; - long weeksMs = weekDiff * DateConstants.WEEKINMILLIS; - - setDates(e, from, to, weeksMs + daysMs, false); - e.setStart(from); - e.setEnd(to); - if (w.isTimeSpecificEvent()) { - Date start = new Date(); - Date end = new Date(); - setDates(e, start, end, weeksMs + daysMs, true); - e.setStartTime(start); - e.setEndTime(end); - } else { - e.setStartTime(new Date(from.getTime())); - e.setEndTime(new Date(to.getTime())); - } - - updateDragPosition(w, dayDiff, weekDiff); - } - - private void setDates(CalendarEvent e, Date start, Date end, long shift, - boolean isDateTime) { - Date currentStart; - Date currentEnd; - if (isDateTime) { - currentStart = e.getStartTime(); - currentEnd = e.getEndTime(); - } else { - currentStart = e.getStart(); - currentEnd = e.getEnd(); - } - long duration = currentEnd.getTime() - currentStart.getTime(); - if (isDateTime) { - start.setTime(dndSourceStartDateTime.getTime() + shift); - } else { - start.setTime(dndSourceDateFrom.getTime() + shift); - } - end.setTime((start.getTime() + duration)); - } - - private void eventMoved(CalendarEvent e) { - calendar.updateEventToMonthGrid(e); - if (calendar.getEventMovedListener() != null) { - calendar.getEventMovedListener().eventMoved(e); - } - } - - public void startCalendarEventDrag(MouseDownEvent event, - final MonthEventLabel w) { - moveRegistration = addMouseMoveHandler(this); - startX = event.getClientX(); - startY = event.getClientY(); - startYrelative = event.getRelativeY(w.getParent().getElement()) - % getHeigth(); - startXrelative = event.getRelativeX(w.getParent().getElement()) - % getWidth(); - - CalendarEvent e = getEventByWidget(w); - dndSourceDateFrom = (Date) e.getStart().clone(); - dndSourceDateTo = (Date) e.getEnd().clone(); - - dndSourceStartDateTime = (Date) e.getStartTime().clone(); - dndSourceEndDateTime = (Date) e.getEndTime().clone(); - - Event.setCapture(getElement()); - keyDownHandler = addKeyDownHandler(new KeyDownHandler() { - - @Override - public void onKeyDown(KeyDownEvent event) { - if (event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) { - cancelEventDrag(w); - } - } - - }); - - focus(); - - GWT.log("Start drag"); - } - - protected void cancelEventDrag(MonthEventLabel w) { - if (moveRegistration != null) { - // reset position - if (moveEvent == null) { - moveEvent = getEventByWidget(w); - } - - moveEvent.setStart(dndSourceDateFrom); - moveEvent.setEnd(dndSourceDateTo); - moveEvent.setStartTime(dndSourceStartDateTime); - moveEvent.setEndTime(dndSourceEndDateTime); - calendar.updateEventToMonthGrid(moveEvent); - - // reset drag-related properties - Event.releaseCapture(getElement()); - moveRegistration.removeHandler(); - moveRegistration = null; - keyDownHandler.removeHandler(); - keyDownHandler = null; - setFocus(false); - monthEventMouseDown = false; - startY = -1; - startX = -1; - moveEvent = null; - labelMouseDown = false; - clickedWidget = null; - } - } - - public void updateDragPosition(MonthEventLabel w, int dayDiff, - int weekDiff) { - // Draw event to its new position only when position has changed - if (dayDiff == prevDayDiff && weekDiff == prevWeekDiff) { - return; - } - - prevDayDiff = dayDiff; - prevWeekDiff = weekDiff; - - if (moveEvent == null) { - moveEvent = getEventByWidget(w); - } - - calendar.updateEventToMonthGrid(moveEvent); - } - - public int getRow() { - return row; - } - - public int getCell() { - return cell; - } - - public int getHeigth() { - return intHeight + BORDERPADDINGSIZE; - } - - public int getWidth() { - return getOffsetWidth() - BORDERPADDINGSIZE; - } - - public void setToday(boolean today) { - if (today) { - addStyleDependentName("today"); - } else { - removeStyleDependentName("today"); - } - } - - public boolean removeEvent(CalendarEvent targetEvent, - boolean reDrawImmediately) { - int slot = targetEvent.getSlotIndex(); - if (slot < 0) { - return false; - } - - CalendarEvent e = getCalendarEvent(slot); - if (targetEvent.equals(e)) { - events[slot] = null; - eventCount--; - if (reDrawImmediately) { - reDraw(moveEvent == null); - } - return true; - } - return false; - } - - private CalendarEvent getEventByWidget(MonthEventLabel eventWidget) { - int index = getWidgetIndex(eventWidget); - return getCalendarEvent(index - 1); - } - - public CalendarEvent getCalendarEvent(int i) { - return events[i]; - } - - public CalendarEvent[] getEvents() { - return events; - } - - public int getEventCount() { - return eventCount; - } - - public CalendarEvent getMoveEvent() { - return moveEvent; - } - - public void addEmphasisStyle() { - addStyleDependentName("dragemphasis"); - } - - public void removeEmphasisStyle() { - removeStyleDependentName("dragemphasis"); - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/SimpleDayToolbar.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/SimpleDayToolbar.java deleted file mode 100644 index e83a2cce3a..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/SimpleDayToolbar.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import com.google.gwt.user.client.ui.HorizontalPanel; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.Widget; - -/** - * - * @since 7.1.0 - * @author Vaadin Ltd. - * - */ -public class SimpleDayToolbar extends HorizontalPanel { - private int width = 0; - private boolean isWidthUndefined = false; - - public SimpleDayToolbar() { - setStylePrimaryName("v-calendar-header-month"); - } - - public void setDayNames(String[] dayNames) { - clear(); - for (int i = 0; i < dayNames.length; i++) { - Label l = new Label(dayNames[i]); - l.setStylePrimaryName("v-calendar-header-day"); - add(l); - } - updateCellWidth(); - } - - public void setWidthPX(int width) { - this.width = width; - - setWidthUndefined(width == -1); - - if (!isWidthUndefined()) { - super.setWidth(this.width + "px"); - if (getWidgetCount() == 0) { - return; - } - } - updateCellWidth(); - } - - private boolean isWidthUndefined() { - return isWidthUndefined; - } - - private void setWidthUndefined(boolean isWidthUndefined) { - this.isWidthUndefined = isWidthUndefined; - - if (isWidthUndefined) { - addStyleDependentName("Hsized"); - - } else { - removeStyleDependentName("Hsized"); - } - } - - private void updateCellWidth() { - int cellw = -1; - int widgetCount = getWidgetCount(); - if (widgetCount <= 0) { - return; - } - if (isWidthUndefined()) { - Widget widget = getWidget(0); - String w = widget.getElement().getStyle().getWidth(); - if (w.length() > 2) { - cellw = Integer.parseInt(w.substring(0, w.length() - 2)); - } - } else { - cellw = width / getWidgetCount(); - } - if (cellw > 0) { - for (int i = 0; i < getWidgetCount(); i++) { - Widget widget = getWidget(i); - setCellWidth(widget, cellw + "px"); - } - } - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/SimpleWeekToolbar.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/SimpleWeekToolbar.java deleted file mode 100644 index 30c52e1059..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/SimpleWeekToolbar.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.user.client.ui.FlexTable; -import com.vaadin.client.ui.VCalendar; - -/** - * - * @since 7.1 - * @author Vaadin Ltd. - * - */ -public class SimpleWeekToolbar extends FlexTable implements ClickHandler { - private int height; - private VCalendar calendar; - private boolean isHeightUndefined; - - public SimpleWeekToolbar(VCalendar parent) { - calendar = parent; - setCellSpacing(0); - setCellPadding(0); - setStyleName("v-calendar-week-numbers"); - } - - public void addWeek(int week, int year) { - WeekLabel l = new WeekLabel(week + "", week, year); - l.addClickHandler(this); - int rowCount = getRowCount(); - insertRow(rowCount); - setWidget(rowCount, 0, l); - updateCellHeights(); - } - - public void updateCellHeights() { - if (!isHeightUndefined()) { - int rowCount = getRowCount(); - if (rowCount == 0) { - return; - } - int cellheight = (height / rowCount) - 1; - int remainder = height % rowCount; - if (cellheight < 0) { - cellheight = 0; - } - for (int i = 0; i < rowCount; i++) { - if (remainder > 0) { - getWidget(i, 0).setHeight(cellheight + 1 + "px"); - } else { - getWidget(i, 0).setHeight(cellheight + "px"); - } - getWidget(i, 0).getElement().getStyle() - .setProperty("lineHeight", cellheight + "px"); - remainder--; - } - } else { - for (int i = 0; i < getRowCount(); i++) { - getWidget(i, 0).setHeight(""); - getWidget(i, 0).getElement().getStyle() - .setProperty("lineHeight", ""); - } - } - } - - public void setHeightPX(int intHeight) { - setHeightUndefined(intHeight == -1); - height = intHeight; - updateCellHeights(); - } - - public boolean isHeightUndefined() { - return isHeightUndefined; - } - - public void setHeightUndefined(boolean isHeightUndefined) { - this.isHeightUndefined = isHeightUndefined; - - if (isHeightUndefined) { - addStyleDependentName("Vsized"); - - } else { - removeStyleDependentName("Vsized"); - } - } - - @Override - public void onClick(ClickEvent event) { - WeekLabel wl = (WeekLabel) event.getSource(); - if (calendar.getWeekClickListener() != null) { - calendar.getWeekClickListener() - .weekClick(wl.getYear() + "w" + wl.getWeek()); - } - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/WeekGrid.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/WeekGrid.java deleted file mode 100644 index cfc9d6231a..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/WeekGrid.java +++ /dev/null @@ -1,692 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import java.util.Arrays; -import java.util.Date; - -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.Style; -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.event.dom.client.ScrollEvent; -import com.google.gwt.event.dom.client.ScrollHandler; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.HorizontalPanel; -import com.google.gwt.user.client.ui.Panel; -import com.google.gwt.user.client.ui.ScrollPanel; -import com.google.gwt.user.client.ui.SimplePanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.DateTimeService; -import com.vaadin.client.WidgetUtil; -import com.vaadin.client.ui.VCalendar; -import com.vaadin.shared.ui.calendar.DateConstants; - -/** - * - * @since 7.1 - * @author Vaadin Ltd. - * - */ -public class WeekGrid extends SimplePanel { - - int width = 0; - private int height = 0; - final HorizontalPanel content; - private VCalendar calendar; - private boolean disabled; - final Timebar timebar; - private Panel wrapper; - private boolean verticalScrollEnabled; - private boolean horizontalScrollEnabled; - private int[] cellHeights; - private final int slotInMinutes = 30; - private int dateCellBorder; - private DateCell dateCellOfToday; - private int[] cellWidths; - private int firstHour; - private int lastHour; - - public WeekGrid(VCalendar parent, boolean format24h) { - setCalendar(parent); - content = new HorizontalPanel(); - timebar = new Timebar(format24h); - content.add(timebar); - - wrapper = new SimplePanel(); - wrapper.setStylePrimaryName("v-calendar-week-wrapper"); - wrapper.add(content); - - setWidget(wrapper); - } - - private void setVerticalScroll(boolean isVerticalScrollEnabled) { - if (isVerticalScrollEnabled && !(isVerticalScrollable())) { - verticalScrollEnabled = true; - horizontalScrollEnabled = false; - wrapper.remove(content); - - final ScrollPanel scrollPanel = new ScrollPanel(); - scrollPanel.setStylePrimaryName("v-calendar-week-wrapper"); - scrollPanel.setWidget(content); - - scrollPanel.addScrollHandler(new ScrollHandler() { - @Override - public void onScroll(ScrollEvent event) { - if (calendar.getScrollListener() != null) { - calendar.getScrollListener().scroll( - scrollPanel.getVerticalScrollPosition()); - } - } - }); - - setWidget(scrollPanel); - wrapper = scrollPanel; - - } else if (!isVerticalScrollEnabled && (isVerticalScrollable())) { - verticalScrollEnabled = false; - horizontalScrollEnabled = false; - wrapper.remove(content); - - SimplePanel simplePanel = new SimplePanel(); - simplePanel.setStylePrimaryName("v-calendar-week-wrapper"); - simplePanel.setWidget(content); - - setWidget(simplePanel); - wrapper = simplePanel; - } - } - - public void setVerticalScrollPosition(int verticalScrollPosition) { - if (isVerticalScrollable()) { - ((ScrollPanel) wrapper) - .setVerticalScrollPosition(verticalScrollPosition); - } - } - - public int getInternalWidth() { - return width; - } - - public void addDate(Date d) { - final DateCell dc = new DateCell(this, d); - dc.setDisabled(isDisabled()); - dc.setHorizontalSized(isHorizontalScrollable() || width < 0); - dc.setVerticalSized(isVerticalScrollable()); - content.add(dc); - } - - /** - * @param dateCell - * @return get the index of the given date cell in this week, starting from - * 0 - */ - public int getDateCellIndex(DateCell dateCell) { - return content.getWidgetIndex(dateCell) - 1; - } - - /** - * @return get the slot border in pixels - */ - public int getDateSlotBorder() { - return ((DateCell) content.getWidget(1)).getSlotBorder(); - } - - private boolean isVerticalScrollable() { - return verticalScrollEnabled; - } - - private boolean isHorizontalScrollable() { - return horizontalScrollEnabled; - } - - public void setWidthPX(int width) { - if (isHorizontalScrollable()) { - updateCellWidths(); - - // Otherwise the scroll wrapper is somehow too narrow = horizontal - // scroll - wrapper.setWidth(content.getOffsetWidth() - + WidgetUtil.getNativeScrollbarSize() + "px"); - - this.width = content.getOffsetWidth() - timebar.getOffsetWidth(); - - } else { - this.width = (width == -1) ? width - : width - timebar.getOffsetWidth(); - - if (isVerticalScrollable() && width != -1) { - this.width = this.width - WidgetUtil.getNativeScrollbarSize(); - } - updateCellWidths(); - } - } - - public void setHeightPX(int intHeight) { - height = intHeight; - - setVerticalScroll(height <= -1); - - // if not scrollable, use any height given - if (!isVerticalScrollable() && height > 0) { - - content.setHeight(height + "px"); - setHeight(height + "px"); - wrapper.setHeight(height + "px"); - wrapper.removeStyleDependentName("Vsized"); - updateCellHeights(); - timebar.setCellHeights(cellHeights); - timebar.setHeightPX(height); - - } else if (isVerticalScrollable()) { - updateCellHeights(); - wrapper.addStyleDependentName("Vsized"); - timebar.setCellHeights(cellHeights); - timebar.setHeightPX(height); - } - } - - public void clearDates() { - while (content.getWidgetCount() > 1) { - content.remove(1); - } - - dateCellOfToday = null; - } - - /** - * @return true if this weekgrid contains a date that is today - */ - public boolean hasToday() { - return dateCellOfToday != null; - } - - public void updateCellWidths() { - if (!isHorizontalScrollable() && width != -1) { - int count = content.getWidgetCount(); - int datesWidth = width; - if (datesWidth > 0 && count > 1) { - cellWidths = VCalendar.distributeSize(datesWidth, count - 1, - -1); - - for (int i = 1; i < count; i++) { - DateCell dc = (DateCell) content.getWidget(i); - dc.setHorizontalSized( - isHorizontalScrollable() || width < 0); - dc.setWidthPX(cellWidths[i - 1]); - if (dc.isToday()) { - dc.setTimeBarWidth(getOffsetWidth()); - } - } - } - - } else { - int count = content.getWidgetCount(); - if (count > 1) { - for (int i = 1; i < count; i++) { - DateCell dc = (DateCell) content.getWidget(i); - dc.setHorizontalSized( - isHorizontalScrollable() || width < 0); - } - } - } - } - - /** - * @return an int-array containing the widths of the cells (days) - */ - public int[] getDateCellWidths() { - return cellWidths; - } - - public void updateCellHeights() { - if (!isVerticalScrollable()) { - int count = content.getWidgetCount(); - if (count > 1) { - DateCell first = (DateCell) content.getWidget(1); - dateCellBorder = first.getSlotBorder(); - cellHeights = VCalendar.distributeSize(height, - first.getNumberOfSlots(), -dateCellBorder); - for (int i = 1; i < count; i++) { - DateCell dc = (DateCell) content.getWidget(i); - dc.setHeightPX(height, cellHeights); - } - } - - } else { - int count = content.getWidgetCount(); - if (count > 1) { - DateCell first = (DateCell) content.getWidget(1); - dateCellBorder = first.getSlotBorder(); - int dateHeight = (first.getOffsetHeight() - / first.getNumberOfSlots()) - dateCellBorder; - cellHeights = new int[48]; - Arrays.fill(cellHeights, dateHeight); - - for (int i = 1; i < count; i++) { - DateCell dc = (DateCell) content.getWidget(i); - dc.setVerticalSized(isVerticalScrollable()); - } - } - } - } - - public void addEvent(CalendarEvent e) { - int dateCount = content.getWidgetCount(); - Date from = e.getStart(); - Date toTime = e.getEndTime(); - for (int i = 1; i < dateCount; i++) { - DateCell dc = (DateCell) content.getWidget(i); - Date dcDate = dc.getDate(); - int comp = dcDate.compareTo(from); - int comp2 = dcDate.compareTo(toTime); - if (comp >= 0 && comp2 < 0 || (comp == 0 && comp2 == 0 - && VCalendar.isZeroLengthMidnightEvent(e))) { - // Same event may be over two DateCells if event's date - // range floats over one day. It can't float over two days, - // because event which range is over 24 hours, will be handled - // as a "fullDay" event. - dc.addEvent(dcDate, e); - } - } - } - - public int getPixelLengthFor(int startFromMinutes, int durationInMinutes) { - int pixelLength = 0; - int currentSlot = 0; - - int firstHourInMinutes = firstHour * DateConstants.HOURINMINUTES; - int endHourInMinutes = lastHour * DateConstants.HOURINMINUTES; - - if (firstHourInMinutes > startFromMinutes) { - durationInMinutes = durationInMinutes - - (firstHourInMinutes - startFromMinutes); - startFromMinutes = 0; - } else { - startFromMinutes -= firstHourInMinutes; - } - - int shownHeightInMinutes = endHourInMinutes - firstHourInMinutes - + DateConstants.HOURINMINUTES; - - durationInMinutes = Math.min(durationInMinutes, - shownHeightInMinutes - startFromMinutes); - - // calculate full slots to event - int slotsTillEvent = startFromMinutes / slotInMinutes; - int startOverFlowTime = slotInMinutes - - (startFromMinutes % slotInMinutes); - if (startOverFlowTime == slotInMinutes) { - startOverFlowTime = 0; - currentSlot = slotsTillEvent; - } else { - currentSlot = slotsTillEvent + 1; - } - - int durationInSlots = 0; - int endOverFlowTime = 0; - - if (startOverFlowTime > 0) { - durationInSlots = (durationInMinutes - startOverFlowTime) - / slotInMinutes; - endOverFlowTime = (durationInMinutes - startOverFlowTime) - % slotInMinutes; - - } else { - durationInSlots = durationInMinutes / slotInMinutes; - endOverFlowTime = durationInMinutes % slotInMinutes; - } - - // calculate slot overflow at start - if (startOverFlowTime > 0 && currentSlot < cellHeights.length) { - int lastSlotHeight = cellHeights[currentSlot] + dateCellBorder; - pixelLength += (int) (((double) lastSlotHeight - / (double) slotInMinutes) * startOverFlowTime); - } - - // calculate length in full slots - int lastFullSlot = currentSlot + durationInSlots; - for (; currentSlot < lastFullSlot - && currentSlot < cellHeights.length; currentSlot++) { - pixelLength += cellHeights[currentSlot] + dateCellBorder; - } - - // calculate overflow at end - if (endOverFlowTime > 0 && currentSlot < cellHeights.length) { - int lastSlotHeight = cellHeights[currentSlot] + dateCellBorder; - pixelLength += (int) (((double) lastSlotHeight - / (double) slotInMinutes) * endOverFlowTime); - } - - // reduce possible underflow at end - if (endOverFlowTime < 0) { - int lastSlotHeight = cellHeights[currentSlot] + dateCellBorder; - pixelLength += (int) (((double) lastSlotHeight - / (double) slotInMinutes) * endOverFlowTime); - } - - return pixelLength; - } - - public int getPixelTopFor(int startFromMinutes) { - int pixelsToTop = 0; - int slotIndex = 0; - - int firstHourInMinutes = firstHour * 60; - - if (firstHourInMinutes > startFromMinutes) { - startFromMinutes = 0; - } else { - startFromMinutes -= firstHourInMinutes; - } - - // calculate full slots to event - int slotsTillEvent = startFromMinutes / slotInMinutes; - int overFlowTime = startFromMinutes % slotInMinutes; - if (slotsTillEvent > 0) { - for (slotIndex = 0; slotIndex < slotsTillEvent; slotIndex++) { - pixelsToTop += cellHeights[slotIndex] + dateCellBorder; - } - } - - // calculate lengths less than one slot - if (overFlowTime > 0) { - int lastSlotHeight = cellHeights[slotIndex] + dateCellBorder; - pixelsToTop += ((double) lastSlotHeight / (double) slotInMinutes) - * overFlowTime; - } - - return pixelsToTop; - } - - public void eventMoved(DateCellDayEvent dayEvent) { - Style s = dayEvent.getElement().getStyle(); - int left = Integer - .parseInt(s.getLeft().substring(0, s.getLeft().length() - 2)); - DateCell previousParent = (DateCell) dayEvent.getParent(); - DateCell newParent = (DateCell) content - .getWidget((left / getDateCellWidth()) + 1); - CalendarEvent se = dayEvent.getCalendarEvent(); - previousParent.removeEvent(dayEvent); - newParent.addEvent(dayEvent); - if (!previousParent.equals(newParent)) { - previousParent.recalculateEventWidths(); - } - newParent.recalculateEventWidths(); - if (calendar.getEventMovedListener() != null) { - calendar.getEventMovedListener().eventMoved(se); - } - } - - public void setToday(Date todayDate, Date todayTimestamp) { - int count = content.getWidgetCount(); - if (count > 1) { - for (int i = 1; i < count; i++) { - DateCell dc = (DateCell) content.getWidget(i); - if (dc.getDate().getTime() == todayDate.getTime()) { - if (isVerticalScrollable()) { - dc.setToday(todayTimestamp, -1); - } else { - dc.setToday(todayTimestamp, getOffsetWidth()); - } - } - dateCellOfToday = dc; - } - } - } - - public DateCell getDateCellOfToday() { - return dateCellOfToday; - } - - public void setDisabled(boolean disabled) { - this.disabled = disabled; - } - - public boolean isDisabled() { - return disabled; - } - - public Timebar getTimeBar() { - return timebar; - } - - public void setDateColor(Date when, Date to, String styleName) { - int dateCount = content.getWidgetCount(); - for (int i = 1; i < dateCount; i++) { - DateCell dc = (DateCell) content.getWidget(i); - Date dcDate = dc.getDate(); - int comp = dcDate.compareTo(when); - int comp2 = dcDate.compareTo(to); - if (comp >= 0 && comp2 <= 0) { - dc.setDateColor(styleName); - } - } - } - - /** - * @param calendar - * the calendar to set - */ - public void setCalendar(VCalendar calendar) { - this.calendar = calendar; - } - - /** - * @return the calendar - */ - public VCalendar getCalendar() { - return calendar; - } - - /** - * Get width of the single date cell - * - * @return Date cell width - */ - public int getDateCellWidth() { - int count = content.getWidgetCount() - 1; - int cellWidth = -1; - if (count <= 0) { - return cellWidth; - } - - if (width == -1) { - Widget firstWidget = content.getWidget(1); - cellWidth = firstWidget.getElement().getOffsetWidth(); - } else { - cellWidth = getInternalWidth() / count; - } - return cellWidth; - } - - /** - * @return the number of day cells in this week - */ - public int getDateCellCount() { - return content.getWidgetCount() - 1; - } - - public void setFirstHour(int firstHour) { - this.firstHour = firstHour; - timebar.setFirstHour(firstHour); - } - - public void setLastHour(int lastHour) { - this.lastHour = lastHour; - timebar.setLastHour(lastHour); - } - - public int getFirstHour() { - return firstHour; - } - - public int getLastHour() { - return lastHour; - } - - public static class Timebar extends HTML { - - private static final int[] timesFor12h = { 12, 1, 2, 3, 4, 5, 6, 7, 8, - 9, 10, 11 }; - - private int height; - - private final int verticalPadding = 7; // FIXME measure this from DOM - - private int[] slotCellHeights; - - private int firstHour; - - private int lastHour; - - public Timebar(boolean format24h) { - createTimeBar(format24h); - } - - public void setLastHour(int lastHour) { - this.lastHour = lastHour; - } - - public void setFirstHour(int firstHour) { - this.firstHour = firstHour; - - } - - public void setCellHeights(int[] cellHeights) { - slotCellHeights = cellHeights; - } - - private void createTimeBar(boolean format24h) { - setStylePrimaryName("v-calendar-times"); - - // Fist "time" is empty - Element e = DOM.createDiv(); - setStyleName(e, "v-calendar-time"); - e.setInnerText(""); - getElement().appendChild(e); - - DateTimeService dts = new DateTimeService(); - - if (format24h) { - for (int i = firstHour + 1; i <= lastHour; i++) { - e = DOM.createDiv(); - setStyleName(e, "v-calendar-time"); - String delimiter = dts.getClockDelimeter(); - e.setInnerHTML("<span>" + i + "</span>" + delimiter + "00"); - getElement().appendChild(e); - } - } else { - // FIXME Use dts.getAmPmStrings(); and make sure that - // DateTimeService has a some Locale set. - String[] ampm = new String[] { "AM", "PM" }; - - int amStop = (lastHour < 11) ? lastHour : 11; - int pmStart = (firstHour > 11) ? firstHour % 11 : 0; - - if (firstHour < 12) { - for (int i = firstHour + 1; i <= amStop; i++) { - e = DOM.createDiv(); - setStyleName(e, "v-calendar-time"); - e.setInnerHTML("<span>" + timesFor12h[i] + "</span>" - + " " + ampm[0]); - getElement().appendChild(e); - } - } - - if (lastHour > 11) { - for (int i = pmStart; i < lastHour - 11; i++) { - e = DOM.createDiv(); - setStyleName(e, "v-calendar-time"); - e.setInnerHTML("<span>" + timesFor12h[i] + "</span>" - + " " + ampm[1]); - getElement().appendChild(e); - } - } - } - } - - public void updateTimeBar(boolean format24h) { - clear(); - createTimeBar(format24h); - } - - private void clear() { - while (getElement().getChildCount() > 0) { - getElement().removeChild(getElement().getChild(0)); - } - } - - public void setHeightPX(int pixelHeight) { - height = pixelHeight; - - if (pixelHeight > -1) { - // as the negative margins on children pulls the whole element - // upwards, we must compensate. otherwise the element would be - // too short - super.setHeight((height + verticalPadding) + "px"); - removeStyleDependentName("Vsized"); - updateChildHeights(); - - } else { - addStyleDependentName("Vsized"); - updateChildHeights(); - } - } - - private void updateChildHeights() { - int childCount = getElement().getChildCount(); - - if (height != -1) { - - // 23 hours + first is empty - // we try to adjust the height of time labels to the distributed - // heights of the time slots - int hoursPerDay = lastHour - firstHour + 1; - - int slotsPerHour = slotCellHeights.length / hoursPerDay; - int[] cellHeights = new int[slotCellHeights.length - / slotsPerHour]; - - int slotHeightPosition = 0; - for (int i = 0; i < cellHeights.length; i++) { - for (int j = slotHeightPosition; j < slotHeightPosition - + slotsPerHour; j++) { - cellHeights[i] += slotCellHeights[j] + 1; - // 1px more for borders - // FIXME measure from DOM - } - slotHeightPosition += slotsPerHour; - } - - for (int i = 0; i < childCount; i++) { - Element e = (Element) getElement().getChild(i); - e.getStyle().setHeight(cellHeights[i], Unit.PX); - } - - } else { - for (int i = 0; i < childCount; i++) { - Element e = (Element) getElement().getChild(i); - e.getStyle().setProperty("height", ""); - } - } - } - } - - public VCalendar getParentCalendar() { - return calendar; - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/WeekGridMinuteTimeRange.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/WeekGridMinuteTimeRange.java deleted file mode 100644 index 984d3d48dc..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/WeekGridMinuteTimeRange.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import java.util.Date; - -/** - * Internally used by the calendar - * - * @since 7.1 - */ -public class WeekGridMinuteTimeRange { - private final Date start; - private final Date end; - - /** - * Creates a Date time range between start and end date. Drops seconds from - * the range. - * - * @param start - * Start time of the range - * @param end - * End time of the range - * @param clearSeconds - * Boolean Indicates, if seconds should be dropped from the range - * start and end - */ - public WeekGridMinuteTimeRange(Date start, Date end) { - this.start = new Date(start.getTime()); - this.end = new Date(end.getTime()); - this.start.setSeconds(0); - this.end.setSeconds(0); - } - - public Date getStart() { - return start; - } - - public Date getEnd() { - return end; - } - - public static boolean doesOverlap(WeekGridMinuteTimeRange a, - WeekGridMinuteTimeRange b) { - boolean overlaps = a.getStart().compareTo(b.getEnd()) < 0 - && a.getEnd().compareTo(b.getStart()) > 0; - return overlaps; - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/WeekLabel.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/WeekLabel.java deleted file mode 100644 index ae7001cb21..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/WeekLabel.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import com.google.gwt.user.client.ui.Label; - -/** - * A label in the {@link SimpleWeekToolbar} - * - * @since 7.1 - */ -public class WeekLabel extends Label { - private int week; - private int year; - - public WeekLabel(String string, int week2, int year2) { - super(string); - setStylePrimaryName("v-calendar-week-number"); - week = week2; - year = year2; - } - - public int getWeek() { - return week; - } - - public void setWeek(int week) { - this.week = week; - } - - public int getYear() { - return year; - } - - public void setYear(int year) { - this.year = year; - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/WeeklyLongEvents.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/WeeklyLongEvents.java deleted file mode 100644 index fe1f3e181e..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/WeeklyLongEvents.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import java.util.Date; -import java.util.List; - -import com.google.gwt.user.client.ui.HorizontalPanel; -import com.vaadin.client.ui.VCalendar; - -/** - * - * @since 7.1 - * @author Vaadin Ltd. - * - */ -public class WeeklyLongEvents extends HorizontalPanel implements HasTooltipKey { - - public static final int EVENT_HEIGTH = 15; - - public static final int EVENT_MARGIN = 1; - - private int rowCount = 0; - - private VCalendar calendar; - - private boolean undefinedWidth; - - public WeeklyLongEvents(VCalendar calendar) { - setStylePrimaryName("v-calendar-weekly-longevents"); - this.calendar = calendar; - } - - public void addDate(Date d) { - DateCellContainer dcc = new DateCellContainer(); - dcc.setDate(d); - dcc.setCalendar(calendar); - add(dcc); - } - - public void setWidthPX(int width) { - if (getWidgetCount() == 0) { - return; - } - undefinedWidth = (width < 0); - - updateCellWidths(); - } - - public void addEvents(List<CalendarEvent> events) { - for (CalendarEvent e : events) { - addEvent(e); - } - } - - public void addEvent(CalendarEvent calendarEvent) { - updateEventSlot(calendarEvent); - - int dateCount = getWidgetCount(); - Date from = calendarEvent.getStart(); - Date to = calendarEvent.getEnd(); - boolean started = false; - for (int i = 0; i < dateCount; i++) { - DateCellContainer dc = (DateCellContainer) getWidget(i); - Date dcDate = dc.getDate(); - int comp = dcDate.compareTo(from); - int comp2 = dcDate.compareTo(to); - WeeklyLongEventsDateCell eventLabel = dc - .getDateCell(calendarEvent.getSlotIndex()); - eventLabel.setStylePrimaryName("v-calendar-event"); - if (comp >= 0 && comp2 <= 0) { - eventLabel.setEvent(calendarEvent); - eventLabel.setCalendar(calendar); - - eventLabel.addStyleDependentName("all-day"); - if (comp == 0) { - eventLabel.addStyleDependentName("start"); - } - if (comp2 == 0) { - eventLabel.addStyleDependentName("end"); - } - if (!started && comp > 0 && comp2 <= 0) { - eventLabel.addStyleDependentName("continued-from"); - } else if (i == (dateCount - 1)) { - eventLabel.addStyleDependentName("continued-to"); - } - final String extraStyle = calendarEvent.getStyleName(); - if (extraStyle != null && extraStyle.length() > 0) { - eventLabel.addStyleDependentName(extraStyle + "-all-day"); - } - if (!started) { - if (calendar.isEventCaptionAsHtml()) { - eventLabel.setHTML(calendarEvent.getCaption()); - } else { - eventLabel.setText(calendarEvent.getCaption()); - } - started = true; - } - } - } - } - - private void updateEventSlot(CalendarEvent e) { - boolean foundFreeSlot = false; - int slot = 0; - while (!foundFreeSlot) { - if (isSlotFree(slot, e.getStart(), e.getEnd())) { - e.setSlotIndex(slot); - foundFreeSlot = true; - - } else { - slot++; - } - } - } - - private boolean isSlotFree(int slot, Date start, Date end) { - int dateCount = getWidgetCount(); - - // Go over all dates this week - for (int i = 0; i < dateCount; i++) { - DateCellContainer dc = (DateCellContainer) getWidget(i); - Date dcDate = dc.getDate(); - int comp = dcDate.compareTo(start); - int comp2 = dcDate.compareTo(end); - - // check if the date is in the range we need - if (comp >= 0 && comp2 <= 0) { - - // check if the slot is taken - if (dc.hasEvent(slot)) { - return false; - } - } - } - - return true; - } - - public int getRowCount() { - return rowCount; - } - - public void updateCellWidths() { - int cells = getWidgetCount(); - if (cells <= 0) { - return; - } - - int cellWidth = -1; - - // if width is undefined, use the width of the first cell - // otherwise use distributed sizes - if (undefinedWidth) { - cellWidth = calendar.getWeekGrid().getDateCellWidth() - - calendar.getWeekGrid().getDateSlotBorder(); - } - - for (int i = 0; i < cells; i++) { - DateCellContainer dc = (DateCellContainer) getWidget(i); - - if (undefinedWidth) { - dc.setWidth(cellWidth + "px"); - - } else { - dc.setWidth( - calendar.getWeekGrid().getDateCellWidths()[i] + "px"); - } - } - } - - @Override - public String getTooltipKey() { - return null; - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/WeeklyLongEventsDateCell.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/WeeklyLongEventsDateCell.java deleted file mode 100644 index a098ab9c1a..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/WeeklyLongEventsDateCell.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule; - -import java.util.Date; - -import com.google.gwt.user.client.ui.HTML; -import com.vaadin.client.ui.VCalendar; - -/** - * Represents a cell used in {@link WeeklyLongEvents} - * - * @since 7.1 - */ -public class WeeklyLongEventsDateCell extends HTML implements HasTooltipKey { - private Date date; - private CalendarEvent calendarEvent; - private VCalendar calendar; - - public WeeklyLongEventsDateCell() { - } - - public void setDate(Date date) { - this.date = date; - } - - public Date getDate() { - return date; - } - - public void setEvent(CalendarEvent event) { - calendarEvent = event; - } - - public CalendarEvent getEvent() { - return calendarEvent; - } - - public void setCalendar(VCalendar calendar) { - this.calendar = calendar; - } - - public VCalendar getCalendar() { - return calendar; - } - - @Override - public Object getTooltipKey() { - if (calendarEvent != null) { - return calendarEvent.getIndex(); - } - return null; - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/dd/CalendarDropHandler.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/dd/CalendarDropHandler.java deleted file mode 100644 index 58757b8552..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/dd/CalendarDropHandler.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule.dd; - -import com.vaadin.client.ApplicationConnection; -import com.vaadin.client.ui.calendar.CalendarConnector; -import com.vaadin.client.ui.dd.VAbstractDropHandler; - -/** - * Abstract base class for calendar drop handlers. - * - * @since 7.1 - * @author Vaadin Ltd. - * - */ -public abstract class CalendarDropHandler extends VAbstractDropHandler { - - protected final CalendarConnector calendarConnector; - - /** - * Constructor - * - * @param connector - * The connector of the calendar - */ - public CalendarDropHandler(CalendarConnector connector) { - calendarConnector = connector; - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler#getConnector() - */ - @Override - public CalendarConnector getConnector() { - return calendarConnector; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.ui.dd.VDropHandler# - * getApplicationConnection () - */ - @Override - public ApplicationConnection getApplicationConnection() { - return calendarConnector.getClient(); - } - -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/dd/CalendarMonthDropHandler.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/dd/CalendarMonthDropHandler.java deleted file mode 100644 index 663ee1eb98..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/dd/CalendarMonthDropHandler.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule.dd; - -import com.google.gwt.dom.client.Element; -import com.google.gwt.user.client.DOM; -import com.vaadin.client.WidgetUtil; -import com.vaadin.client.ui.calendar.CalendarConnector; -import com.vaadin.client.ui.calendar.schedule.SimpleDayCell; -import com.vaadin.client.ui.dd.VAcceptCallback; -import com.vaadin.client.ui.dd.VDragEvent; - -/** - * Handles DD when the monthly view is showing in the Calendar. In the monthly - * view, drops are only allowed in the the day cells. Only the day index is - * included in the drop details sent to the server. - * - * @since 7.1 - * @author Vaadin Ltd. - */ -public class CalendarMonthDropHandler extends CalendarDropHandler { - - public CalendarMonthDropHandler(CalendarConnector connector) { - super(connector); - } - - private Element currentTargetElement; - private SimpleDayCell currentTargetDay; - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler#dragAccepted - * (com.vaadin.terminal.gwt.client.ui.dd.VDragEvent) - */ - @Override - protected void dragAccepted(VDragEvent drag) { - deEmphasis(); - currentTargetElement = drag.getElementOver(); - currentTargetDay = WidgetUtil.findWidget(currentTargetElement, - SimpleDayCell.class); - emphasis(); - } - - /** - * Removed the emphasis CSS style name from the currently emphasized day - */ - private void deEmphasis() { - if (currentTargetElement != null && currentTargetDay != null) { - currentTargetDay.removeEmphasisStyle(); - currentTargetElement = null; - } - } - - /** - * Add CSS style name for the currently emphasized day - */ - private void emphasis() { - if (currentTargetElement != null && currentTargetDay != null) { - currentTargetDay.addEmphasisStyle(); - } - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler#dragOver(com - * .vaadin.terminal.gwt.client.ui.dd.VDragEvent) - */ - @Override - public void dragOver(final VDragEvent drag) { - if (isLocationValid(drag.getElementOver())) { - validate(new VAcceptCallback() { - @Override - public void accepted(VDragEvent event) { - dragAccepted(drag); - } - }, drag); - } - } - - /** - * Checks if the one can perform a drop in a element - * - * @param elementOver - * The element to check - * @return - */ - private boolean isLocationValid(Element elementOver) { - Element monthGridElement = calendarConnector.getWidget().getMonthGrid() - .getElement(); - - // drops are not allowed in: - // - weekday header - // - week number bart - return DOM.isOrHasChild(monthGridElement, elementOver); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler#dragEnter(com - * .vaadin.terminal.gwt.client.ui.dd.VDragEvent) - */ - @Override - public void dragEnter(VDragEvent drag) { - // NOOP, we determine drag acceptance in dragOver - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler#drop(com.vaadin - * .terminal.gwt.client.ui.dd.VDragEvent) - */ - @Override - public boolean drop(VDragEvent drag) { - if (isLocationValid(drag.getElementOver())) { - updateDropDetails(drag); - deEmphasis(); - return super.drop(drag); - - } else { - deEmphasis(); - return false; - } - } - - /** - * Updates the drop details sent to the server - * - * @param drag - * The drag event - */ - private void updateDropDetails(VDragEvent drag) { - int dayIndex = calendarConnector.getWidget().getMonthGrid() - .getDayCellIndex(currentTargetDay); - - drag.getDropDetails().put("dropDayIndex", dayIndex); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler#dragLeave(com - * .vaadin.terminal.gwt.client.ui.dd.VDragEvent) - */ - @Override - public void dragLeave(VDragEvent drag) { - deEmphasis(); - super.dragLeave(drag); - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/dd/CalendarWeekDropHandler.java b/client/src/main/java/com/vaadin/client/ui/calendar/schedule/dd/CalendarWeekDropHandler.java deleted file mode 100644 index c0ad635ef7..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/calendar/schedule/dd/CalendarWeekDropHandler.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2000-2016 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.calendar.schedule.dd; - -import com.google.gwt.dom.client.Element; -import com.google.gwt.user.client.DOM; -import com.vaadin.client.WidgetUtil; -import com.vaadin.client.ui.calendar.CalendarConnector; -import com.vaadin.client.ui.calendar.schedule.DateCell; -import com.vaadin.client.ui.calendar.schedule.DateCellDayEvent; -import com.vaadin.client.ui.dd.VAcceptCallback; -import com.vaadin.client.ui.dd.VDragEvent; - -/** - * Handles DD when the weekly view is showing in the Calendar. In the weekly - * view, drops are only allowed in the the time slots for each day. The slot - * index and the day index are included in the drop details sent to the server. - * - * @since 7.1 - * @author Vaadin Ltd. - */ -public class CalendarWeekDropHandler extends CalendarDropHandler { - - private Element currentTargetElement; - private DateCell currentTargetDay; - - public CalendarWeekDropHandler(CalendarConnector connector) { - super(connector); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler#dragAccepted - * (com.vaadin.terminal.gwt.client.ui.dd.VDragEvent) - */ - @Override - protected void dragAccepted(VDragEvent drag) { - deEmphasis(); - currentTargetElement = drag.getElementOver(); - currentTargetDay = WidgetUtil.findWidget(currentTargetElement, - DateCell.class); - emphasis(); - } - - /** - * Removes the CSS style name from the emphasized element - */ - private void deEmphasis() { - if (currentTargetElement != null) { - currentTargetDay.removeEmphasisStyle(currentTargetElement); - currentTargetElement = null; - } - } - - /** - * Add a CSS stylen name to current target element - */ - private void emphasis() { - currentTargetDay.addEmphasisStyle(currentTargetElement); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler#dragOver(com - * .vaadin.terminal.gwt.client.ui.dd.VDragEvent) - */ - @Override - public void dragOver(final VDragEvent drag) { - if (isLocationValid(drag.getElementOver())) { - validate(new VAcceptCallback() { - @Override - public void accepted(VDragEvent event) { - dragAccepted(drag); - } - }, drag); - } - } - - /** - * Checks if the location is a valid drop location - * - * @param elementOver - * The element to check - * @return - */ - private boolean isLocationValid(Element elementOver) { - Element weekGridElement = calendarConnector.getWidget().getWeekGrid() - .getElement(); - Element timeBarElement = calendarConnector.getWidget().getWeekGrid() - .getTimeBar().getElement(); - - Element todayBarElement = null; - if (calendarConnector.getWidget().getWeekGrid().hasToday()) { - todayBarElement = calendarConnector.getWidget().getWeekGrid() - .getDateCellOfToday().getTodaybarElement(); - } - - // drops are not allowed in: - // - weekday header - // - allday event list - // - todaybar - // - timebar - // - events - return DOM.isOrHasChild(weekGridElement, elementOver) - && !DOM.isOrHasChild(timeBarElement, elementOver) - && todayBarElement != elementOver - && (WidgetUtil.findWidget(elementOver, - DateCellDayEvent.class) == null); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler#dragEnter(com - * .vaadin.terminal.gwt.client.ui.dd.VDragEvent) - */ - @Override - public void dragEnter(VDragEvent drag) { - // NOOP, we determine drag acceptance in dragOver - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler#drop(com.vaadin - * .terminal.gwt.client.ui.dd.VDragEvent) - */ - @Override - public boolean drop(VDragEvent drag) { - if (isLocationValid(drag.getElementOver())) { - updateDropDetails(drag); - deEmphasis(); - return super.drop(drag); - - } else { - deEmphasis(); - return false; - } - } - - /** - * Update the drop details sent to the server - * - * @param drag - * The drag event - */ - private void updateDropDetails(VDragEvent drag) { - int slotIndex = currentTargetDay.getSlotIndex(currentTargetElement); - int dayIndex = calendarConnector.getWidget().getWeekGrid() - .getDateCellIndex(currentTargetDay); - - drag.getDropDetails().put("dropDayIndex", dayIndex); - drag.getDropDetails().put("dropSlotIndex", slotIndex); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler#dragLeave(com - * .vaadin.terminal.gwt.client.ui.dd.VDragEvent) - */ - @Override - public void dragLeave(VDragEvent drag) { - deEmphasis(); - super.dragLeave(drag); - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/colorpicker/AbstractColorPickerConnector.java b/client/src/main/java/com/vaadin/client/ui/colorpicker/AbstractColorPickerConnector.java deleted file mode 100644 index 6f480538e0..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/colorpicker/AbstractColorPickerConnector.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2000-2016 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.colorpicker; - -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.HasClickHandlers; -import com.vaadin.client.communication.StateChangeEvent; -import com.vaadin.client.ui.AbstractComponentConnector; -import com.vaadin.shared.ui.colorpicker.ColorPickerState; - -/** - * An abstract class that defines default implementation for a color picker - * connector. - * - * @since 7.0.0 - */ -public abstract class AbstractColorPickerConnector - extends AbstractComponentConnector implements ClickHandler { - - private static final String DEFAULT_WIDTH_STYLE = "v-default-caption-width"; - - @Override - public ColorPickerState getState() { - return (ColorPickerState) super.getState(); - } - - @Override - public boolean delegateCaptionHandling() { - return false; - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - // NOTE: this method is called after @DelegateToWidget - super.onStateChanged(stateChangeEvent); - if (stateChangeEvent.hasPropertyChanged("color")) { - refreshColor(); - - if (getState().showDefaultCaption && (getState().caption == null - || "".equals(getState().caption))) { - - setCaption(getState().color); - } - } - if (stateChangeEvent.hasPropertyChanged("caption") - || stateChangeEvent.hasPropertyChanged("htmlContentAllowed") - || stateChangeEvent.hasPropertyChanged("showDefaultCaption")) { - - setCaption(getCaption()); - refreshDefaultCaptionStyle(); - } - } - - @Override - public void init() { - super.init(); - if (getWidget() instanceof HasClickHandlers) { - ((HasClickHandlers) getWidget()).addClickHandler(this); - } - } - - /** - * Get caption for the color picker widget. - * - * @return - */ - protected String getCaption() { - if (getState().showDefaultCaption && (getState().caption == null - || "".equals(getState().caption))) { - return getState().color; - } - return getState().caption; - } - - /** - * Add/remove default caption style. - */ - protected void refreshDefaultCaptionStyle() { - if (getState().showDefaultCaption - && (getState().caption == null || getState().caption.isEmpty()) - && getState().width.isEmpty()) { - getWidget().addStyleName(DEFAULT_WIDTH_STYLE); - } else { - getWidget().removeStyleName(DEFAULT_WIDTH_STYLE); - } - } - - /** - * Set caption of the color picker widget. - * - * @param caption - */ - protected abstract void setCaption(String caption); - - /** - * Update the widget to show the currently selected color. - */ - protected abstract void refreshColor(); - -} diff --git a/client/src/main/java/com/vaadin/client/ui/colorpicker/ColorPickerAreaConnector.java b/client/src/main/java/com/vaadin/client/ui/colorpicker/ColorPickerAreaConnector.java deleted file mode 100644 index 828cc689c7..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/colorpicker/ColorPickerAreaConnector.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2000-2016 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.colorpicker; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.VCaption; -import com.vaadin.client.communication.RpcProxy; -import com.vaadin.client.ui.VColorPickerArea; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.shared.ui.colorpicker.ColorPickerServerRpc; -import com.vaadin.ui.ColorPickerArea; - -/** - * A class that defines an implementation for a color picker connector. Connects - * the server side {@link com.vaadin.ui.ColorPickerArea} with the client side - * counterpart {@link VColorPickerArea} - * - * @since 7.0.0 - */ -@Connect(value = ColorPickerArea.class, loadStyle = LoadStyle.LAZY) -public class ColorPickerAreaConnector extends AbstractColorPickerConnector { - - private ColorPickerServerRpc rpc = RpcProxy - .create(ColorPickerServerRpc.class, this); - - @Override - protected Widget createWidget() { - return GWT.create(VColorPickerArea.class); - } - - @Override - public VColorPickerArea getWidget() { - return (VColorPickerArea) super.getWidget(); - } - - @Override - public void onClick(ClickEvent event) { - rpc.openPopup(getWidget().isOpen()); - } - - @Override - protected void setCaption(String caption) { - VCaption.setCaptionText(getWidget(), getState()); - } - - @Override - protected void refreshColor() { - getWidget().refreshColor(); - } - -} diff --git a/client/src/main/java/com/vaadin/client/ui/colorpicker/ColorPickerConnector.java b/client/src/main/java/com/vaadin/client/ui/colorpicker/ColorPickerConnector.java deleted file mode 100644 index 6254e7adbe..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/colorpicker/ColorPickerConnector.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2000-2016 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.colorpicker; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.communication.RpcProxy; -import com.vaadin.client.ui.VColorPicker; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.shared.ui.colorpicker.ColorPickerServerRpc; -import com.vaadin.ui.ColorPicker; - -/** - * A class that defines default implementation for a color picker connector. - * Connects the server side {@link com.vaadin.ui.ColorPicker} with the client - * side counterpart {@link VColorPicker} - * - * @since 7.0.0 - */ -@Connect(value = ColorPicker.class, loadStyle = LoadStyle.LAZY) -public class ColorPickerConnector extends AbstractColorPickerConnector { - - private ColorPickerServerRpc rpc = RpcProxy - .create(ColorPickerServerRpc.class, this); - - @Override - protected Widget createWidget() { - return GWT.create(VColorPicker.class); - } - - @Override - public VColorPicker getWidget() { - return (VColorPicker) super.getWidget(); - } - - @Override - public void onClick(ClickEvent event) { - rpc.openPopup(getWidget().isOpen()); - } - - @Override - protected void setCaption(String caption) { - if (getState().captionAsHtml) { - getWidget().setHtml(caption); - } else { - getWidget().setText(caption); - } - } - - @Override - protected void refreshColor() { - getWidget().refreshColor(); - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/colorpicker/ColorPickerGradientConnector.java b/client/src/main/java/com/vaadin/client/ui/colorpicker/ColorPickerGradientConnector.java deleted file mode 100644 index c05449d7bd..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/colorpicker/ColorPickerGradientConnector.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2000-2016 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.colorpicker; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.event.dom.client.MouseUpEvent; -import com.google.gwt.event.dom.client.MouseUpHandler; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.communication.RpcProxy; -import com.vaadin.client.communication.StateChangeEvent; -import com.vaadin.client.ui.AbstractComponentConnector; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.shared.ui.colorpicker.ColorPickerGradientServerRpc; -import com.vaadin.shared.ui.colorpicker.ColorPickerGradientState; -import com.vaadin.ui.components.colorpicker.ColorPickerGradient; - -/** - * A class that defines the default implementation for a color picker gradient - * connector. Connects the server side - * {@link com.vaadin.ui.components.colorpicker.ColorPickerGradient} with the - * client side counterpart {@link VColorPickerGradient} - * - * @since 7.0.0 - */ -@Connect(value = ColorPickerGradient.class, loadStyle = LoadStyle.LAZY) -public class ColorPickerGradientConnector extends AbstractComponentConnector - implements MouseUpHandler { - - private ColorPickerGradientServerRpc rpc = RpcProxy - .create(ColorPickerGradientServerRpc.class, this); - - @Override - protected Widget createWidget() { - return GWT.create(VColorPickerGradient.class); - } - - @Override - public VColorPickerGradient getWidget() { - return (VColorPickerGradient) super.getWidget(); - } - - @Override - public ColorPickerGradientState getState() { - return (ColorPickerGradientState) super.getState(); - } - - @Override - public void onMouseUp(MouseUpEvent event) { - rpc.select(getWidget().getCursorX(), getWidget().getCursorY()); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - if (stateChangeEvent.hasPropertyChanged("cursorX") - || stateChangeEvent.hasPropertyChanged("cursorY")) { - - getWidget().setCursor(getState().cursorX, getState().cursorY); - } - if (stateChangeEvent.hasPropertyChanged("bgColor")) { - getWidget().setBGColor(getState().bgColor); - } - } - - @Override - protected void init() { - super.init(); - getWidget().addMouseUpHandler(this); - } - -} diff --git a/client/src/main/java/com/vaadin/client/ui/colorpicker/ColorPickerGridConnector.java b/client/src/main/java/com/vaadin/client/ui/colorpicker/ColorPickerGridConnector.java deleted file mode 100644 index cd0a3d1466..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/colorpicker/ColorPickerGridConnector.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2000-2016 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.colorpicker; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.communication.RpcProxy; -import com.vaadin.client.communication.StateChangeEvent; -import com.vaadin.client.ui.AbstractComponentConnector; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.shared.ui.colorpicker.ColorPickerGridServerRpc; -import com.vaadin.shared.ui.colorpicker.ColorPickerGridState; -import com.vaadin.ui.components.colorpicker.ColorPickerGrid; - -/** - * A class that defines the default implementation for a color picker grid - * connector. Connects the server side - * {@link com.vaadin.ui.components.colorpicker.ColorPickerGrid} with the client - * side counterpart {@link VColorPickerGrid} - * - * @since 7.0.0 - */ -@Connect(value = ColorPickerGrid.class, loadStyle = LoadStyle.LAZY) -public class ColorPickerGridConnector extends AbstractComponentConnector - implements ClickHandler { - - private ColorPickerGridServerRpc rpc = RpcProxy - .create(ColorPickerGridServerRpc.class, this); - - @Override - protected Widget createWidget() { - return GWT.create(VColorPickerGrid.class); - } - - @Override - public VColorPickerGrid getWidget() { - return (VColorPickerGrid) super.getWidget(); - } - - @Override - public ColorPickerGridState getState() { - return (ColorPickerGridState) super.getState(); - } - - @Override - public void onClick(ClickEvent event) { - rpc.select(getWidget().getSelectedX(), getWidget().getSelectedY()); - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - if (stateChangeEvent.hasPropertyChanged("rowCount") - || stateChangeEvent.hasPropertyChanged("columnCount") - || stateChangeEvent.hasPropertyChanged("updateGrid")) { - - getWidget().updateGrid(getState().rowCount, getState().columnCount); - } - if (stateChangeEvent.hasPropertyChanged("changedX") - || stateChangeEvent.hasPropertyChanged("changedY") - || stateChangeEvent.hasPropertyChanged("changedColor") - || stateChangeEvent.hasPropertyChanged("updateColor")) { - - getWidget().updateColor(getState().changedColor, - getState().changedX, getState().changedY); - - if (!getWidget().isGridLoaded()) { - rpc.refresh(); - } - } - } - - @Override - protected void init() { - super.init(); - getWidget().addClickHandler(this); - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/colorpicker/VColorPickerGradient.java b/client/src/main/java/com/vaadin/client/ui/colorpicker/VColorPickerGradient.java deleted file mode 100644 index b75bee23c1..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/colorpicker/VColorPickerGradient.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2000-2016 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.colorpicker; - -import com.google.gwt.dom.client.Style.Unit; -import com.google.gwt.event.dom.client.MouseDownEvent; -import com.google.gwt.event.dom.client.MouseDownHandler; -import com.google.gwt.event.dom.client.MouseMoveEvent; -import com.google.gwt.event.dom.client.MouseMoveHandler; -import com.google.gwt.event.dom.client.MouseUpEvent; -import com.google.gwt.event.dom.client.MouseUpHandler; -import com.google.gwt.user.client.ui.AbsolutePanel; -import com.google.gwt.user.client.ui.FocusPanel; -import com.google.gwt.user.client.ui.HTML; -import com.vaadin.client.ui.SubPartAware; - -/** - * Client side implementation for ColorPickerGradient. - * - * @since 7.0.0 - * - */ -public class VColorPickerGradient extends FocusPanel implements - MouseDownHandler, MouseUpHandler, MouseMoveHandler, SubPartAware { - - /** Set the CSS class name to allow styling. */ - public static final String CLASSNAME = "v-colorpicker-gradient"; - public static final String CLASSNAME_BACKGROUND = CLASSNAME + "-background"; - public static final String CLASSNAME_FOREGROUND = CLASSNAME + "-foreground"; - public static final String CLASSNAME_LOWERBOX = CLASSNAME + "-lowerbox"; - public static final String CLASSNAME_HIGHERBOX = CLASSNAME + "-higherbox"; - public static final String CLASSNAME_CONTAINER = CLASSNAME + "-container"; - public static final String CLASSNAME_CLICKLAYER = CLASSNAME + "-clicklayer"; - private static final String CLICKLAYER_ID = "clicklayer"; - - private final HTML background; - private final HTML foreground; - private final HTML lowercross; - private final HTML highercross; - private final HTML clicklayer; - private final AbsolutePanel container; - - private boolean mouseIsDown = false; - - private int cursorX; - private int cursorY; - - private int width = 220; - private int height = 220; - - /** - * Instantiates the client side component for a color picker gradient. - */ - public VColorPickerGradient() { - super(); - - setStyleName(CLASSNAME); - - background = new HTML(); - background.setStyleName(CLASSNAME_BACKGROUND); - background.setPixelSize(width, height); - - foreground = new HTML(); - foreground.setStyleName(CLASSNAME_FOREGROUND); - foreground.setPixelSize(width, height); - - clicklayer = new HTML(); - clicklayer.setStyleName(CLASSNAME_CLICKLAYER); - clicklayer.setPixelSize(width, height); - clicklayer.addMouseDownHandler(this); - clicklayer.addMouseUpHandler(this); - clicklayer.addMouseMoveHandler(this); - - lowercross = new HTML(); - lowercross.setPixelSize(width / 2, height / 2); - lowercross.setStyleName(CLASSNAME_LOWERBOX); - - highercross = new HTML(); - highercross.setPixelSize(width / 2, height / 2); - highercross.setStyleName(CLASSNAME_HIGHERBOX); - - container = new AbsolutePanel(); - container.setStyleName(CLASSNAME_CONTAINER); - container.setPixelSize(width, height); - container.add(background, 0, 0); - container.add(foreground, 0, 0); - container.add(lowercross, 0, height / 2); - container.add(highercross, width / 2, 0); - container.add(clicklayer, 0, 0); - - add(container); - } - - /** - * Returns the latest x-coordinate for pressed-down mouse cursor. - */ - protected int getCursorX() { - return cursorX; - } - - /** - * Returns the latest y-coordinate for pressed-down mouse cursor. - */ - protected int getCursorY() { - return cursorY; - } - - /** - * Sets the given css color as the background. - * - * @param bgColor - */ - protected void setBGColor(String bgColor) { - if (bgColor == null) { - background.getElement().getStyle().clearBackgroundColor(); - } else { - background.getElement().getStyle().setBackgroundColor(bgColor); - } - } - - @Override - public void onMouseDown(MouseDownEvent event) { - event.preventDefault(); - - mouseIsDown = true; - setCursor(event.getX(), event.getY()); - } - - @Override - public void onMouseUp(MouseUpEvent event) { - event.preventDefault(); - mouseIsDown = false; - setCursor(event.getX(), event.getY()); - - cursorX = event.getX(); - cursorY = event.getY(); - } - - @Override - public void onMouseMove(MouseMoveEvent event) { - event.preventDefault(); - - if (mouseIsDown) { - setCursor(event.getX(), event.getY()); - } - } - - /** - * Sets the latest coordinates for pressed-down mouse cursor and updates the - * cross elements. - * - * @param x - * @param y - */ - public void setCursor(int x, int y) { - cursorX = x; - cursorY = y; - if (x >= 0) { - lowercross.getElement().getStyle().setWidth(x, Unit.PX); - } - if (y >= 0) { - lowercross.getElement().getStyle().setTop(y, Unit.PX); - } - if (y >= 0) { - lowercross.getElement().getStyle().setHeight(height - y, Unit.PX); - } - - if (x >= 0) { - highercross.getElement().getStyle().setWidth(width - x, Unit.PX); - } - if (x >= 0) { - highercross.getElement().getStyle().setLeft(x, Unit.PX); - } - if (y >= 0) { - highercross.getElement().getStyle().setHeight(y, Unit.PX); - } - } - - @Override - public com.google.gwt.user.client.Element getSubPartElement( - String subPart) { - if (subPart.equals(CLICKLAYER_ID)) { - return clicklayer.getElement(); - } - - return null; - } - - @Override - public String getSubPartName( - com.google.gwt.user.client.Element subElement) { - if (clicklayer.getElement().isOrHasChild(subElement)) { - return CLICKLAYER_ID; - } - - return null; - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/colorpicker/VColorPickerGrid.java b/client/src/main/java/com/vaadin/client/ui/colorpicker/VColorPickerGrid.java deleted file mode 100644 index 67f2ce07dd..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/colorpicker/VColorPickerGrid.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2000-2016 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.colorpicker; - -import com.google.gwt.dom.client.Element; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.HasClickHandlers; -import com.google.gwt.event.shared.HandlerRegistration; -import com.google.gwt.user.client.ui.AbsolutePanel; -import com.google.gwt.user.client.ui.Grid; -import com.google.gwt.user.client.ui.HTMLTable.Cell; - -/** - * Client side implementation for ColorPickerGrid. - * - * @since 7.0.0 - * - */ -public class VColorPickerGrid extends AbsolutePanel - implements ClickHandler, HasClickHandlers { - - private int rows = 1; - private int columns = 1; - - private Grid grid; - - private boolean gridLoaded = false; - - private int selectedX; - private int selectedY; - - /** - * Instantiates the client side component for a color picker grid. - */ - public VColorPickerGrid() { - super(); - - this.add(createGrid(), 0, 0); - } - - /** - * Creates a grid according to the current row and column count information. - * - * @return grid - */ - private Grid createGrid() { - grid = new Grid(rows, columns); - grid.setWidth("100%"); - grid.setHeight("100%"); - grid.addClickHandler(this); - return grid; - } - - /** - * Updates the row and column count and creates a new grid based on them. - * The new grid replaces the old grid if one existed. - * - * @param rowCount - * @param columnCount - */ - protected void updateGrid(int rowCount, int columnCount) { - rows = rowCount; - columns = columnCount; - this.remove(grid); - this.add(createGrid(), 0, 0); - } - - /** - * Updates the changed colors within the grid based on the given x- and - * y-coordinates. Nothing happens if any of the parameters is null or the - * parameter lengths don't match. - * - * @param changedColor - * @param changedX - * @param changedY - */ - protected void updateColor(String[] changedColor, String[] changedX, - String[] changedY) { - if (changedColor != null && changedX != null && changedY != null) { - if (changedColor.length == changedX.length - && changedX.length == changedY.length) { - for (int c = 0; c < changedColor.length; c++) { - Element element = grid.getCellFormatter().getElement( - Integer.parseInt(changedX[c]), - Integer.parseInt(changedY[c])); - element.getStyle().setProperty("background", - changedColor[c]); - } - } - - gridLoaded = true; - } - } - - /** - * Returns currently selected x-coordinate of the grid. - */ - protected int getSelectedX() { - return selectedX; - } - - /** - * Returns currently selected y-coordinate of the grid. - */ - protected int getSelectedY() { - return selectedY; - } - - /** - * Returns true if the colors have been successfully updated at least once, - * false otherwise. - */ - protected boolean isGridLoaded() { - return gridLoaded; - } - - @Override - public void onClick(ClickEvent event) { - Cell cell = grid.getCellForEvent(event); - if (cell == null) { - return; - } - - selectedY = cell.getRowIndex(); - selectedX = cell.getCellIndex(); - } - - @Override - public HandlerRegistration addClickHandler(ClickHandler handler) { - return addDomHandler(handler, ClickEvent.getType()); - } - -} diff --git a/client/src/main/java/com/vaadin/client/ui/combobox/ComboBoxConnector.java b/client/src/main/java/com/vaadin/client/ui/combobox/ComboBoxConnector.java deleted file mode 100644 index f6dff893f5..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/combobox/ComboBoxConnector.java +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright 2000-2016 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.combobox; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import com.vaadin.client.ApplicationConnection; -import com.vaadin.client.Paintable; -import com.vaadin.client.Profiler; -import com.vaadin.client.UIDL; -import com.vaadin.client.communication.RpcProxy; -import com.vaadin.client.communication.StateChangeEvent; -import com.vaadin.client.ui.AbstractFieldConnector; -import com.vaadin.client.ui.SimpleManagedLayout; -import com.vaadin.client.ui.VFilterSelect; -import com.vaadin.client.ui.VFilterSelect.DataReceivedHandler; -import com.vaadin.client.ui.VFilterSelect.FilterSelectSuggestion; -import com.vaadin.shared.EventId; -import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.combobox.ComboBoxServerRpc; -import com.vaadin.shared.ui.combobox.ComboBoxState; -import com.vaadin.ui.ComboBox; - -@Connect(ComboBox.class) -public class ComboBoxConnector extends AbstractFieldConnector - implements Paintable, SimpleManagedLayout { - - protected ComboBoxServerRpc rpc = RpcProxy.create(ComboBoxServerRpc.class, - this); - - protected FocusAndBlurServerRpc focusAndBlurRpc = RpcProxy - .create(FocusAndBlurServerRpc.class, this); - - @Override - protected void init() { - super.init(); - getWidget().connector = this; - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - Profiler.enter("ComboBoxConnector.onStateChanged update content"); - - getWidget().readonly = isReadOnly(); - getWidget().updateReadOnly(); - - getWidget().setTextInputEnabled(getState().textInputAllowed); - - if (getState().inputPrompt != null) { - getWidget().inputPrompt = getState().inputPrompt; - } else { - getWidget().inputPrompt = ""; - } - - getWidget().pageLength = getState().pageLength; - - getWidget().filteringmode = getState().filteringMode; - - getWidget().suggestionPopupWidth = getState().suggestionPopupWidth; - - Profiler.leave("ComboBoxConnector.onStateChanged update content"); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.client.Paintable#updateFromUIDL(com.vaadin.client.UIDL, - * com.vaadin.client.ApplicationConnection) - */ - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (!isRealUpdate(uidl)) { - return; - } - - // not a FocusWidget -> needs own tabindex handling - getWidget().tb.setTabIndex(getState().tabIndex); - - getWidget().nullSelectionAllowed = uidl.hasAttribute("nullselect"); - - getWidget().nullSelectItem = uidl.hasAttribute("nullselectitem") - && uidl.getBooleanAttribute("nullselectitem"); - - getWidget().currentPage = uidl.getIntVariable("page"); - - getWidget().suggestionPopup.updateStyleNames(getState()); - - getWidget().allowNewItem = uidl.hasAttribute("allownewitem"); - getWidget().lastNewItemString = null; - - final UIDL options = uidl.getChildUIDL(0); - if (uidl.hasAttribute("totalMatches")) { - getWidget().totalMatches = uidl.getIntAttribute("totalMatches"); - } else { - getWidget().totalMatches = 0; - } - - List<FilterSelectSuggestion> newSuggestions = new ArrayList<FilterSelectSuggestion>(); - - for (final Iterator<?> i = options.getChildIterator(); i.hasNext();) { - final UIDL optionUidl = (UIDL) i.next(); - String key = optionUidl.getStringAttribute("key"); - String caption = optionUidl.getStringAttribute("caption"); - String style = optionUidl.getStringAttribute("style"); - - String untranslatedIconUri = null; - if (optionUidl.hasAttribute("icon")) { - untranslatedIconUri = optionUidl.getStringAttribute("icon"); - } - - final FilterSelectSuggestion suggestion = getWidget().new FilterSelectSuggestion( - key, caption, style, untranslatedIconUri); - newSuggestions.add(suggestion); - } - - // only close the popup if the suggestions list has actually changed - boolean suggestionsChanged = !getWidget().initDone - || !newSuggestions.equals(getWidget().currentSuggestions); - - // An ItemSetChangeEvent on server side clears the current suggestion - // popup. Popup needs to be repopulated with suggestions from UIDL. - boolean popupOpenAndCleared = false; - - // oldSuggestionTextMatchTheOldSelection is used to detect when it's - // safe to update textbox text by a changed item caption. - boolean oldSuggestionTextMatchesTheOldSelection = false; - - if (suggestionsChanged) { - oldSuggestionTextMatchesTheOldSelection = isWidgetsCurrentSelectionTextInTextBox(); - getWidget().currentSuggestions.clear(); - - if (!getDataReceivedHandler().isWaitingForFilteringResponse()) { - /* - * Clear the current suggestions as the server response always - * includes the new ones. Exception is when filtering, then we - * need to retain the value if the user does not select any of - * the options matching the filter. - */ - getWidget().currentSuggestion = null; - /* - * Also ensure no old items in menu. Unless cleared the old - * values may cause odd effects on blur events. Suggestions in - * menu might not necessary exist in select at all anymore. - */ - getWidget().suggestionPopup.menu.clearItems(); - popupOpenAndCleared = getWidget().suggestionPopup.isAttached(); - - } - - for (FilterSelectSuggestion suggestion : newSuggestions) { - getWidget().currentSuggestions.add(suggestion); - } - } - - // handle selection (null or a single value) - if (uidl.hasVariable("selected") - - // In case we're switching page no need to update the selection as the - // selection process didn't finish. - // && getWidget().selectPopupItemWhenResponseIsReceived == - // VFilterSelect.Select.NONE - // - ) { - - // single selected key (can be empty string) or empty array for null - // selection - String[] selectedKeys = uidl.getStringArrayVariable("selected"); - String selectedKey = null; - if (selectedKeys.length == 1) { - selectedKey = selectedKeys[0]; - } - // selected item caption in case it is not on the current page - String selectedCaption = null; - if (uidl.hasAttribute("selectedCaption")) { - selectedCaption = uidl.getStringAttribute("selectedCaption"); - } - - getDataReceivedHandler().updateSelectionFromServer(selectedKey, - selectedCaption, oldSuggestionTextMatchesTheOldSelection); - } - - // TODO even this condition should probably be moved to the handler - if ((getDataReceivedHandler().isWaitingForFilteringResponse() - && getWidget().lastFilter.toLowerCase() - .equals(uidl.getStringVariable("filter"))) - || popupOpenAndCleared) { - getDataReceivedHandler().dataReceived(); - } - - // Calculate minimum textarea width - getWidget().updateSuggestionPopupMinWidth(); - - /* - * if this is our first time we need to recalculate the root width. - */ - if (!getWidget().initDone) { - - getWidget().updateRootWidth(); - } - - // Focus dependent style names are lost during the update, so we add - // them here back again - if (getWidget().focused) { - getWidget().addStyleDependentName("focus"); - } - - getWidget().initDone = true; - - // TODO this should perhaps be moved to be a part of dataReceived() - getDataReceivedHandler().serverReplyHandled(); - } - - private boolean isWidgetsCurrentSelectionTextInTextBox() { - return getWidget().currentSuggestion != null - && getWidget().currentSuggestion.getReplacementString() - .equals(getWidget().tb.getText()); - } - - @Override - public VFilterSelect getWidget() { - return (VFilterSelect) super.getWidget(); - } - - private DataReceivedHandler getDataReceivedHandler() { - return getWidget().getDataReceivedHandler(); - } - - @Override - public ComboBoxState getState() { - return (ComboBoxState) super.getState(); - } - - @Override - public void layout() { - VFilterSelect widget = getWidget(); - if (widget.initDone) { - widget.updateRootWidth(); - } - } - - @Override - public void setWidgetEnabled(boolean widgetEnabled) { - super.setWidgetEnabled(widgetEnabled); - getWidget().enabled = widgetEnabled; - getWidget().tb.setEnabled(widgetEnabled); - } - - /* - * These methods exist to move communications out of VFilterSelect, and may - * be refactored/removed in the future - */ - - /** - * Send a message about a newly created item to the server. - * - * This method is for internal use only and may be removed in future - * versions. - * - * @since - * @param itemValue - * user entered string value for the new item - */ - public void sendNewItem(String itemValue) { - rpc.createNewItem(itemValue); - afterSendRequestToServer(); - } - - /** - * Send a message to the server to request the first page of items without - * filtering or selection. - * - * This method is for internal use only and may be removed in future - * versions. - * - * @since - */ - public void requestFirstPage() { - sendSelection(null); - requestPage("", 0); - } - - /** - * Send a message to the server to request a page of items with a given - * filter. - * - * This method is for internal use only and may be removed in future - * versions. - * - * @since - * @param filter - * the current filter string - * @param page - * the page number to get - */ - public void requestPage(String filter, int page) { - rpc.requestPage(filter, page); - afterSendRequestToServer(); - } - - /** - * Send a message to the server updating the current selection. - * - * This method is for internal use only and may be removed in future - * versions. - * - * @since - * @param selection - * the current selection - */ - public void sendSelection(String selection) { - rpc.setSelectedItem(selection); - afterSendRequestToServer(); - } - - /** - * Notify the server that the combo box received focus. - * - * For timing reasons, ConnectorFocusAndBlurHandler is not used at the - * moment. - * - * This method is for internal use only and may be removed in future - * versions. - * - * @since - */ - public void sendFocusEvent() { - boolean registeredListeners = hasEventListener(EventId.FOCUS); - if (registeredListeners) { - focusAndBlurRpc.focus(); - afterSendRequestToServer(); - } - } - - /** - * Notify the server that the combo box lost focus. - * - * For timing reasons, ConnectorFocusAndBlurHandler is not used at the - * moment. - * - * This method is for internal use only and may be removed in future - * versions. - * - * @since - */ - public void sendBlurEvent() { - boolean registeredListeners = hasEventListener(EventId.BLUR); - if (registeredListeners) { - focusAndBlurRpc.blur(); - afterSendRequestToServer(); - } - } - - /* - * Called after any request to server. - */ - private void afterSendRequestToServer() { - getDataReceivedHandler().anyRequestSentToServer(); - } - -} diff --git a/client/src/main/java/com/vaadin/client/ui/dd/VIsOverId.java b/client/src/main/java/com/vaadin/client/ui/dd/VIsOverId.java deleted file mode 100644 index b02f8df147..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/dd/VIsOverId.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2000-2016 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.dd; - -import com.vaadin.client.ComponentConnector; -import com.vaadin.client.UIDL; -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.ui.AbstractSelect; - -@AcceptCriterion(AbstractSelect.TargetItemIs.class) -final public class VIsOverId extends VAcceptCriterion { - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - try { - - String pid = configuration.getStringAttribute("s"); - VDropHandler currentDropHandler = VDragAndDropManager.get() - .getCurrentDropHandler(); - ComponentConnector dropHandlerConnector = currentDropHandler - .getConnector(); - - String pid2 = dropHandlerConnector.getConnectorId(); - if (pid2.equals(pid)) { - Object searchedId = drag.getDropDetails().get("itemIdOver"); - String[] stringArrayAttribute = configuration - .getStringArrayAttribute("keys"); - for (String string : stringArrayAttribute) { - if (string.equals(searchedId)) { - return true; - } - } - } - } catch (Exception e) { - } - return false; - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/dd/VItemIdIs.java b/client/src/main/java/com/vaadin/client/ui/dd/VItemIdIs.java deleted file mode 100644 index 6992ebcaad..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/dd/VItemIdIs.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2000-2016 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.dd; - -import com.vaadin.client.ComponentConnector; -import com.vaadin.client.UIDL; -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.ui.AbstractSelect; - -@AcceptCriterion(AbstractSelect.AcceptItem.class) -final public class VItemIdIs extends VAcceptCriterion { - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - try { - String pid = configuration.getStringAttribute("s"); - ComponentConnector dragSource = drag.getTransferable() - .getDragSource(); - String pid2 = dragSource.getConnectorId(); - if (pid2.equals(pid)) { - Object searchedId = drag.getTransferable().getData("itemId"); - String[] stringArrayAttribute = configuration - .getStringArrayAttribute("keys"); - for (String string : stringArrayAttribute) { - if (string.equals(searchedId)) { - return true; - } - } - } - } catch (Exception e) { - } - return false; - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/tree/TreeConnector.java b/client/src/main/java/com/vaadin/client/ui/tree/TreeConnector.java deleted file mode 100644 index c28a58aaad..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/tree/TreeConnector.java +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright 2000-2016 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.tree; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -import com.google.gwt.aria.client.Roles; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.EventTarget; -import com.vaadin.client.ApplicationConnection; -import com.vaadin.client.BrowserInfo; -import com.vaadin.client.Paintable; -import com.vaadin.client.TooltipInfo; -import com.vaadin.client.UIDL; -import com.vaadin.client.VConsole; -import com.vaadin.client.WidgetUtil; -import com.vaadin.client.communication.StateChangeEvent; -import com.vaadin.client.ui.AbstractComponentConnector; -import com.vaadin.client.ui.VTree; -import com.vaadin.client.ui.VTree.TreeNode; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.MultiSelectMode; -import com.vaadin.shared.ui.tree.TreeConstants; -import com.vaadin.shared.ui.tree.TreeServerRpc; -import com.vaadin.shared.ui.tree.TreeState; -import com.vaadin.ui.Tree; - -@Connect(Tree.class) -public class TreeConnector extends AbstractComponentConnector - implements Paintable { - - protected final Map<TreeNode, TooltipInfo> tooltipMap = new HashMap<TreeNode, TooltipInfo>(); - - @Override - protected void init() { - getWidget().connector = this; - } - - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (!isRealUpdate(uidl)) { - return; - } - - getWidget().rendering = true; - - getWidget().client = client; - - if (uidl.hasAttribute("partialUpdate")) { - handleUpdate(uidl); - - getWidget().rendering = false; - return; - } - - getWidget().paintableId = uidl.getId(); - - getWidget().immediate = getState().immediate; - - getWidget().disabled = !isEnabled(); - getWidget().readonly = isReadOnly(); - - getWidget().dragMode = uidl.hasAttribute("dragMode") - ? uidl.getIntAttribute("dragMode") : 0; - - getWidget().isNullSelectionAllowed = uidl - .getBooleanAttribute("nullselect"); - getWidget().isHtmlContentAllowed = uidl - .getBooleanAttribute(TreeConstants.ATTRIBUTE_HTML_ALLOWED); - - if (uidl.hasAttribute("alb")) { - getWidget().bodyActionKeys = uidl.getStringArrayAttribute("alb"); - } - - getWidget().body.clear(); - // clear out any references to nodes that no longer are attached - getWidget().clearNodeToKeyMap(); - tooltipMap.clear(); - - TreeNode childTree = null; - UIDL childUidl = null; - for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) { - childUidl = (UIDL) i.next(); - if ("actions".equals(childUidl.getTag())) { - updateActionMap(childUidl); - continue; - } else if ("-ac".equals(childUidl.getTag())) { - getWidget().updateDropHandler(childUidl); - continue; - } - childTree = getWidget().new TreeNode(); - getConnection().getVTooltip().connectHandlersToWidget(childTree); - updateNodeFromUIDL(childTree, childUidl, 1); - getWidget().body.add(childTree); - childTree.addStyleDependentName("root"); - childTree.childNodeContainer.addStyleDependentName("root"); - } - if (childTree != null && childUidl != null) { - boolean leaf = !childUidl.getTag().equals("node"); - childTree.addStyleDependentName(leaf ? "leaf-last" : "last"); - childTree.childNodeContainer.addStyleDependentName("last"); - } - final String selectMode = uidl.getStringAttribute("selectmode"); - getWidget().selectable = !"none".equals(selectMode); - getWidget().isMultiselect = "multi".equals(selectMode); - - if (getWidget().isMultiselect) { - Roles.getTreeRole().setAriaMultiselectableProperty( - getWidget().getElement(), true); - - if (BrowserInfo.get().isTouchDevice()) { - // Always use the simple mode for touch devices that do not have - // shift/ctrl keys (#8595) - getWidget().multiSelectMode = MultiSelectMode.SIMPLE; - } else { - getWidget().multiSelectMode = MultiSelectMode - .valueOf(uidl.getStringAttribute("multiselectmode")); - } - } else { - Roles.getTreeRole().setAriaMultiselectableProperty( - getWidget().getElement(), false); - } - - getWidget().selectedIds = uidl.getStringArrayVariableAsSet("selected"); - - // Update lastSelection and focusedNode to point to *actual* nodes again - // after the old ones have been cleared from the body. This fixes focus - // and keyboard navigation issues as described in #7057 and other - // tickets. - if (getWidget().lastSelection != null) { - getWidget().lastSelection = getWidget() - .getNodeByKey(getWidget().lastSelection.key); - } - - if (getWidget().focusedNode != null) { - - Set<String> selectedIds = getWidget().selectedIds; - - // If the focused node is not between the selected nodes, we need to - // refresh the focused node to prevent an undesired scroll. #12618. - if (!selectedIds.isEmpty() - && !selectedIds.contains(getWidget().focusedNode.key)) { - String keySelectedId = selectedIds.iterator().next(); - - TreeNode nodeToSelect = getWidget().getNodeByKey(keySelectedId); - - getWidget().setFocusedNode(nodeToSelect); - } else { - getWidget().setFocusedNode( - getWidget().getNodeByKey(getWidget().focusedNode.key)); - } - } - - if (getWidget().lastSelection == null && getWidget().focusedNode == null - && !getWidget().selectedIds.isEmpty()) { - getWidget().setFocusedNode(getWidget() - .getNodeByKey(getWidget().selectedIds.iterator().next())); - getWidget().focusedNode.setFocused(false); - } - - getWidget().rendering = false; - - } - - @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - // VTree does not implement Focusable - getWidget().setTabIndex(getState().tabIndex); - } - - @Override - public VTree getWidget() { - return (VTree) super.getWidget(); - } - - private void handleUpdate(UIDL uidl) { - final TreeNode rootNode = getWidget() - .getNodeByKey(uidl.getStringAttribute("rootKey")); - if (rootNode != null) { - if (!rootNode.getState()) { - // expanding node happened server side - rootNode.setState(true, false); - } - String levelPropertyString = Roles.getTreeitemRole() - .getAriaLevelProperty(rootNode.getElement()); - int levelProperty; - try { - levelProperty = Integer.valueOf(levelPropertyString); - } catch (NumberFormatException e) { - levelProperty = 1; - VConsole.error(e); - } - - renderChildNodes(rootNode, (Iterator) uidl.getChildIterator(), - levelProperty + 1); - } - } - - /** - * Registers action for the root and also for individual nodes - * - * @param uidl - */ - private void updateActionMap(UIDL uidl) { - final Iterator<?> it = uidl.getChildIterator(); - while (it.hasNext()) { - final UIDL action = (UIDL) it.next(); - final String key = action.getStringAttribute("key"); - final String caption = action - .getStringAttribute(TreeConstants.ATTRIBUTE_ACTION_CAPTION); - String iconUrl = null; - if (action.hasAttribute(TreeConstants.ATTRIBUTE_ACTION_ICON)) { - iconUrl = getConnection() - .translateVaadinUri(action.getStringAttribute( - TreeConstants.ATTRIBUTE_ACTION_ICON)); - } - getWidget().registerAction(key, caption, iconUrl); - } - - } - - public void updateNodeFromUIDL(TreeNode treeNode, UIDL uidl, int level) { - Roles.getTreeitemRole().setAriaLevelProperty(treeNode.getElement(), - level); - - String nodeKey = uidl.getStringAttribute("key"); - String caption = uidl - .getStringAttribute(TreeConstants.ATTRIBUTE_NODE_CAPTION); - if (getWidget().isHtmlContentAllowed) { - treeNode.setHtml(caption); - } else { - treeNode.setText(caption); - } - treeNode.key = nodeKey; - - getWidget().registerNode(treeNode); - - if (uidl.hasAttribute("al")) { - treeNode.actionKeys = uidl.getStringArrayAttribute("al"); - } - - if (uidl.getTag().equals("node")) { - if (uidl.getChildCount() == 0) { - treeNode.childNodeContainer.setVisible(false); - } else { - renderChildNodes(treeNode, (Iterator) uidl.getChildIterator(), - level + 1); - treeNode.childrenLoaded = true; - } - } else { - treeNode.addStyleName(TreeNode.CLASSNAME + "-leaf"); - } - if (uidl.hasAttribute(TreeConstants.ATTRIBUTE_NODE_STYLE)) { - treeNode.setNodeStyleName(uidl - .getStringAttribute(TreeConstants.ATTRIBUTE_NODE_STYLE)); - } - - String description = uidl.getStringAttribute("descr"); - if (description != null) { - tooltipMap.put(treeNode, - new TooltipInfo(description, null, treeNode)); - } - - if (uidl.getBooleanAttribute("expanded") && !treeNode.getState()) { - treeNode.setState(true, false); - } - - if (uidl.getBooleanAttribute("selected")) { - treeNode.setSelected(true); - // ensure that identifier is in selectedIds array (this may be a - // partial update) - getWidget().selectedIds.add(nodeKey); - } - - String iconUrl = uidl - .getStringAttribute(TreeConstants.ATTRIBUTE_NODE_ICON); - String iconAltText = uidl - .getStringAttribute(TreeConstants.ATTRIBUTE_NODE_ICON_ALT); - treeNode.setIcon(iconUrl, iconAltText); - } - - void renderChildNodes(TreeNode containerNode, Iterator<UIDL> i, int level) { - containerNode.childNodeContainer.clear(); - containerNode.childNodeContainer.setVisible(true); - while (i.hasNext()) { - final UIDL childUidl = i.next(); - // actions are in bit weird place, don't mix them with children, - // but current node's actions - if ("actions".equals(childUidl.getTag())) { - updateActionMap(childUidl); - continue; - } - final TreeNode childTree = getWidget().new TreeNode(); - getConnection().getVTooltip().connectHandlersToWidget(childTree); - updateNodeFromUIDL(childTree, childUidl, level); - containerNode.childNodeContainer.add(childTree); - if (!i.hasNext()) { - childTree.addStyleDependentName( - childTree.isLeaf() ? "leaf-last" : "last"); - childTree.childNodeContainer.addStyleDependentName("last"); - } - } - containerNode.childrenLoaded = true; - } - - @Override - public boolean isReadOnly() { - return super.isReadOnly() || getState().propertyReadOnly; - } - - @Override - public TreeState getState() { - return (TreeState) super.getState(); - } - - @Override - public TooltipInfo getTooltipInfo(Element element) { - - TooltipInfo info = null; - - // Try to find a tooltip for a node - if (element != getWidget().getElement()) { - Object node = WidgetUtil.findWidget(element, TreeNode.class); - - if (node != null) { - TreeNode tnode = (TreeNode) node; - if (tnode.isCaptionElement(element)) { - info = tooltipMap.get(tnode); - } - } - } - - // If no tooltip found for the node or if the target was not a node, use - // the default tooltip - if (info == null) { - info = super.getTooltipInfo(element); - } - - return info; - } - - @Override - public boolean hasTooltip() { - /* - * Item tooltips are not processed until updateFromUIDL, so we can't be - * sure that there are no tooltips during onStateChange when this method - * is used. - */ - return true; - } - - @Override - protected void sendContextClickEvent(MouseEventDetails details, - EventTarget eventTarget) { - if (!Element.is(eventTarget)) { - return; - } - - Element e = Element.as(eventTarget); - String key = null; - - if (getWidget().body.getElement().isOrHasChild(e)) { - TreeNode t = WidgetUtil.findWidget(e, TreeNode.class); - if (t != null) { - key = t.key; - } - } - - getRpcProxy(TreeServerRpc.class).contextClick(key, details); - - WidgetUtil.clearTextSelection(); - } -} - diff --git a/client/src/main/java/com/vaadin/client/ui/tree/VTargetInSubtree.java b/client/src/main/java/com/vaadin/client/ui/tree/VTargetInSubtree.java deleted file mode 100644 index 34b8428582..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/tree/VTargetInSubtree.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2000-2016 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.tree; - -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.UIDL; -import com.vaadin.client.ui.VTree; -import com.vaadin.client.ui.VTree.TreeNode; -import com.vaadin.client.ui.dd.VAcceptCriterion; -import com.vaadin.client.ui.dd.VDragAndDropManager; -import com.vaadin.client.ui.dd.VDragEvent; -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.ui.Tree; - -@AcceptCriterion(Tree.TargetInSubtree.class) -final public class VTargetInSubtree extends VAcceptCriterion { - - @Override - protected boolean accept(VDragEvent drag, UIDL configuration) { - - VTree tree = (VTree) VDragAndDropManager.get().getCurrentDropHandler() - .getConnector().getWidget(); - TreeNode treeNode = tree - .getNodeByKey((String) drag.getDropDetails().get("itemIdOver")); - if (treeNode != null) { - Widget parent2 = treeNode; - int depth = configuration.getIntAttribute("depth"); - if (depth < 0) { - depth = Integer.MAX_VALUE; - } - final String searchedKey = configuration.getStringAttribute("key"); - for (int i = 0; i <= depth && parent2 instanceof TreeNode; i++) { - if (searchedKey.equals(((TreeNode) parent2).key)) { - return true; - } - // panel -> next level node - parent2 = parent2.getParent().getParent(); - } - } - - return false; - } -} diff --git a/client/src/main/java/com/vaadin/client/ui/tree/VTreeLazyInitItemIdentifiers.java b/client/src/main/java/com/vaadin/client/ui/tree/VTreeLazyInitItemIdentifiers.java deleted file mode 100644 index 46089af16e..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/tree/VTreeLazyInitItemIdentifiers.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2000-2016 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.tree; - -import com.vaadin.client.ui.dd.VLazyInitItemIdentifiers; -import com.vaadin.shared.ui.dd.AcceptCriterion; -import com.vaadin.ui.Tree; - -@AcceptCriterion(Tree.TreeDropCriterion.class) -public final class VTreeLazyInitItemIdentifiers - extends VLazyInitItemIdentifiers { - // all logic in superclass -} |