Package org.olat.commons.calendar.ui.components

Source Code of org.olat.commons.calendar.ui.components.WeeklyCalendarComponentRenderer

/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/

package org.olat.commons.calendar.ui.components;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.time.DateUtils;
import org.olat.commons.calendar.CalendarManager;
import org.olat.commons.calendar.CalendarUtils;
import org.olat.commons.calendar.model.KalendarEvent;
import org.olat.commons.calendar.model.KalendarEventLink;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.ComponentRenderer;
import org.olat.core.gui.control.winmgr.AJAXFlags;
import org.olat.core.gui.render.RenderResult;
import org.olat.core.gui.render.Renderer;
import org.olat.core.gui.render.RenderingState;
import org.olat.core.gui.render.StringOutput;
import org.olat.core.gui.render.URLBuilder;
import org.olat.core.gui.translator.Translator;
import org.olat.core.util.Formatter;
import org.olat.core.util.StringHelper;
import org.olat.core.util.Util;

public class WeeklyCalendarComponentRenderer implements ComponentRenderer {

 
  /* This is fix (see calendar.css) */
  private int days = 7;
  private int viewStartHour = 7;
  /* This is fix (and depends on settings in calendar.css) */
  private static int dayEventHeightPixels = 20;
  private static int halfHourHeightPixels = 20;
  private static float dayGridRelativeStart = 9;
  private static float dayRelativeWidth = 13;
  private static DateFormat dmyDateFormat = new SimpleDateFormat("ddMMyyyyHHmm");

  private boolean isIframePostEnabled = false;
 
  public WeeklyCalendarComponentRenderer(int viewStartHour) {
    this.viewStartHour = viewStartHour;
  }
 
  public void render(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, Translator translator,
      RenderResult renderResult, String[] args) {
   
    WeeklyCalendarComponent calendarComponent = (WeeklyCalendarComponent)source;
    days = calendarComponent.getDisplayDays();
    int year = calendarComponent.getYear();
    int weekOfYear = calendarComponent.getWeekOfYear();
    isIframePostEnabled = renderer.getGlobalSettings().getAjaxFlags().isIframePostEnabled();

    // get all events from all calendars within the week's view
    // sort into standard events and allday events
    // sort both arrays
    Calendar cal = CalendarUtils.getStartOfWeekCalendar(calendarComponent.getYear(), calendarComponent.getWeekOfYear(), translator.getLocale());
    Date weekStart = cal.getTime();
    cal.add(Calendar.DAY_OF_YEAR, days);
    Date weekEnd = cal.getTime();
    List<KalendarEventRenderWrapper> sortedEventsWithinWeek = new ArrayList<KalendarEventRenderWrapper>();
    List<KalendarEventRenderWrapper> sortedAllDayEventsWithinWeek = new ArrayList<KalendarEventRenderWrapper>();
    boolean hasWriteableCalendar = false;
    for (Iterator kalendarWrappers = calendarComponent.getKalendars().iterator(); kalendarWrappers.hasNext();) {
      KalendarRenderWrapper calendarWrapper = (KalendarRenderWrapper) kalendarWrappers.next();
      // check if calendar is writeable
      if (calendarWrapper.getAccess() == KalendarRenderWrapper.ACCESS_READ_WRITE)
        hasWriteableCalendar = true;
      // skip if not selected for display
      if (!calendarWrapper.getKalendarConfig().isVis()) continue;
      boolean readOnlyCalendar = calendarWrapper.getAccess() == KalendarRenderWrapper.ACCESS_READ_ONLY;
      boolean isImportedCalendar = calendarWrapper.isImported();
      List events = CalendarUtils.listEventsForPeriod(calendarWrapper.getKalendar(), weekStart, weekEnd);
      for (Iterator iter = events.iterator(); iter.hasNext();) {
        KalendarEvent event = (KalendarEvent) iter.next();
        // filter out private events on readonly calendars
        if (readOnlyCalendar && !isImportedCalendar && event.getClassification() == KalendarEvent.CLASS_PRIVATE) continue;
        if (event.isAllDayEvent()) {
          sortedAllDayEventsWithinWeek.add(new KalendarEventRenderWrapper(event, calendarWrapper));
        } else {
          sortedEventsWithinWeek.add(new KalendarEventRenderWrapper(event, calendarWrapper));
        }
      }
    }
    Collections.sort(sortedEventsWithinWeek, KalendarEventDateComparator.getInstance());
    Collections.sort(sortedAllDayEventsWithinWeek, KalendarEventDateComparator.getInstance());

    Locale locale = translator.getLocale();
   
    // open grid divs
    sb.append("\n<div class=\"o_cal_wv\" id=\"o_cal_wv\">");   
    // render the grid
    sb.append("<div id=\"o_cal_wv_header_wrapper\">");
    renderWeekHeader(year, weekOfYear, hasWriteableCalendar, sb, ubu, locale);
    renderAllDayGrid(year, weekOfYear, sortedAllDayEventsWithinWeek, sb, ubu, translator);
    sb.append("</div><div class=\"o_cal_wv_grid_wrapper\"><div class=\"o_cal_wv_grid\" id=\"o_cal_wv_grid\">");
    renderWeekGrid(year, weekOfYear, hasWriteableCalendar, sb, ubu, locale);
    // add events to grid, absolute positioned
    renderEvents(year, weekOfYear, sortedEventsWithinWeek, sb, ubu, locale);
    // close grid divs
    sb.append("</div></div></div>");
   
    // optimize grid height and position scrollbar using ext.onready
    sb.append("<script type=\"text/javascript\">\n/* <![CDATA[ */\n");
    sb.append("Ext.onReady(function(){\n");
    sb.append("B_AjaxLogger.logDebug('onready','calendar');");
    sb.append("o_adjustCalendarHeight(\"o_cal_wv_grid\", 960);\n");
    sb.append("window.onresize = function() {o_adjustCalendarHeight(\"o_cal_wv_grid\", 960) };\n");
    sb.append("o_positionScrollbar(\"o_cal_wv_grid\", ").append(viewStartHour * 2 * halfHourHeightPixels).append(");\n");
    sb.append("o_init_event_tooltips();");
    sb.append("o_mark_event_box_overflow();");
    sb.append("\n});");
    sb.append("B_AjaxLogger.logDebug('right away','calendar');");
    sb.append("\n/* ]]> */\n</script>");

    // render print view
    List<KalendarEventRenderWrapper> allEventsOfWeek = new ArrayList<KalendarEventRenderWrapper>(sortedAllDayEventsWithinWeek);
    allEventsOfWeek.addAll(sortedEventsWithinWeek);
    Collections.sort(allEventsOfWeek, KalendarEventDateComparator.getInstance());
    renderEventsListForPrint(year, weekOfYear, allEventsOfWeek, sb, locale);
  }

  private void renderEventsListForPrint(int year, int weekOfYear, List<KalendarEventRenderWrapper> sortedEventsWithinWeek, StringOutput sb,
      Locale locale) {
    sb.append("<div class=\"o_cal_wv_print\">\n");
    sb.append("<ul class=\"o_cal_wv_list\">\n");
    // render day events which are positioned absolute
    Calendar cal = CalendarUtils.getStartOfWeekCalendar(year, weekOfYear, locale);
    Date periodStart = cal.getTime();
    cal.add(Calendar.DAY_OF_YEAR, 1);
    Date periodEnd = cal.getTime();
    // itterate over days
    for (int dayCounter = 0; dayCounter < days; dayCounter++) {
      // collect all events for actual day
      List<KalendarEventRenderWrapper> sortedEventsOfDay = new ArrayList<KalendarEventRenderWrapper>();
      for (KalendarEventRenderWrapper eventWrapper : sortedEventsWithinWeek) {
        KalendarEvent nextEvent = eventWrapper.getEvent();
        if (nextEvent.getEnd().before(periodStart) || nextEvent.getBegin().after(periodEnd)) continue;
        sortedEventsOfDay.add(eventWrapper);
      }
      // note that eventWrappers may get re-used if it is a multi-day event
      renderEventsOfDayForPrint(sortedEventsOfDay, periodStart, periodEnd, sb, locale);

      // reposition start/end period
      periodStart = periodEnd;
      cal.add(Calendar.DAY_OF_YEAR, 1);
      periodEnd = cal.getTime();
    } // day iteration
    sb.append("</ul>\n");
    sb.append("<div class=\"b_clearfix\">&nbsp;</div>\n");
    sb.append("</div>\n");
  }

  private void renderEventsOfDayForPrint(List<KalendarEventRenderWrapper> sortedEvents, Date dayStart, Date dayEnd, StringOutput sb, Locale locale) {
    if (!sortedEvents.isEmpty()) {
      sb.append("<li>\n");
      sb.append("<span class=\"o_cal_date\">\n");
      sb.append(StringHelper.formatLocaleDateFull(dayStart.getTime(), locale));
      sb.append("</span>\n");
      sb.append("<ul class=\"o_cal_events\">\n");
      for (KalendarEventRenderWrapper event : sortedEvents) {
        renderEventForPrint(event, dayStart, dayEnd, sb, locale);
      }
      sb.append("</ul>\n");
      sb.append("</li>\n");
    }
  }

  private void renderEventForPrint(KalendarEventRenderWrapper eventWrapper, Date dayStart, Date dayEnd, StringOutput sb, Locale locale) {
    KalendarEvent event = eventWrapper.getEvent();
    boolean hidden = eventWrapper.getCalendarAccess() == KalendarRenderWrapper.ACCESS_READ_ONLY
        && !eventWrapper.getKalendarRenderWrapper().isImported() && event.getClassification() != KalendarEvent.CLASS_PUBLIC;
    String escapedSubject = Formatter.escWithBR(event.getSubject()).toString();
    escapedSubject = escapedSubject.replace('\r', ' ');
    sb.append("<li class=\"o_cal_event\">\n");
    // time
    sb.append("<div class=\"o_cal_time\"><span>\n");
    Translator translator = Util.createPackageTranslator(CalendarManager.class, locale);
    if (event.isAllDayEvent()) {
      sb.append(translator.translate("cal.form.allday"));
    } else {
      // set start and end times for events spanning more than one day
      Date begin = event.getBegin();
      Date end = event.getEnd();
      if (begin.before(dayStart)) {
        begin = dayStart;
      }
      if (end.after(dayEnd)) {
        end = dayEnd;
      }
      sb.append(StringHelper.formatLocaleTime(begin.getTime(), locale));
      sb.append(" - ");
      sb.append(StringHelper.formatLocaleTime(end.getTime(), locale));
    }
    sb.append("</span></div>\n");
    // event name (subject)
    sb.append("<div class=\"o_cal_subject " + eventWrapper.getCssClass() + "\"><span>\n");
    if (hidden) {
      sb.append("-");
    } else {
      sb.append(escapedSubject);
    }
    sb.append("</span></div>\n");
    // location
    if (StringHelper.containsNonWhitespace(event.getLocation())) {
      sb.append("<div class=\"o_cal_location\"><span>\n");
      sb.append(translator.translate("cal.form.location") + ": ");
      if (!hidden) {
        sb.append(event.getLocation());
      }
      sb.append("</span></div>\n");
    }
    sb.append("</li>\n");
  }
 
  private void renderAllDayGrid(int year, int weekOfYear, List sortedAllDayEventsForWeek, StringOutput sb, URLBuilder ubu, Translator translator) {
    Calendar cal = CalendarUtils.getStartOfWeekCalendar(year, weekOfYear, translator.getLocale());
    int dayToday = -1;
    Calendar calNow = CalendarUtils.createCalendarInstance(translator.getLocale());
    if ( (calNow.get(Calendar.WEEK_OF_YEAR) == weekOfYear)
        && (calNow.get(Calendar.YEAR) == year) ) {
      // if we are within current week, adjust dayToday
      dayToday = calNow.get(Calendar.DAY_OF_WEEK);
    }
   
    StringOutput inset = new StringOutput(1024);
    int maxDayEvents = 0;
    for (int day = 1; day <= days; day++) {
      int dayOfWeekIter = cal.get(Calendar.DAY_OF_WEEK);
      Date periodBegin = cal.getTime();
      inset.append("<div class=\"o_cal_wv_dlday o_cal_wv_row");
      inset.append(day);
      if (dayOfWeekIter == dayToday) {
        // current day
        inset.append(" o_cal_wv_today");
      } else if (dayOfWeekIter == Calendar.SATURDAY || dayOfWeekIter == Calendar.SUNDAY) {
        // holiday
        inset.append(" o_cal_wv_holiday");
      }
      if (day == days) {
        // last day
        inset.append(" o_cal_wv_lastday");
      }
      inset.append("\" style=\"height: 100%;\">");

      cal.add(Calendar.DAY_OF_YEAR, 1);
      Date periodEnd = cal.getTime();
      // render daylong events
      int maxDayEventsThisDay = 0;
      for (Iterator iter = sortedAllDayEventsForWeek.iterator(); iter.hasNext();) {
        KalendarEventRenderWrapper eventWrapper = (KalendarEventRenderWrapper) iter.next();
        KalendarEvent event = eventWrapper.getEvent();
        // skip if not within period
        if (event.getEnd().compareTo(periodBegin) < 0 || event.getBegin().compareTo(periodEnd) >= 0) continue;
        // increment count of number of dayevents
        maxDayEventsThisDay++;
        boolean hideSubject = eventWrapper.getCalendarAccess() == KalendarRenderWrapper.ACCESS_READ_ONLY && !eventWrapper.getKalendarRenderWrapper().isImported() && event.getClassification() != KalendarEvent.CLASS_PUBLIC;
        String escapedSubject = Formatter.escWithBR(event.getSubject()).toString();
       
        inset.append("<div class=\"o_cal_wv_devent_wrapper\">");
        inset.append("<div class=\"o_cal_wv_devent ").append(eventWrapper.getKalendarRenderWrapper().getKalendarConfig().getCss()).append("\">");
        inset.append("<div class=\"o_cal_wv_devent_content\">");
        inset.append("<a href=\"");
        ubu.buildURI(inset, new String[] {WeeklyCalendarComponent.ID_CMD, WeeklyCalendarComponent.ID_PARAM},
            new String[] {WeeklyCalendarComponent.CMD_EDIT, event.getCalendar().getCalendarID() + WeeklyCalendarComponent.ID_PARAM_SEPARATOR + event.getID() + WeeklyCalendarComponent.ID_PARAM_SEPARATOR + event.getBegin().getTime()},
            isIframePostEnabled ? AJAXFlags.MODE_TOBGIFRAME : AJAXFlags.MODE_NORMAL);
        inset.append("\" ");
        if (isIframePostEnabled) {
          ubu.appendTarget(inset);
        }
        inset.append(" onclick=\"return o2cl();\">");
        if (hideSubject) {
          inset.append("<i>").append(translator.translate("cal.eventdetails.hidden")).append("</i>");
        } else {
          inset.append(escapedSubject);
        }
        inset.append("</a>");
        // append any event links
        if (!hideSubject) {
          renderEventLinks(event, inset);
        }
        // closing devent_content
        inset.append("</div>");
       
        // render event tooltip content
        renderEventTooltip(event, escapedSubject, hideSubject, inset, ubu, translator.getLocale());
       
        // closing devent and devent_wrapper
        inset.append("</div></div>");
      } // events within day iterator
     
      inset.append("</div>");
      if (maxDayEventsThisDay > maxDayEvents) maxDayEvents = maxDayEventsThisDay;
    } // day irterator
   
    // do not render anything if we do not have any allday events
    if (maxDayEvents == 0) return;
    sb.append("\n<div id=\"o_cal_wv_daylong\" style=\"height: ").append(maxDayEvents * dayEventHeightPixels).append("px;\">");
    sb.append("<div class=\"o_cal_wv_time o_cal_wv_row0\" style=\"height: 100%;\"></div>")
    sb.append(inset);
    sb.append("</div>");
  }
 
  private void renderEvents(int year, int weekOfYear, List sortedEventsWithinWeek, StringOutput sb, URLBuilder ubu, Locale locale) {
    // render day events which are positioned absolute
    Calendar cal = CalendarUtils.getStartOfWeekCalendar(year, weekOfYear, locale);
    Date periodStart = cal.getTime();
    cal.add(Calendar.DAY_OF_YEAR, 1);
    Date periodEnd = cal.getTime();
    // itterate over days
    for (int dayCounter = 0; dayCounter < days; dayCounter++) {
      // collect all events for actual day
      List sortedEventsOfDay = new ArrayList();
      for (Iterator iter = sortedEventsWithinWeek.iterator(); iter.hasNext();) {
        KalendarEventRenderWrapper eventWrapper = (KalendarEventRenderWrapper) iter.next();
        KalendarEvent nextEvent = eventWrapper.getEvent();
        if (nextEvent.getEnd().before(periodStart) || nextEvent.getBegin().after(periodEnd)) continue;
        sortedEventsOfDay.add(eventWrapper);
      }
      // not that eventWrappers may get re-used if it is a multi-day event
      renderEventsForDay(sortedEventsOfDay, periodStart, dayCounter, sb, ubu, locale);
     
      // reposition start/end period
      periodStart = periodEnd;
      cal.add(Calendar.DAY_OF_YEAR, 1);
      periodEnd = cal.getTime();
    } // day iteration
   
  }
 
  private void renderEventsForDay(List sortedEvents, Date dayStart, int column, StringOutput sb, URLBuilder ubu, Locale locale) {
    if (sortedEvents.isEmpty()) return;
   
    // this is the start of this day
    long startDateLong = dayStart.getTime();
   
    /**
     * STAGE 1: assign slots
     */
   
    // list containing slot endpoint information (Long(lastEndPointMillis))
    List slotEndPointsList = new ArrayList();
    // make at least one end point slot available
    slotEndPointsList.add(new Long(-1));
    // List of event group with equal slot widths
    List slotGroup = new ArrayList();
    // the maximum slots for this group
    int maxSlotsForGroup = 1;
    // the latest endpoint of this group (this endpoint is part of the slotEndPointsList)
    long latestEndPointForGroup = -1;
   
    // Iterate over all events
    for (int eventCounter = 0; eventCounter < sortedEvents.size(); eventCounter++) {
      KalendarEventRenderWrapper eventWrapper = (KalendarEventRenderWrapper)sortedEvents.get(eventCounter);
      KalendarEvent event = eventWrapper.getEvent();
      // get relative begin / end of event in millis
      long eventBeginRelativeMillis = event.getBegin().getTime() - startDateLong;
      // if begin is before our start period, correct
      if (eventBeginRelativeMillis < 0) eventBeginRelativeMillis = 0;
      long eventEndRelativeMillis = event.getEnd().getTime() - startDateLong;
      // if end relative greater than one day, correct
      if (eventEndRelativeMillis > (1000 * 60 * 60 * 24)) eventEndRelativeMillis = (1000 * 60 * 60 * 24);
     
      // first, cleanup slot group if we reach new, completely empty slot row
      if (eventBeginRelativeMillis > latestEndPointForGroup) {
        // reset slotGroup and slotEndPointsList
        slotGroup = new ArrayList();
        slotEndPointsList = new ArrayList();
        slotEndPointsList.add(new Long(-1));
        maxSlotsForGroup = 1;
      }
     
      // search for a slot which matches relative begin and mark it in the slot list
      boolean foundSlot = false;
      int nextFreeSlot = 0;
      for (; nextFreeSlot < slotEndPointsList.size(); nextFreeSlot++) {
        Long slotEnd = (Long)slotEndPointsList.get(nextFreeSlot);
        if (slotEnd.longValue() <= eventBeginRelativeMillis) {
          foundSlot = true;
          break;
        }
      }
      if (!foundSlot) {
        // no free slots, open a new slot
        // register end point
        slotEndPointsList.add(new Long(eventEndRelativeMillis));
        // correct max slot width for all in slot group
        maxSlotsForGroup++;
        for (Iterator iter = slotGroup.iterator(); iter.hasNext();) {
          KalendarEventRenderWrapper rw = (KalendarEventRenderWrapper) iter.next();
          rw.setMaxSlots(maxSlotsForGroup);
        }
      } else {
        // mark slot end point
        slotEndPointsList.set(nextFreeSlot, new Long(eventEndRelativeMillis));
      }

      // add to slot group
      slotGroup.add(eventWrapper);
      // mark latest end point of slot group
      if (latestEndPointForGroup < eventEndRelativeMillis)
        latestEndPointForGroup = eventEndRelativeMillis;
      // set assigned slot
      eventWrapper.setAssignedSlot(nextFreeSlot);
      // set max slots
      eventWrapper.setMaxSlots(maxSlotsForGroup);

     
      // see how much we can expand to the east
      // note that this makes it n*(n-1) loops. Remove this to have linear times
      int maxExpandToEast = maxSlotsForGroup - nextFreeSlot;
      for (Iterator iter = slotGroup.iterator(); iter.hasNext();) {
        KalendarEventRenderWrapper rw2 = (KalendarEventRenderWrapper) iter.next();
        // skip all slots which are to the west
        if (rw2.getAssignedSlot() <= eventWrapper.getAssignedSlot()) continue;
        // skip if we don't collide with the event
        if (rw2.getEvent().getEnd().before(event.getBegin())) continue;
        // now this event is limiting.... see how far we can grow to the east
        if (maxExpandToEast > rw2.getAssignedSlot())
          maxExpandToEast = rw2.getAssignedSlot();
      }
      eventWrapper.setSlotExpandToEast(maxExpandToEast);
    }
   
    /**
     * STAGE 2: calculate final geometry
     */
   
    int pixelsTotalPerPeriod = 24 * 2 * halfHourHeightPixels;
    int millisTotalPerPeriod = 24 * 60 * 60 * 1000;
    for (int eventCounter = 0; eventCounter < sortedEvents.size(); eventCounter++) {
      KalendarEventRenderWrapper eventWrapper = (KalendarEventRenderWrapper)sortedEvents.get(eventCounter);
     
      // calculate Y-coordinate and height ehich are already
      // total available pixels is 24 * 2 * half hour pixels
      // get relative begin / end of event
      long eventBeginRelative = eventWrapper.getEvent().getBegin().getTime() - startDateLong;
      if (eventBeginRelative < 0) eventBeginRelative = 0;
      long eventEndRelative = eventWrapper.getEvent().getEnd().getTime() - startDateLong;
      if (eventEndRelative > (1000 * 60 * 60 * 24)) eventEndRelative = (1000 * 60 * 60 * 24);
      int yPos = (int)(pixelsTotalPerPeriod * eventBeginRelative / millisTotalPerPeriod);
      int height = (int)((eventEndRelative - eventBeginRelative) * pixelsTotalPerPeriod / millisTotalPerPeriod);
      eventWrapper.setYPosAbsolute(yPos);
      eventWrapper.setHeightAbsolute(height);

      int assignedSlot = eventWrapper.getAssignedSlot();
      int slotsExpandToEast = eventWrapper.getSlotExpandToEast();
      float slotWidth = dayRelativeWidth / eventWrapper.getMaxSlots();
      eventWrapper.setXPosRelative(dayGridRelativeStart  + (dayRelativeWidth * column) + (slotWidth * assignedSlot));
      eventWrapper.setWidthRelative(slotWidth * slotsExpandToEast);
      renderSingleEvent(eventWrapper, sb, ubu, locale);
    }
  }

  private void renderSingleEvent(KalendarEventRenderWrapper eventWrapper, StringOutput sb, URLBuilder ubu, Locale locale) {
    KalendarEvent event = eventWrapper.getEvent();
    boolean hideSubject = eventWrapper.getCalendarAccess() == KalendarRenderWrapper.ACCESS_READ_ONLY && !eventWrapper.getKalendarRenderWrapper().isImported() && event.getClassification() != KalendarEvent.CLASS_PUBLIC;
    String escapedSubject = Formatter.escWithBR(event.getSubject()).toString();
    escapedSubject = escapedSubject.replace('\r', ' ');
    sb.append("\n<div class=\"o_cal_wv_event_wrapper\" style=\"");
    sb.append("left: ").append("" + eventWrapper.getXPosRelative());
    sb.append("%; width: ").append("" + eventWrapper.getWidthRelative());
    sb.append("%; top: ").append(eventWrapper.getYPosAbsolute() - 1 ); // fixt start position -1px for top border
    sb.append("px; height: ").append(eventWrapper.getHeightAbsolute() - 1 ); // fix height -1 px for bottom border
    sb.append("px;\"");
    sb.append(">");
   
    sb.append("<div class=\"o_cal_wv_event ").append(eventWrapper.getCssClass()).append("\" style=\"");
    sb.append("width: auto; height: 100%\">");
    sb.append("<div class=\"o_cal_wv_event_header\"><a href=\"");
    ubu.buildURI(sb, new String[] {WeeklyCalendarComponent.ID_CMD, WeeklyCalendarComponent.ID_PARAM},
        new String[] {WeeklyCalendarComponent.CMD_EDIT, event.getCalendar().getCalendarID() + WeeklyCalendarComponent.ID_PARAM_SEPARATOR + event.getID() + WeeklyCalendarComponent.ID_PARAM_SEPARATOR + event.getBegin().getTime()},
        isIframePostEnabled ? AJAXFlags.MODE_TOBGIFRAME : AJAXFlags.MODE_NORMAL);
    sb.append("\" ");
    if (isIframePostEnabled) {
      ubu.appendTarget(sb);
    }
    sb.append(" onclick=\"return o2cl();\">");
    sb.append(CalendarUtils.getTimeAsString(event.getBegin(), locale));
    sb.append("</a></div>");
    sb.append("<div class=\"o_cal_wv_event_content\">");
    // check if we need to hide textual information.
    // Private events on readonly kalendars are already filtered out and do not appear in the render list.
    // We thus only need to check for freebusy events in readonly calendars.
    if (!hideSubject) {
      sb.append(escapedSubject);
      // append any event links
      renderEventLinks(event, sb);
    }
    sb.append("</div>");
    // tooltip content
    renderEventTooltip(event, escapedSubject, hideSubject, sb, ubu, locale);
    sb.append("</div></div>");
  }

  private void renderEventTooltip(KalendarEvent event, String escapedSubject, boolean hideSubject, StringOutput sb, URLBuilder ubu, Locale locale) {
    // Tooltip content
    sb.append("<div class=\"o_cal_wv_event_tooltip");
    if (event.isAllDayEvent()) {
      // add marker css class used in js code to identify all day events
      sb.append(" o_cal_allday");
    }
    sb.append("\">");
    // time
    sb.append("<div class=\"o_cal_time\">\n");
    Translator translator = Util.createPackageTranslator(CalendarManager.class, locale);
    Calendar cal = CalendarUtils.createCalendarInstance(locale);
    Date begin = event.getBegin();
    Date end = event.getEnd()
    cal.setTime(begin);
    sb.append(StringHelper.formatLocaleDateFull(begin.getTime(), locale));
    if (!event.isAllDayEvent()) {
      sb.append("<br />").append(StringHelper.formatLocaleTime(begin.getTime(), locale));
      sb.append(" - ");
      if (!DateUtils.isSameDay(begin, end)) {
        sb.append(StringHelper.formatLocaleDateFull(end.getTime(), locale)).append(", ");
      }
      sb.append(StringHelper.formatLocaleTime(end.getTime(), locale));
    }
    sb.append("</div>\n");
    sb.append("<div class=\"o_cal_wv_event_tooltip_content\">");
    sb.append(escapedSubject);

    // location
    if (StringHelper.containsNonWhitespace(event.getLocation())) {
      sb.append("<div class=\"o_cal_location\">\n");
      if (!hideSubject) {
        sb.append("<b>").append(translator.translate("cal.form.location")).append("</b>:");
        sb.append(event.getLocation());
      }
      sb.append("</div>\n");
    }
    // links
    if (!hideSubject) {
      renderEventLinks(event, sb);
    }
    // edit link
    sb.append("<div class=\"o_cal_tooltip_buttons\"><a class=\"b_button b_xsmall\" href=\"");
    ubu.buildURI(sb, new String[] {WeeklyCalendarComponent.ID_CMD, WeeklyCalendarComponent.ID_PARAM},
        new String[] {WeeklyCalendarComponent.CMD_EDIT, event.getCalendar().getCalendarID() + WeeklyCalendarComponent.ID_PARAM_SEPARATOR + event.getID() + WeeklyCalendarComponent.ID_PARAM_SEPARATOR + event.getBegin().getTime()},
        isIframePostEnabled ? AJAXFlags.MODE_TOBGIFRAME : AJAXFlags.MODE_NORMAL);
    sb.append("\" ");
    if (isIframePostEnabled) {
      ubu.appendTarget(sb);
    }
    sb.append("><span>");
    sb.append(translator.translate("edit"));
    sb.append("</span></a></div>");
    // event_tooltip and tooltip_content   
    sb.append("</div></div>");
  }
 
  private void renderEventLinks(KalendarEvent event, StringOutput sb) {
    List kalendarEventLinks = event.getKalendarEventLinks();
   
    if (kalendarEventLinks != null) {
      sb.append("<div class=\"o_cal_links\">");
      for (Iterator iter = kalendarEventLinks.iterator(); iter.hasNext();) {
        KalendarEventLink link = (KalendarEventLink) iter.next();
        sb.append("<br /><b>");       
        sb.append("<a href=\"javascript:top.o_openUriInMainWindow('").append(link.getURI()).append("')\" title=\"").append(StringEscapeUtils.escapeHtml(link.getDisplayName())).append("\" ");
        String iconCssClass = link.getIconCssClass();
        if (StringHelper.containsNonWhitespace(iconCssClass)) {
          sb.append("class=\"b_with_small_icon_left ").append(iconCssClass).append("\"");
        }
        sb.append(" onclick=\"return o2cl();\">").append(link.getDisplayName()).append("</a>");
        sb.append("</b>");
      }
      sb.append("</div>");
    }
  }
  private void renderWeekHeader(int year, int weekOfYear, boolean enableAddEvent, StringOutput sb, URLBuilder ubu, Locale locale) {
    Calendar cal = CalendarUtils.getStartOfWeekCalendar(year, weekOfYear, locale);
    Calendar calNow = CalendarUtils.createCalendarInstance(locale);
    cal.set(Calendar.HOUR_OF_DAY, calNow.get(Calendar.HOUR_OF_DAY));
    cal.set(Calendar.MINUTE, calNow.get(Calendar.MINUTE));
    SimpleDateFormat dayMonth = new SimpleDateFormat("E dd.MM", locale);

    // render header
    sb.append("\n<div id=\"o_cal_wv_header\">");
    sb.append("<div class=\"o_cal_wv_time o_cal_wv_row0\">");
    sb.append("<div class=\"o_cal_wv_legend_hours\"><div></div></div></div>");
    int dayToday = -1;
    if ( (calNow.get(Calendar.WEEK_OF_YEAR) == weekOfYear)
        && (calNow.get(Calendar.YEAR) == year) ) {
      // if we are within current week, adjust dayToday
      dayToday = calNow.get(Calendar.DAY_OF_WEEK);
    }
    for (int i = 1; i <= days; i++) {
      int dayOfWeekIter = cal.get(Calendar.DAY_OF_WEEK);
      sb.append("\n<div class=\"o_cal_wv_day ");
      sb.append("o_cal_wv_row");
      sb.append(i);
      sb.append(" ");
      if (i == 7) {
        // terminate last day
        sb.append("o_cal_wv_lastday ");
      }
      if (dayOfWeekIter == dayToday) {
        // current day
        sb.append("o_cal_wv_today ");
      } else if (dayOfWeekIter == Calendar.SATURDAY || dayOfWeekIter == Calendar.SUNDAY) {
        // holiday
        sb.append("o_cal_wv_holiday ");
      }     
      sb.append("\">");
      sb.append("<div class=\"o_cal_wv_legend_day\"><div>");
      if (enableAddEvent) {
        sb.append("<a href=\"");
        ubu.buildURI(sb, new String[] {WeeklyCalendarComponent.ID_CMD, WeeklyCalendarComponent.ID_PARAM},
            new String[] {WeeklyCalendarComponent.CMD_ADD, dmyDateFormat.format(cal.getTime())},
            isIframePostEnabled ? AJAXFlags.MODE_TOBGIFRAME : AJAXFlags.MODE_NORMAL);
        sb.append("\" ");
        if (isIframePostEnabled) {
          ubu.appendTarget(sb);
        }
        sb.append(" onclick=\"return o2cl();\">");
        sb.append(dayMonth.format(cal.getTime()));
        sb.append("</a>");
      } else {
        sb.append(dayMonth.format(cal.getTime()));
      }
      sb.append("</div></div></div>");
      // add one day to calendar
      cal.add(Calendar.DAY_OF_YEAR, 1);
    }
    sb.append("</div>");
  }
 
  private void renderWeekGrid(int year, int weekOfYear, boolean enableAddEvent, StringOutput sb, URLBuilder ubu, Locale locale) {
    Calendar cal = CalendarUtils.getStartOfWeekCalendar(year, weekOfYear, locale);
    int dayToday = -1;
    Calendar calNow = CalendarUtils.createCalendarInstance(locale);
    if ( (calNow.get(Calendar.WEEK_OF_YEAR) == weekOfYear)
        && (calNow.get(Calendar.YEAR) == year) ) {
      // if we are within current week, adjust dayToday
      dayToday = calNow.get(Calendar.DAY_OF_WEEK);
    }
   
    // render day grid
    sb.append("\n<div class=\"o_cal_wv_time o_cal_wv_row0\">");
    for (int i = 0; i < 23; i++) {
      sb.append("<div class=\"o_cal_wv_legend_hour\"><div>");
      sb.append(i);
      sb.append(":00</div></div>");
    }
    sb.append("<div class=\"o_cal_wv_legend_hour o_cal_wv_lasthour\"><div>23:00</div></div></div>");
   
    // render daily grid
    // reposition calendar to start of week
    for (int i = 1; i <= 7; i++) {
      int dayOfWeekIter = cal.get(Calendar.DAY_OF_WEEK);
      sb.append("\n<div class=\"o_cal_wv_day o_cal_wv_row");
      sb.append(i);
      if (dayOfWeekIter == dayToday) {
        // current day
        sb.append(" o_cal_wv_today");
      } else if (dayOfWeekIter == Calendar.SATURDAY || dayOfWeekIter == Calendar.SUNDAY) {
        // holiday
        sb.append(" o_cal_wv_holiday");
      }
      sb.append("\">");
     
      for (int j = 0; j < 23; j++) {
        // set calendar add link to corresponding hour
        cal.set(Calendar.HOUR_OF_DAY, j);
       
        //build the add event uri
        StringOutput uri = new StringOutput();
        ubu.buildJavaScriptBgCommand(uri, new String[] {WeeklyCalendarComponent.ID_CMD, WeeklyCalendarComponent.ID_PARAM},
            new String[] {WeeklyCalendarComponent.CMD_ADD, dmyDateFormat.format(cal.getTime())},
            isIframePostEnabled ? AJAXFlags.MODE_TOBGIFRAME : AJAXFlags.MODE_NORMAL, true);
       
        sb.append("<div class=\"o_cal_wv_hour\"");
        if (enableAddEvent) {
          sb.append(" onclick=\"");
          sb.append(uri);
        }
        sb.append("\"></div>");
        sb.append("<div class=\"o_cal_wv_half_hour\"");
        if (enableAddEvent) {
          sb.append(" onclick=\"");
          sb.append(uri);
        }
        sb.append("\"></div>");
      }
      // set calendar add link to last hour (23)
      cal.set(Calendar.HOUR_OF_DAY, 23);
      StringOutput uri = new StringOutput();
      // TODO: AJAX Mode
      uri.append("window.location.replace('");
      ubu.buildURI(uri, new String[] {WeeklyCalendarComponent.ID_CMD, WeeklyCalendarComponent.ID_PARAM},
          new String[] {WeeklyCalendarComponent.CMD_ADD, dmyDateFormat.format(cal.getTime())},
          AJAXFlags.MODE_NORMAL);
      uri.append("');");
      sb.append("<div class=\"o_cal_wv_hour\"");
      if (enableAddEvent) {
        sb.append(" onclick=\"");
        sb.append(uri);
      }
      sb.append("\"></div>");
      sb.append("<div class=\"o_cal_wv_half_hour o_cal_wv_lasthour\"");
      if (enableAddEvent) {
        sb.append(" onclick=\"");
        sb.append(uri);
      }
      sb.append("\"></div></div>");
      cal.add(Calendar.DAY_OF_YEAR, 1);
    }

  }

  /**
   * @see org.olat.core.gui.components.ComponentRenderer#renderHeaderIncludes(org.olat.core.gui.render.Renderer, org.olat.core.gui.render.StringOutput, org.olat.core.gui.components.Component, org.olat.core.gui.render.URLBuilder, org.olat.core.gui.translator.Translator, org.olat.core.gui.render.RenderingState)
   */
  public void renderHeaderIncludes(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, Translator translator,
      RenderingState rstate) {
    // nothing to include, css and javascript is included by calender component
  }

  /**
   * @see org.olat.core.gui.components.ComponentRenderer#renderBodyOnLoadJSFunctionCall(org.olat.core.gui.render.Renderer, org.olat.core.gui.render.StringOutput, org.olat.core.gui.components.Component, org.olat.core.gui.render.RenderingState)
   */
  public void renderBodyOnLoadJSFunctionCall(Renderer renderer, StringOutput sb, Component source, RenderingState rstate) {
    // using Ext.onReady() instead
  }

}
TOP

Related Classes of org.olat.commons.calendar.ui.components.WeeklyCalendarComponentRenderer

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.