Package com.bradrydzewski.gwt.calendar.client.dayview

Source Code of com.bradrydzewski.gwt.calendar.client.dayview.DayView

/*
* This file is part of gwt-cal
* Copyright (C) 2010  Scottsdale Software LLC
*
* gwt-cal is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.

* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/
*/
package com.bradrydzewski.gwt.calendar.client.dayview;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.allen_sauer.gwt.dnd.client.DragEndEvent;
import com.allen_sauer.gwt.dnd.client.DragHandler;
import com.allen_sauer.gwt.dnd.client.DragStartEvent;
import com.allen_sauer.gwt.dnd.client.PickupDragController;
import com.allen_sauer.gwt.dnd.client.VetoDragException;
import com.allen_sauer.gwt.dnd.client.drop.DayViewDropController;
import com.allen_sauer.gwt.dnd.client.drop.DayViewPickupDragController;
import com.allen_sauer.gwt.dnd.client.drop.DayViewResizeController;
import com.bradrydzewski.gwt.calendar.client.Appointment;
import com.bradrydzewski.gwt.calendar.client.CalendarSettings.Click;
import com.bradrydzewski.gwt.calendar.client.CalendarView;
import com.bradrydzewski.gwt.calendar.client.CalendarWidget;
import com.bradrydzewski.gwt.calendar.client.util.AppointmentUtil;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;

public class DayView extends CalendarView {

  private DayViewHeader dayViewHeader = null;
  private DayViewBody dayViewBody = null;
  private DayViewMultiDayBody multiViewBody = null;
  private DayViewLayoutStrategy layoutStrategy = null;

  private final List<AppointmentWidget> appointmentWidgets = new ArrayList<AppointmentWidget>();
  /**
   * List of AppointmentAdapter objects that represent the currently selected
   * appointment.
   */
  private List<AppointmentWidget> selectedAppointmentWidgets = new ArrayList<AppointmentWidget>();

  private final DayViewStyleManager styleManager = GWT.create(DayViewStyleManager.class);
 
  private DayViewResizeController resizeController = null;
 
  private DayViewDropController dropController = null;
 
  private PickupDragController dragController = null;
 
  private DayViewResizeController proxyResizeController = null;
 
  public DayView() {
    super();
  }

  private int getMaxProxyHeight() {
    // For a comfortable use, the Proxy should be, top 2/3 (66%) of the view
    int maxProxyHeight = 2 * (dayViewBody.getScrollPanel().getOffsetHeight() / 3);
   
    return maxProxyHeight;
  }
 
  @SuppressWarnings("deprecation")
  public void doLayout() {
    // PERFORM APPOINTMENT LAYOUT NOW
    final Date date = (Date) calendarWidget.getDate().clone();

    multiViewBody.setDays((Date) date.clone(), calendarWidget.getDays());
    dayViewHeader.setDays((Date) date.clone(), calendarWidget.getDays());
    dayViewHeader.setYear((Date) date.clone());
    dayViewBody.setDays((Date) date.clone(), calendarWidget.getDays());
    dayViewBody.getTimeline().prepare();

    dropController.setColumns(calendarWidget.getDays());
    dropController.setIntervalsPerHour(calendarWidget.getSettings().getIntervalsPerHour());
    dropController.setDate((Date)calendarWidget.getDate().clone());
    dropController.setSnapSize(
        calendarWidget.getSettings().getPixelsPerInterval());
    dropController.setMaxProxyHeight(getMaxProxyHeight());
    resizeController.setIntervalsPerHour(
        calendarWidget.getSettings().getIntervalsPerHour());
    resizeController.setSnapSize(
        calendarWidget.getSettings().getPixelsPerInterval());
    proxyResizeController.setSnapSize(calendarWidget.getSettings().getPixelsPerInterval());
    proxyResizeController.setIntervalsPerHour(calendarWidget.getSettings().getIntervalsPerHour());
   
    this.selectedAppointmentWidgets.clear();
    appointmentWidgets.clear();

    // HERE IS WHERE WE DO THE LAYOUT
    final Date tmpDate = (Date) calendarWidget.getDate().clone();

    for (int i = 0; i < calendarWidget.getDays(); i++) {

      ArrayList<Appointment> filteredList = AppointmentUtil
          .filterListByDate(calendarWidget.getAppointments(), tmpDate);

      // perform layout
      ArrayList<AppointmentAdapter> appointmentAdapters = layoutStrategy
          .doLayout(filteredList, i, calendarWidget.getDays());

      // add all appointments back to the grid
      addAppointmentsToGrid(appointmentAdapters, false);

      tmpDate.setDate(tmpDate.getDate() + 1);
    }
   
        ArrayList<Appointment> filteredList =
            AppointmentUtil.filterListByDateRange(calendarWidget.getAppointments(),
                calendarWidget.getDate(), calendarWidget.getDays());
       
        ArrayList<AppointmentAdapter> adapterList = new ArrayList<AppointmentAdapter>();
        int desiredHeight = layoutStrategy.doMultiDayLayout(filteredList,
            adapterList, calendarWidget.getDate(), calendarWidget.getDays());
       
        multiViewBody.grid.setHeight(desiredHeight + "px");
       
        addAppointmentsToGrid(adapterList, true);
  }

  /**
   * Adds the Appointments to the view.
   * @param appointmentList List of Appointments
   * @param addToMultiView <code>true</code> if is adding the appointments to the multiview section, <code>false</code> otherwise
   */
  private void addAppointmentsToGrid(final List<AppointmentAdapter> appointmentList, final boolean addToMultiView) {
    for (AppointmentAdapter appt : appointmentList) {
      AppointmentWidget panel = new AppointmentWidget();
        panel.setWidth(appt.getWidth());
        panel.setHeight(appt.getHeight());
        panel.setTitle(appt.getAppointment().getTitle());
        panel.setTop(appt.getTop());
        panel.setLeft(appt.getLeft());
      panel.setAppointment(appt.getAppointment());
     
      boolean selected = calendarWidget.isTheSelectedAppointment(panel
          .getAppointment());
      if (selected) {
        selectedAppointmentWidgets.add(panel);
      }
      styleManager.applyStyle(panel, selected);
      appointmentWidgets.add(panel);

      if (addToMultiView) {
        panel.setMultiDay(true);
        this.multiViewBody.grid.add(panel);
      } else {
        panel.setDescription(appt.getAppointment().getDescription());
        dayViewBody.getGrid().grid.add(panel);

        //make footer 'draggable'
        if (calendarWidget.getSettings().isEnableDragDrop() && !appt.getAppointment().isReadOnly()) {
          resizeController.makeDraggable(panel.getResizeHandle());
                dragController.makeDraggable(panel, panel.getMoveHandle());
        }
      }
    }
  }
 
  @Override
    public void scrollToHour(final int hour) {
        dayViewBody.getScrollPanel().setVerticalScrollPosition(hour *
                getSettings().getIntervalsPerHour() * getSettings().getPixelsPerInterval());
    }
 
  public void doSizing() {

    if (calendarWidget.getOffsetHeight() > 0) {
      dayViewBody.setHeight(calendarWidget.getOffsetHeight() - 2
          - dayViewHeader.getOffsetHeight()
          - multiViewBody.getOffsetHeight() + "px");
    }

    // multiViewBody.grid.setHeight(desiredHeight + "px");
  }

  public void onDeleteKeyPressed() {
    if (calendarWidget.getSelectedAppointment()!=null) {
      calendarWidget.fireDeleteEvent(calendarWidget.getSelectedAppointment());
    }
  }

  public void onDoubleClick(Element element, Event event) {

    List<AppointmentWidget> list = findAppointmentWidgetsByElement(element);
    if (!list.isEmpty()) {
      Appointment appt = list.get(0).getAppointment();
      //if (appt.equals(calendarWidget.getSelectedAppointment()))
        calendarWidget.fireOpenEvent(appt);
      // exit out

    } else if (getSettings().getTimeBlockClickNumber() == Click.Double
        && element == dayViewBody.getGrid().gridOverlay.getElement()) {
      int x = DOM.eventGetClientX(event);
      int y = DOM.eventGetClientY(event);
      timeBlockClick(x, y);
    }
  }

  public void onSingleClick(final Element element, final Event event) {

    // Ignore the scroll panel
    if (dayViewBody.getScrollPanel().getElement().equals(element)) {
      return;
    }

        Appointment appt =
          findAppointmentByElement(element);
       
        if (appt!=null) {
          selectAppointment(appt);
        } else if ((getSettings().getTimeBlockClickNumber() == Click.Single
        || getSettings().getEnableDragDropCreation())
        && element == dayViewBody.getGrid().gridOverlay
        .getElement()) {
      int x = DOM.eventGetClientX(event);
      int y = DOM.eventGetClientY(event);
      timeBlockClick(x, y);
    }
  }
 
  public void onMouseOver(final Element element, final Event event) {
    Appointment appointment = findAppointmentByElement(element);
    calendarWidget.fireMouseOverEvent(appointment, element);
  }
 
  @Override
  public void onAppointmentSelected(Appointment appt) {

    List<AppointmentWidget> clickedAppointmentAdapters =
      findAppointmentWidget(appt);

    if (!clickedAppointmentAdapters.isEmpty()) {
      for (AppointmentWidget adapter : selectedAppointmentWidgets) {
        styleManager.applyStyle(adapter, false);
      }

      for (AppointmentWidget adapter : clickedAppointmentAdapters) {
        styleManager.applyStyle(adapter, true);
      }

      selectedAppointmentWidgets.clear();
      selectedAppointmentWidgets = clickedAppointmentAdapters;
     
      float height = clickedAppointmentAdapters.get(0).getHeight();
      // scrollIntoView ONLY if the appointment fits in the viewable area
      if (dayViewBody.getScrollPanel().getOffsetHeight() > height) {
        DOM.scrollIntoView(clickedAppointmentAdapters.get(0).getElement())
      }
    }
  }

  public void onRightArrowKeyPressed() {
    calendarWidget.selectNextAppointment();
  }

  public void onUpArrowKeyPressed() {
    calendarWidget.selectPreviousAppointment();
  }

  public void onDownArrowKeyPressed() {
    calendarWidget.selectNextAppointment();
  }

  public void onLeftArrowKeyPressed() {
    calendarWidget.selectPreviousAppointment();
  }

  @Override
  public String getStyleName() {
    return "gwt-cal";
  }

  @Override
  public void attach(CalendarWidget widget) {
    super.attach(widget);

    if (dayViewBody == null) {
      dayViewBody = new DayViewBody(this);
      dayViewHeader = new DayViewHeader(this);
      layoutStrategy = new DayViewLayoutStrategy(this);
      multiViewBody = new DayViewMultiDayBody(this);
    }

    calendarWidget.getRootPanel().add(dayViewHeader);
    calendarWidget.getRootPanel().add(multiViewBody);
    calendarWidget.getRootPanel().add(dayViewBody);
   
    if (getSettings() != null) {
      scrollToHour(getSettings().getScrollToHour());
    }
   
    // Creates the different Controllers, if needed
    createDragController();
   
    createDropController();
   
    createResizeController();

  }

  private void createDragController() {
    if (dragController == null) {
      dragController = new DayViewPickupDragController(dayViewBody.getGrid().grid, false);
          dragController.setBehaviorDragProxy(true);
          dragController.setBehaviorDragStartSensitivity(1);
          dragController.setBehaviorConstrainedToBoundaryPanel(true); //do I need these?
          dragController.setConstrainWidgetToBoundaryPanel(true); //do I need these?
          dragController.setBehaviorMultipleSelection(false);
          dragController.addDragHandler(new DragHandler(){
 
        public void onDragEnd(DragEndEvent event) {
          Appointment appt = ((AppointmentWidget) event.getContext().draggable).getAppointment();
                  calendarWidget.setCommittedAppointment(appt);
                  calendarWidget.fireUpdateEvent(appt);
        }
 
        public void onDragStart(DragStartEvent event) {
          Appointment appt = ((AppointmentWidget) event.getContext().draggable).getAppointment();
          calendarWidget.setRollbackAppointment(appt.clone());
          ((DayViewPickupDragController)dragController).setMaxProxyHeight(getMaxProxyHeight());
        }
 
        public void onPreviewDragEnd(DragEndEvent event)
            throws VetoDragException {
        }
 
        public void onPreviewDragStart(DragStartEvent event)
            throws VetoDragException {
        }
          });
    }
  }
 
  private void createDropController() {
    if (dropController==null) {
      dropController = new DayViewDropController(dayViewBody.getGrid().grid);
      dragController.registerDropController(dropController);
    }
  }
 
  private void createResizeController() {
    if (resizeController == null) {
      resizeController = new DayViewResizeController(dayViewBody.getGrid().grid);
      resizeController.addDragHandler(new DragHandler(){

        public void onDragEnd(DragEndEvent event) {
          Appointment appt = ((AppointmentWidget) event.getContext().draggable.getParent()).getAppointment();
                    calendarWidget.setCommittedAppointment(appt);
                    calendarWidget.fireUpdateEvent(appt);
        }

        public void onDragStart(DragStartEvent event) {
          calendarWidget
          .setRollbackAppointment(((AppointmentWidget) event
              .getContext().draggable.getParent()).getAppointment()
              .clone());
        }

        public void onPreviewDragEnd(DragEndEvent event)
            throws VetoDragException {}
        public void onPreviewDragStart(DragStartEvent event)
            throws VetoDragException {}
      });
    }
     
    if(proxyResizeController == null) {
      proxyResizeController = new DayViewResizeController(dayViewBody.getGrid().grid);
      proxyResizeController.addDragHandler(new DragHandler(){
        long startTime = 0L;
        int initialX = 0;
        int initialY = 0;
        Date startDate;
       
        public void onDragEnd(DragEndEvent event) {
          long clickTime = System.currentTimeMillis() - startTime;
          int y = event.getContext().mouseY;
          if (clickTime <= 500 && initialY == y) {
            calendarWidget.fireTimeBlockClickEvent(startDate);
          } else {
            Appointment appt = ((AppointmentWidget) event.getContext().draggable.getParent()).getAppointment();
            calendarWidget.fireCreateEvent(appt);           
          }
        }

        public void onDragStart(DragStartEvent event) {
          startTime = System.currentTimeMillis();
          initialX = event.getContext().mouseX;
          initialY = event.getContext().mouseY;
          startDate = getCoordinatesDate(initialX, initialY);
        }

        public void onPreviewDragEnd(DragEndEvent event)
            throws VetoDragException {}
        public void onPreviewDragStart(DragStartEvent event)
            throws VetoDragException {}
      });
    }
  }
 
  @SuppressWarnings("deprecation")
  private Date getCoordinatesDate(int x, int y) {
    int left = dayViewBody.getGrid().gridOverlay.getAbsoluteLeft();
    int top = dayViewBody.getScrollPanel().getAbsoluteTop();
    int width = dayViewBody.getGrid().gridOverlay.getOffsetWidth();
    int scrollOffset = dayViewBody.getScrollPanel().getScrollPosition();

    // x & y are based on screen position,need to get x/y relative to
    // component
    int relativeY = y - top + scrollOffset;
    int relativeX = x - left;

    // find the interval clicked and day clicked
    double interval = Math.floor(relativeY
        / (double) getSettings().getPixelsPerInterval());
    double day = Math.floor((double) relativeX
        / ((double) width / (double) calendarWidget.getDays()));

    // create new appointment date based on click
    Date newStartDate = calendarWidget.getDate();
    newStartDate.setHours(0);
    newStartDate.setMinutes(0);
    newStartDate.setSeconds(0);
    newStartDate.setMinutes((int) interval
        * (60 / getSettings().getIntervalsPerHour()));
    newStartDate.setDate(newStartDate.getDate() + (int) day);
   
    return newStartDate;
  }
 
  @SuppressWarnings("deprecation")
  private void timeBlockClick(int x, int y) {   
    int left = dayViewBody.getGrid().gridOverlay.getAbsoluteLeft();
    int top = dayViewBody.getScrollPanel().getAbsoluteTop();
    int width = dayViewBody.getGrid().gridOverlay.getOffsetWidth();
    int scrollOffset = dayViewBody.getScrollPanel().getScrollPosition();
   
    // x & y are based on screen position,need to get x/y relative to
    // component
    int relativeY = y - top + scrollOffset;
    int relativeX = x - left;
   
    // find the interval clicked and day clicked
    double day = Math.floor((double) relativeX
        / ((double) width / (double) calendarWidget.getDays()));

    Date newStartDate = getCoordinatesDate(x, y);
   
    if (getSettings().getTimeBlockClickNumber() != Click.Drag) {
      calendarWidget.fireTimeBlockClickEvent(newStartDate);
    } else {
      int snapSize = calendarWidget.getSettings().getPixelsPerInterval();
      // Create the proxy
      width = width / calendarWidget.getDays();
      int height = snapSize;
      left = (int) day * width;
      // Adjust the start to the closest interval
      top = (int)Math.floor(
          (float) relativeY / snapSize) * snapSize;

      AppointmentWidget proxy = new AppointmentWidget();
      Appointment app = new Appointment();
      app.setStart(newStartDate);
      app.setEnd(newStartDate);
      proxy.setAppointment(app);
      proxy.setStart(newStartDate);
      proxy.setPixelSize(width, height);
      dayViewBody.getGrid().grid.add(proxy, left, top);
        styleManager.applyStyle(proxy, false);
        proxyResizeController.makeDraggable(proxy.getResizeHandle());
       
          NativeEvent evt = Document.get().createMouseDownEvent(1, 0, 0, x, y, false,
                false, false, false, NativeEvent.BUTTON_LEFT);
          proxy.getResizeHandle().getElement().dispatchEvent(evt);
    }
  }

  private List<AppointmentWidget> findAppointmentWidgetsByElement(
      Element element) {
    return findAppointmentWidget(findAppointmentByElement(element));
  }

  /**
   * Returns the {@link Appointment} indirectly associated to the passed
   * <code>element</code>. Each Appointment drawn on the CalendarView maps to
   * a Widget and therefore an Element. This method attempts to find an
   * Appointment based on the provided Element. If no match is found a null
   * value is returned.
   *
   * @param element
   *            Element to look up.
   * @return Appointment matching the element.
   */
  private Appointment findAppointmentByElement(Element element) {
    Appointment appointmentAtElement = null;
    for (AppointmentWidget widget : appointmentWidgets) {
      if (DOM.isOrHasChild(widget.getElement(), element)) {
        appointmentAtElement = widget.getAppointment();
        break;
      }
    }
    return appointmentAtElement;
  }

  /**
   * Finds any related adapters that match the given Appointment.
   *
   * @param appt
   *            Appointment to match.
   * @return List of related AppointmentWidget objects.
   */
  private List<AppointmentWidget> findAppointmentWidget(Appointment appt) {
    ArrayList<AppointmentWidget> appointmentAdapters = new ArrayList<AppointmentWidget>();
    if (appt != null) {
      for (AppointmentWidget widget : appointmentWidgets) {
        if (widget.getAppointment().equals(appt)) {
          appointmentAdapters.add(widget);
        }
      }
    }
    return appointmentAdapters;
  }


}
TOP

Related Classes of com.bradrydzewski.gwt.calendar.client.dayview.DayView

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.