|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736 |
- /*
- * 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.v7.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.v7.client.ui.VCalendar;
- import com.vaadin.v7.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().isEmpty()) {
- 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");
- }
- }
|