You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by jl...@apache.org on 2006/05/29 03:59:09 UTC
svn commit: r410011 [3/5] - in /myfaces/tomahawk/trunk:
core/src/main/java/org/apache/myfaces/custom/schedule/
core/src/main/java/org/apache/myfaces/custom/schedule/model/
core/src/main/java/org/apache/myfaces/custom/schedule/renderer/
core/src/main/ja...
Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/renderer/ScheduleDetailedDayRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/renderer/ScheduleDetailedDayRenderer.java?rev=410011&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/renderer/ScheduleDetailedDayRenderer.java (added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/renderer/ScheduleDetailedDayRenderer.java Sun May 28 18:59:05 2006
@@ -0,0 +1,854 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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 org.apache.myfaces.custom.schedule.renderer;
+
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Iterator;
+import java.util.TreeSet;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIForm;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.custom.schedule.HtmlSchedule;
+import org.apache.myfaces.custom.schedule.model.ScheduleDay;
+import org.apache.myfaces.custom.schedule.model.ScheduleEntry;
+import org.apache.myfaces.custom.schedule.util.ScheduleUtil;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
+
+/**
+ * <p>
+ * Renderer for the day and workweek views of the Schedule component
+ * </p>
+ *
+ * @author Jurgen Lust (latest modification by $Author: jlust $)
+ * @author Bruno Aranda (adaptation of Jurgen's code to myfaces)
+ * @version $Revision: 392301 $
+ */
+public class ScheduleDetailedDayRenderer extends AbstractScheduleRenderer
+{
+ private static final Log log = LogFactory.getLog(ScheduleDetailedDayRenderer.class);
+
+ //~ Instance fields --------------------------------------------------------
+
+ private final int defaultRowHeightInPixels = 22;
+
+ //~ Methods ----------------------------------------------------------------
+
+ /**
+ * @see javax.faces.render.Renderer#encodeBegin(javax.faces.context.FacesContext,
+ * javax.faces.component.UIComponent)
+ */
+ public void encodeBegin(FacesContext context, UIComponent component)
+ throws IOException
+ {
+ if (!component.isRendered())
+ {
+ return;
+ }
+
+ super.encodeBegin(context, component);
+
+ HtmlSchedule schedule = (HtmlSchedule) component;
+ ResponseWriter writer = context.getResponseWriter();
+ int rowHeight = getRowHeight(schedule.getAttributes());
+
+ //the number of rows in the grid is the number of half hours between
+ //visible start hour and visible end hour, plus 1 for the header
+ int numberOfRows = ((schedule.getVisibleEndHour() - schedule
+ .getVisibleStartHour()) * 2) + 1;
+
+ //the grid height = 22 pixels times the number of rows + 3, for the
+ //table border and the cellpadding
+ int gridHeight = (numberOfRows * rowHeight) + 3 + 10;
+
+ //container div for the schedule grid
+ writer.startElement(HTML.DIV_ELEM, schedule);
+ writer.writeAttribute(HTML.CLASS_ATTR, "schedule-detailed-"
+ + getTheme(schedule), null);
+ writer.writeAttribute(HTML.STYLE_ATTR, "height: "
+ + String.valueOf(gridHeight) + "px; overflow: hidden;", null);
+ writeBackground(context, schedule, writer);
+ writeForegroundStart(context, schedule, writer);
+ }
+
+ /**
+ * @see javax.faces.render.Renderer#encodeChildren(javax.faces.context.FacesContext,
+ * javax.faces.component.UIComponent)
+ */
+ public void encodeChildren(FacesContext context, UIComponent component)
+ throws IOException
+ {
+ if (!component.isRendered())
+ {
+ return;
+ }
+
+ HtmlSchedule schedule = (HtmlSchedule) component;
+ ResponseWriter writer = context.getResponseWriter();
+ String clientId = schedule.getClientId(context);
+ UIForm parentForm = getParentForm(schedule);
+ String formId = parentForm == null ? null : parentForm.getClientId(context);
+
+ for (Iterator dayIterator = schedule.getModel().iterator(); dayIterator
+ .hasNext();)
+ {
+ ScheduleDay day = (ScheduleDay) dayIterator.next();
+ String dayBodyId = clientId + "_body_" + ScheduleUtil.getDateId(day.getDate());
+ writer.startElement(HTML.TD_ELEM, schedule);
+ writer.writeAttribute(HTML.CLASS_ATTR, getStyleClass(schedule,
+ "column"), null);
+ writer.writeAttribute(HTML.STYLE_ATTR, "height: 100%;", null);
+ writer.startElement(HTML.DIV_ELEM, schedule);
+ writer.writeAttribute(HTML.ID_ATTR, dayBodyId, null);
+ writer.writeAttribute(HTML.CLASS_ATTR, getStyleClass(schedule,
+ "column"), null);
+ writer
+ .writeAttribute(
+ HTML.STYLE_ATTR,
+ "position: relative; top: 0px; left: 0px; width: 100%; height: 100%; z-index: 0;",
+ null);
+ //register an onclick event listener to a column which will capture
+ //the y coordinate of the mouse, to determine the hour of day
+ if (!schedule.isReadonly() && schedule.isSubmitOnClick()) {
+ writer.writeAttribute(
+ HTML.ONMOUSEUP_ATTR,
+ "fireScheduleTimeClicked(this, event, '"
+ + formId + "', '"
+ + clientId
+ + "');",
+ null);
+ }
+ writeEntries(context, schedule, day, writer);
+ writer.endElement(HTML.DIV_ELEM);
+ writer.endElement(HTML.TD_ELEM);
+ }
+ }
+
+ /**
+ * @see javax.faces.render.Renderer#encodeEnd(javax.faces.context.FacesContext,
+ * javax.faces.component.UIComponent)
+ */
+ public void encodeEnd(FacesContext context, UIComponent component)
+ throws IOException
+ {
+ if (!component.isRendered())
+ {
+ return;
+ }
+
+ HtmlSchedule schedule = (HtmlSchedule) component;
+ ResponseWriter writer = context.getResponseWriter();
+
+ writeForegroundEnd(context, schedule, writer);
+ writer.endElement(HTML.DIV_ELEM);
+ }
+
+ private String getCellClass(HtmlSchedule schedule, int column, int row)
+ {
+ String cellClass = "free";
+ ScheduleDay day = (ScheduleDay) schedule.getModel().get(column);
+
+ if (!day.isWorkingDay())
+ {
+ return getStyleClass(schedule, cellClass);
+ }
+
+ if (((schedule.getVisibleStartHour() + (row / 2)) >= schedule
+ .getWorkingStartHour())
+ && ((schedule.getVisibleStartHour() + (row / 2)) < schedule
+ .getWorkingEndHour()))
+ {
+ cellClass = ((row % 2) == 0) ? "even" : "uneven";
+ }
+
+ return getStyleClass(schedule, cellClass);
+ }
+
+ private boolean isSelected(HtmlSchedule schedule, EntryWrapper entry)
+ {
+ ScheduleEntry selectedEntry = schedule.getModel().getSelectedEntry();
+
+ if (selectedEntry == null)
+ {
+ return false;
+ }
+
+ boolean returnboolean = selectedEntry.getId().equals(
+ entry.entry.getId());
+
+ return returnboolean;
+ }
+
+ private void maximizeEntries(EntryWrapper[] entries, int numberOfColumns)
+ {
+ for (int i = 0; i < entries.length; i++)
+ {
+ EntryWrapper entry = entries[i];
+
+ //now see if we can expand the entry to the columns on the right
+ while (((entry.column + entry.colspan) < numberOfColumns)
+ && entry.canFitInColumn(entry.column + entry.colspan))
+ {
+ entry.colspan++;
+ }
+ }
+ }
+
+ private void scanEntries(EntryWrapper[] entries, int index)
+ {
+ if (entries.length <= 0)
+ {
+ return;
+ }
+
+ EntryWrapper entry = entries[index];
+ entry.column = 0;
+
+ //see what columns are already taken
+ for (int i = 0; i < index; i++)
+ {
+ if (entry.overlaps(entries[i]))
+ {
+ entry.overlappingEntries.add(entries[i]);
+ entries[i].overlappingEntries.add(entry);
+ }
+ }
+
+ //find an available column
+ while (!entry.canFitInColumn(entry.column))
+ {
+ entry.column++;
+ }
+
+ //recursively scan the remaining entries for overlaps
+ if (++index < entries.length)
+ {
+ scanEntries(entries, index);
+ }
+ }
+
+ private void writeBackground(FacesContext context, HtmlSchedule schedule,
+ ResponseWriter writer) throws IOException
+ {
+ final int rowHeight = getRowHeight(schedule.getAttributes()) - 1;
+ final int headerHeight = rowHeight + 10;
+ writer.startElement(HTML.DIV_ELEM, schedule);
+ writer.writeAttribute(HTML.CLASS_ATTR, getStyleClass(schedule,
+ "background"), null);
+ writer
+ .writeAttribute(
+ HTML.STYLE_ATTR,
+ "position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; z-index: 0;",
+ null);
+
+ //background table for the schedule grid
+ writer.startElement(HTML.TABLE_ELEM, schedule);
+ writer.writeAttribute(HTML.CLASS_ATTR, getStyleClass(schedule,
+ "background"), null);
+ writer.writeAttribute(HTML.CELLPADDING_ATTR, "0", null);
+ writer.writeAttribute(HTML.CELLSPACING_ATTR, "1", null);
+ writer.writeAttribute(HTML.STYLE_ATTR, "width: 100%; height: 100%",
+ null);
+ writer.startElement(HTML.TBODY_ELEM, schedule);
+
+ //header row, containing the column names
+ writer.startElement(HTML.TR_ELEM, schedule);
+ writer.startElement(HTML.TD_ELEM, schedule);
+ writer.writeAttribute(HTML.CLASS_ATTR,
+ getStyleClass(schedule, "gutter"), null);
+ writer
+ .writeAttribute(
+ HTML.STYLE_ATTR,
+ "height: "
+ + rowHeight
+ + "px; border-style: none; border-width: 0px; overflow: hidden; padding: 0px",
+ null);
+ writer.startElement(HTML.DIV_ELEM, schedule);
+ writer
+ .writeAttribute(HTML.STYLE_ATTR, "height: 1px; width: 56px",
+ null);
+ writer.endElement(HTML.DIV_ELEM);
+ writer.endElement(HTML.TD_ELEM);
+
+ float columnWidth = (schedule.getModel().size() == 0) ? 100
+ : (100 / schedule.getModel().size());
+
+ for (Iterator dayIterator = schedule.getModel().iterator(); dayIterator
+ .hasNext();)
+ {
+ ScheduleDay day = (ScheduleDay) dayIterator.next();
+ writer.startElement(HTML.TD_ELEM, schedule);
+ writer.writeAttribute(HTML.CLASS_ATTR, getStyleClass(schedule,
+ "header"), null);
+ writer
+ .writeAttribute(
+ HTML.STYLE_ATTR,
+ "height: " + headerHeight + "px; border-style: none; border-width: 0px; overflow: hidden;",
+ null);
+ writer.writeAttribute(HTML.WIDTH_ATTR, String.valueOf(columnWidth)
+ + "%", null);
+ writer.startElement(HTML.DIV_ELEM, schedule);
+ writer
+ .writeAttribute(
+ HTML.STYLE_ATTR,
+ "position: relative; left: 0px; top: 0px; width: 100%; height: 100%;",
+ null);
+
+ //write the date
+ writer.startElement(HTML.SPAN_ELEM, schedule);
+ writer.writeAttribute(HTML.CLASS_ATTR, getStyleClass(schedule,
+ "date"), null);
+ writer
+ .writeAttribute(
+ HTML.STYLE_ATTR,
+ "position: absolute; left: 0px; top: 0px; height: 15px; width: 100%; vertical-align: top; overflow: hidden; white-space: nowrap;",
+ null);
+ writer.writeText(getDateString(context, schedule, day.getDate()),
+ null);
+ writer.endElement(HTML.SPAN_ELEM);
+
+ //write the name of the holiday, if there is one
+ if ((day.getSpecialDayName() != null)
+ && (day.getSpecialDayName().length() > 0))
+ {
+ writer.startElement(HTML.SPAN_ELEM, schedule);
+ writer.writeAttribute(HTML.CLASS_ATTR, getStyleClass(schedule,
+ "holiday"), null);
+ writer
+ .writeAttribute(
+ HTML.STYLE_ATTR,
+ "position: absolute; left: 0px; top: 15px; width: 100%; vertical-align: top; overflow: hidden; white-space: nowrap;",
+ null);
+ writer.writeText(day.getSpecialDayName(), null);
+ writer.endElement(HTML.SPAN_ELEM);
+ }
+
+ writer.endElement(HTML.DIV_ELEM);
+ writer.endElement(HTML.TD_ELEM);
+ }
+
+ writer.endElement(HTML.TR_ELEM);
+
+ int numberOfRows = (schedule.getVisibleEndHour() - schedule
+ .getVisibleStartHour()) * 2;
+
+ for (int row = 0; row < numberOfRows; row++)
+ {
+ writer.startElement(HTML.TR_ELEM, schedule);
+
+ //write the hours of the day on the left
+ //this only happens on even rows, or every hour
+ if ((row % 2) == 0)
+ {
+ writer.startElement(HTML.TD_ELEM, schedule);
+ writer.writeAttribute(HTML.CLASS_ATTR, getStyleClass(schedule,
+ "gutter"), null);
+ writer
+ .writeAttribute(
+ HTML.STYLE_ATTR,
+ "height: "
+ + rowHeight
+ + "px; border-style: none; border-width: 0px; overflow: hidden; padding: 0px",
+ null);
+ writer.writeAttribute("rowspan", "2", null);
+ writer.startElement(HTML.SPAN_ELEM, schedule);
+ writer.writeAttribute(HTML.CLASS_ATTR, getStyleClass(schedule,
+ "hours"), null);
+ writer.writeAttribute(HTML.STYLE_ATTR,
+ "vertical-align: top; height: 100%; padding: 0px;",
+ null);
+ writer.writeText(String.valueOf(schedule.getVisibleStartHour()
+ + (row / 2)), null);
+ writer.endElement(HTML.SPAN_ELEM);
+ writer.startElement(HTML.SPAN_ELEM, schedule);
+ writer.writeAttribute(HTML.CLASS_ATTR, getStyleClass(schedule,
+ "minutes"), null);
+ writer.writeAttribute(HTML.STYLE_ATTR,
+ "vertical-align: top; height: 100%; padding: 0px;",
+ null);
+ writer.writeText("00", null);
+ writer.endElement(HTML.SPAN_ELEM);
+ writer.endElement(HTML.TD_ELEM);
+ }
+
+ //write the cells of the day columns on this row
+ for (int column = 0; column < schedule.getModel().size(); column++)
+ {
+ writer.startElement(HTML.TD_ELEM, schedule);
+ writer.writeAttribute(HTML.CLASS_ATTR, getCellClass(schedule,
+ column, row), null);
+ writer.writeAttribute(HTML.STYLE_ATTR,
+ "overflow: hidden; height: " + rowHeight + "px;", null);
+ writer.writeAttribute(HTML.WIDTH_ATTR, String
+ .valueOf(columnWidth)
+ + "%", null);
+ writer.write(HTML.NBSP_ENTITY);
+ writer.endElement(HTML.TD_ELEM);
+ }
+
+ writer.endElement(HTML.TR_ELEM);
+ }
+
+ writer.endElement(HTML.TBODY_ELEM);
+ writer.endElement(HTML.TABLE_ELEM);
+ writer.endElement(HTML.DIV_ELEM);
+ }
+
+ private void writeEntries(FacesContext context, HtmlSchedule schedule,
+ ScheduleDay day, ResponseWriter writer) throws IOException
+ {
+ final UIForm parentForm = getParentForm(schedule);
+ final String clientId = schedule.getClientId(context);
+ final String formId = parentForm == null ? null : parentForm.getClientId(context);
+
+ TreeSet entrySet = new TreeSet();
+
+ for (Iterator entryIterator = day.iterator(); entryIterator.hasNext();)
+ {
+ entrySet.add(new EntryWrapper((ScheduleEntry) entryIterator.next(),
+ day));
+ }
+
+ EntryWrapper[] entries = (EntryWrapper[]) entrySet
+ .toArray(new EntryWrapper[entrySet.size()]);
+
+ //determine overlaps
+ scanEntries(entries, 0);
+
+ //determine the number of columns within this day
+ int maxColumn = 0;
+
+ for (Iterator entryIterator = entrySet.iterator(); entryIterator
+ .hasNext();)
+ {
+ EntryWrapper wrapper = (EntryWrapper) entryIterator.next();
+ maxColumn = Math.max(wrapper.column, maxColumn);
+ }
+
+ int numberOfColumns = maxColumn + 1;
+
+ //make sure the entries take up all available space horizontally
+ maximizeEntries(entries, numberOfColumns);
+
+ //now determine the width in percent of 1 column
+ float columnWidth = 100 / numberOfColumns;
+
+ //and now draw the entries in the columns
+ for (Iterator entryIterator = entrySet.iterator(); entryIterator
+ .hasNext();)
+ {
+ EntryWrapper wrapper = (EntryWrapper) entryIterator.next();
+ boolean selected = isSelected(schedule, wrapper);
+ //compose the CSS style for the entry box
+ StringBuffer entryStyle = new StringBuffer();
+ entryStyle.append(wrapper.getBounds(schedule, columnWidth));
+ String entryBorderColor = getEntryRenderer(schedule).getColor(
+ context, schedule, wrapper.entry, selected);
+ if (entryBorderColor != null)
+ {
+ entryStyle.append(" border-color: ");
+ entryStyle.append(entryBorderColor);
+ entryStyle.append(";");
+ }
+
+ if (selected)
+ {
+ writer.startElement(HTML.DIV_ELEM, schedule);
+ writer.writeAttribute(HTML.CLASS_ATTR, getStyleClass(schedule,
+ "entry-selected"), null);
+ writer.writeAttribute(HTML.STYLE_ATTR, entryStyle.toString(),
+ null);
+
+ //draw the tooltip
+ if (showTooltip(schedule))
+ {
+ getEntryRenderer(schedule).renderToolTip(context, writer,
+ schedule, wrapper.entry, selected);
+ }
+
+ //draw the content
+ getEntryRenderer(schedule).renderContent(context, writer,
+ schedule, day, wrapper.entry, false, selected);
+ writer.endElement(HTML.DIV_ELEM);
+ }
+ else
+ {
+ //if the schedule is read-only, the entries should not be
+ //hyperlinks
+ writer.startElement(
+ schedule.isReadonly() ? HTML.DIV_ELEM : HTML.ANCHOR_ELEM, schedule);
+
+ //draw the tooltip
+ if (showTooltip(schedule))
+ {
+ getEntryRenderer(schedule).renderToolTip(context, writer,
+ schedule, wrapper.entry, selected);
+ }
+
+ if (!schedule.isReadonly())
+ {
+ writer.writeAttribute("href", "#", null);
+
+ writer.writeAttribute(
+ HTML.ONMOUSEUP_ATTR,
+ "fireEntrySelected('"
+ + formId + "', '"
+ + clientId + "', '"
+ + wrapper.entry.getId()
+ + "');",
+ null);
+ }
+
+ writer.writeAttribute(HTML.CLASS_ATTR, getStyleClass(schedule,
+ "entry"), null);
+ writer.writeAttribute(HTML.STYLE_ATTR, entryStyle.toString(),
+ null);
+
+ //draw the content
+ getEntryRenderer(schedule).renderContent(context, writer,
+ schedule, day, wrapper.entry, false, selected);
+
+ writer.endElement(schedule.isReadonly() ? HTML.DIV_ELEM : "a");
+ }
+ }
+ }
+
+ private void writeForegroundEnd(FacesContext context,
+ HtmlSchedule schedule, ResponseWriter writer) throws IOException
+ {
+ writer.endElement(HTML.TR_ELEM);
+ writer.endElement(HTML.TABLE_ELEM);
+ writer.endElement(HTML.DIV_ELEM);
+ }
+
+ private void writeForegroundStart(FacesContext context,
+ HtmlSchedule schedule, ResponseWriter writer) throws IOException
+ {
+ final int rowHeight = getRowHeight(schedule.getAttributes()) - 1;
+ final int headerHeight = rowHeight + 10;
+ final String clientId = schedule.getClientId(context);
+ final UIForm parentForm = getParentForm(schedule);
+ final String formId = parentForm == null ? null : parentForm.getClientId(context);
+
+ writer.startElement(HTML.DIV_ELEM, schedule);
+ writer.writeAttribute(HTML.CLASS_ATTR, getStyleClass(schedule,
+ "foreground"), null);
+ writer
+ .writeAttribute(
+ HTML.STYLE_ATTR,
+ "position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; z-index: 2;",
+ null);
+
+ writer.startElement(HTML.TABLE_ELEM, schedule);
+ writer.writeAttribute(HTML.CLASS_ATTR, getStyleClass(schedule,
+ "foreground"), null);
+ writer.writeAttribute(HTML.CELLSPACING_ATTR, "1", null);
+ writer.writeAttribute(HTML.CELLPADDING_ATTR, "0", null);
+ writer.writeAttribute(HTML.STYLE_ATTR, "width: 100%; height: 100%",
+ null);
+ writer.startElement(HTML.TR_ELEM, schedule);
+ writer.startElement(HTML.TD_ELEM, schedule);
+ writer.startElement(HTML.DIV_ELEM, schedule);
+ writer
+ .writeAttribute(HTML.STYLE_ATTR, "height: 1px; width: 56px",
+ null);
+ writer.endElement(HTML.DIV_ELEM);
+ writer.endElement(HTML.TD_ELEM);
+
+ float columnWidth = (schedule.getModel().size() == 0) ? 100
+ : (100 / schedule.getModel().size());
+
+ for (Iterator dayIterator = schedule.getModel().iterator(); dayIterator
+ .hasNext();)
+ {
+ ScheduleDay day = (ScheduleDay) dayIterator.next();
+ final String dayHeaderId = clientId + "_header_" + ScheduleUtil.getDateId(day.getDate());
+ writer.startElement(HTML.TD_ELEM, schedule);
+ writer.writeAttribute(HTML.ID_ATTR, dayHeaderId, null);
+ writer.writeAttribute(HTML.CLASS_ATTR, getStyleClass(schedule,
+ "header"), null);
+ writer
+ .writeAttribute(
+ HTML.STYLE_ATTR,
+ "height: " + headerHeight + "px; border-style: none; border-width: 0px; overflow: hidden;",
+ null);
+ writer.writeAttribute(HTML.WIDTH_ATTR, String.valueOf(columnWidth)
+ + "%", null);
+ //register an onclick event listener to a column header which will
+ //be used to determine the date
+ if (!schedule.isReadonly() && schedule.isSubmitOnClick()) {
+ writer.writeAttribute(
+ HTML.ONMOUSEUP_ATTR,
+ "fireScheduleDateClicked(this, event, '"
+ + formId + "', '"
+ + clientId
+ + "');",
+ null);
+ }
+
+ writer.endElement(HTML.TD_ELEM);
+ }
+
+ writer.endElement(HTML.TR_ELEM);
+
+ writer.startElement(HTML.TR_ELEM, schedule);
+ writer.startElement(HTML.TD_ELEM, schedule);
+ writer.startElement(HTML.DIV_ELEM, schedule);
+ writer
+ .writeAttribute(HTML.STYLE_ATTR, "height: 1px; width: 56px",
+ null);
+ writer.endElement(HTML.DIV_ELEM);
+ writer.endElement(HTML.TD_ELEM);
+ }
+
+ //~ Inner Classes ----------------------------------------------------------
+
+ protected String getRowHeightProperty()
+ {
+ return "detailedRowHeight";
+ }
+
+ protected int getDefaultRowHeight()
+ {
+ return defaultRowHeightInPixels;
+ }
+
+ /**
+ * In the detailed day renderer, we take the y coordinate of the mouse
+ * into account when determining the last clicked date.
+ */
+ protected Date determineLastClickedDate(HtmlSchedule schedule, String dateId, String yPos) {
+ Calendar cal = GregorianCalendar.getInstance();
+ //the dateId is the schedule client id + "_" + yyyyMMdd
+ String day = dateId.substring(dateId.lastIndexOf("_") + 1);
+ Date date = ScheduleUtil.getDateFromId(day);
+
+ if (date != null) cal.setTime(date);
+ cal.set(Calendar.HOUR_OF_DAY, schedule.getVisibleStartHour());
+ //OK, we have the date, let's determine the time
+ try {
+ int y = Integer.parseInt(yPos);
+ int halfHourHeight = getRowHeight(schedule.getAttributes());
+ int minutes = y * 30 / halfHourHeight;
+ cal.add(Calendar.MINUTE, minutes);
+ } catch (NumberFormatException nfe) {
+ log.debug("y position is not a number");
+ }
+ log.debug("last clicked datetime: " + cal.getTime());
+ return cal.getTime();
+ }
+
+ private class EntryWrapper implements Comparable
+ {
+ //~ Static fields/initializers -----------------------------------------
+
+ private static final int HALF_HOUR = 1000 * 60 * 30;
+
+ //~ Instance fields ----------------------------------------------------
+
+ private final ScheduleDay day;
+ private final ScheduleEntry entry;
+ private final TreeSet overlappingEntries;
+ private int colspan;
+ private int column;
+
+ //~ Constructors -------------------------------------------------------
+
+ EntryWrapper(ScheduleEntry entry, ScheduleDay day)
+ {
+ this.entry = entry;
+ this.day = day;
+ this.column = 0;
+ this.colspan = 1;
+ this.overlappingEntries = new TreeSet();
+ }
+
+ //~ Methods ------------------------------------------------------------
+
+ /**
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(Object o)
+ {
+ return comparator.compare(entry, o);
+ }
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object o)
+ {
+ if (o instanceof EntryWrapper)
+ {
+ EntryWrapper other = (EntryWrapper) o;
+
+ boolean returnboolean = (entry.getStartTime()
+ .equals(other.entry.getStartTime()))
+ && (entry.getEndTime().equals(other.entry.getEndTime()))
+ && (entry.getId().equals(other.entry.getId()))
+ && (day.equals(other.day));
+ /*
+ new EqualsBuilder().append(
+ entry.getStartTime(), other.entry.getStartTime()
+ ).append(entry.getEndTime(), other.entry.getEndTime())
+ .append(
+ entry.getId(), other.entry.getId()
+ ).append(day, other.day).isEquals();
+ */
+ return returnboolean;
+ }
+
+ return false;
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode()
+ {
+ int returnint = entry.getStartTime().hashCode()
+ ^ entry.getEndTime().hashCode() ^ entry.getId().hashCode();
+
+ return returnint;
+ }
+
+ /**
+ * <p>
+ * Determine the bounds of this entry, in CSS position attributes
+ * </p>
+ *
+ * @param schedule the schedule
+ * @param columnWidth the width of a column
+ *
+ * @return the bounds
+ */
+ String getBounds(HtmlSchedule schedule, float columnWidth)
+ {
+ int rowHeight = getRowHeight(schedule.getAttributes());
+ float width = (columnWidth * colspan) - 0.5f;
+ float left = column * columnWidth;
+ Calendar cal = GregorianCalendar.getInstance();
+ cal.setTime(day.getDate());
+
+ int curyear = cal.get(Calendar.YEAR);
+ int curmonth = cal.get(Calendar.MONTH);
+ int curday = cal.get(Calendar.DATE);
+
+ cal.setTime(entry.getStartTime());
+ cal.set(curyear, curmonth, curday);
+
+ long startMillis = cal.getTimeInMillis();
+ cal.set(Calendar.HOUR_OF_DAY, schedule.getVisibleStartHour());
+ cal.set(Calendar.MINUTE, 0);
+ cal.set(Calendar.SECOND, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+
+ long visibleStartMillis = cal.getTimeInMillis();
+ startMillis = day.equalsDate(entry.getStartTime()) ? Math.max(
+ startMillis, visibleStartMillis) : visibleStartMillis;
+ cal.setTime(entry.getEndTime());
+ cal.set(curyear, curmonth, curday);
+
+ long endMillis = cal.getTimeInMillis();
+ cal.set(Calendar.HOUR_OF_DAY, schedule.getVisibleEndHour());
+ cal.set(Calendar.MINUTE, 0);
+ cal.set(Calendar.SECOND, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+
+ long visibleEndMillis = cal.getTimeInMillis();
+ endMillis = day.equalsDate(entry.getEndTime()) ? Math.min(
+ endMillis, visibleEndMillis) : visibleEndMillis;
+
+ int top = (int) (((startMillis - visibleStartMillis) * rowHeight) / HALF_HOUR);
+ int height = (int) (((endMillis - startMillis) * rowHeight) / HALF_HOUR);
+ StringBuffer buffer = new StringBuffer();
+
+ if (height <= 0)
+ {
+ buffer.append("visibility: hidden; ");
+ }
+ buffer.append("position: absolute; height: ");
+ buffer.append(height);
+ buffer.append("px; top: ");
+ buffer.append(top);
+ buffer.append("px; left: ");
+ buffer.append(left);
+ buffer.append("%; width: ");
+ buffer.append(width);
+ buffer
+ .append("%; padding: 0px; overflow: hidden; border-width: 1.0px; border-style:solid;");
+
+ return buffer.toString();
+ }
+
+ /**
+ * <p>
+ * Can this entry fit in the specified column?
+ * </p>
+ *
+ * @param column the column
+ *
+ * @return whether the entry fits
+ */
+ boolean canFitInColumn(int column)
+ {
+ for (Iterator overlapIterator = overlappingEntries.iterator(); overlapIterator
+ .hasNext();)
+ {
+ EntryWrapper overlap = (EntryWrapper) overlapIterator.next();
+
+ if (overlap.column == column)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * <p>
+ * Does this entry overlap with another?
+ * </p>
+ *
+ * @param other the other entry
+ *
+ * @return whether the entries overlap
+ */
+ boolean overlaps(EntryWrapper other)
+ {
+ if ((entry.getStartTime() == null) || (entry.getEndTime() == null))
+ {
+ return false;
+ }
+
+ boolean returnboolean = (entry.getStartTime().before(
+ other.entry.getEndTime()) && entry.getEndTime().after(
+ other.entry.getStartTime()));
+
+ return returnboolean;
+ }
+ }
+}
+//The End
Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/renderer/ScheduleEntryRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/renderer/ScheduleEntryRenderer.java?rev=410011&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/renderer/ScheduleEntryRenderer.java (added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/renderer/ScheduleEntryRenderer.java Sun May 28 18:59:05 2006
@@ -0,0 +1,96 @@
+package org.apache.myfaces.custom.schedule.renderer;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.apache.myfaces.custom.schedule.HtmlSchedule;
+import org.apache.myfaces.custom.schedule.model.ScheduleDay;
+import org.apache.myfaces.custom.schedule.model.ScheduleEntry;
+
+/**
+ * <p>
+ * The ScheduleEntryRenderer is responsible for rendering the content and the
+ * tooltip of a ScheduleEntry.
+ * </p>
+ * <p>
+ * Note that the box around the entry is rendered by the ScheduleRenderer,
+ * because determining the position and size of the box cannot be done
+ * independent of the other entries.
+ * </p>
+ * <p>
+ * The color of the box can be set using the getEntryColor method. This allows a
+ * developer to use different colors for the entries of different users for
+ * example.
+ * </p>
+ *
+ * @author Jurgen Lust (latest modification by $Author$)
+ * @version $Revision$
+ */
+public interface ScheduleEntryRenderer extends Serializable
+{
+ /**
+ * Render the content of an entry.
+ *
+ * @param context
+ * the FacesContext
+ * @param writer
+ * the ResponseWriter
+ * @param schedule
+ * the Schedule component
+ * @param day the current day
+ * @param entry
+ * the entry that should be rendered
+ * @param compact
+ * is the schedule rendered in a compact mode?
+ * @param selected
+ * whether or not the entry is currently selected
+ * @throws IOException
+ * when the output cannot be written
+ */
+ public void renderContent(FacesContext context,
+ ResponseWriter writer, HtmlSchedule schedule, ScheduleDay day,
+ ScheduleEntry entry, boolean compact, boolean selected) throws IOException;
+
+ /**
+ * Get the color of an entry. The border around the entry will be rendered
+ * in this color. The return value of this method should be a CSS2 color
+ * specification, such as #000000 or rgb(0,0,0). If the return value is
+ * null, then the current theme's default color will be used.
+ *
+ * @param context
+ * the FacesContext
+ * @param schedule
+ * the Schedule component
+ * @param entry
+ * the entry
+ * @param selected
+ * whether or not the entry is currently selected
+ * @return the color
+ */
+ public String getColor(FacesContext context, HtmlSchedule schedule,
+ ScheduleEntry entry, boolean selected);
+
+ /**
+ * Render the tooltip of a ScheduleEntry. This method will only be called if
+ * the schedule's tooltip property is set to 'true'.
+ *
+ * @param context
+ * the FacesContext
+ * @param writer
+ * the ResponseWriter
+ * @param schedule
+ * the Schedule component
+ * @param entry
+ * the entry
+ * @param selected
+ * whether or not the entry is currently selected
+ * @throws IOException
+ * when the output cannot be written
+ */
+ public void renderToolTip(FacesContext context, ResponseWriter writer,
+ HtmlSchedule schedule, ScheduleEntry entry, boolean selected)
+ throws IOException;
+}
Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/util/ScheduleEntryComparator.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/util/ScheduleEntryComparator.java?rev=410011&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/util/ScheduleEntryComparator.java (added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/util/ScheduleEntryComparator.java Sun May 28 18:59:05 2006
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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 org.apache.myfaces.custom.schedule.util;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+import org.apache.myfaces.custom.schedule.model.ScheduleEntry;
+
+/**
+ * <p>
+ * Comparator for ScheduleEntry objects. This is needed for correctly
+ * rendering the schedule.
+ * </p>
+ *
+ * @author Jurgen Lust (latest modification by $Author: schof $)
+ * @author Bruno Aranda (adaptation of Jurgen's code to myfaces)
+ * @version $Revision: 381473 $
+ */
+public class ScheduleEntryComparator implements Comparator, Serializable
+{
+ private static final long serialVersionUID = 6863061256811196989L;
+
+ //~ Methods ----------------------------------------------------------------
+
+ /**
+ * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+ */
+ public int compare(Object o1, Object o2)
+ {
+ if (o1 instanceof ScheduleEntry && o2 instanceof ScheduleEntry)
+ {
+ ScheduleEntry entry1 = (ScheduleEntry) o1;
+ ScheduleEntry entry2 = (ScheduleEntry) o2;
+
+ int returnint = entry1.getStartTime().compareTo(
+ entry2.getStartTime());
+ if (returnint == 0)
+ {
+ returnint = entry1.getEndTime().compareTo(entry2.getEndTime());
+ }
+ if (returnint == 0)
+ {
+ returnint = entry1.getId().compareTo(entry2.getId());
+ }
+
+ return returnint;
+ }
+
+ return 1;
+ }
+}
+//The End
Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/util/ScheduleUtil.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/util/ScheduleUtil.java?rev=410011&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/util/ScheduleUtil.java (added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/schedule/util/ScheduleUtil.java Sun May 28 18:59:05 2006
@@ -0,0 +1,424 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * 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 org.apache.myfaces.custom.schedule.util;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.el.ValueBinding;
+
+
+/**
+ * <p>
+ * Some utility methods
+ * </p>
+ *
+ * @author Jurgen Lust (latest modification by $Author: jlust $)
+ * @author Kito Mann (some methods taken from the source code of his book 'JavaServer Faces in Action', which is also released under the Apache License
+ * @author Bruno Aranda (adaptation of Jurgen's code to myfaces)
+ * @version $Revision: 387334 $
+ */
+public class ScheduleUtil
+{
+ //~ Class Variables --------------------------------------------------------
+ private final static SimpleDateFormat DATE_ID_FORMATTER = new SimpleDateFormat("yyyyMMdd");
+
+ //~ Methods ----------------------------------------------------------------
+
+ /**
+ * <p>
+ * Check if the value of a UIComponent is a value or method binding
+ * expression.
+ * </p>
+ *
+ * @param value the value to check
+ *
+ * @return whether the value is a binding expression
+ */
+ public static boolean isBindingExpression(Object value)
+ {
+ boolean returnboolean =
+ ((value != null) && value instanceof String &&
+ ((String) value).startsWith("#{") &&
+ ((String) value).endsWith("}"));
+
+ return returnboolean;
+ }
+
+ /**
+ * <p>
+ * Get the boolean value of a UIComponent, even if it is a value
+ * binding expression.
+ * </p>
+ *
+ * @param component the component
+ * @param property the property
+ * @param key the key of the value binding
+ * @param defaultValue the default value
+ *
+ * @return the boolean value
+ */
+ public static boolean getBooleanProperty(
+ UIComponent component,
+ Boolean property,
+ String key,
+ boolean defaultValue
+ )
+ {
+ if (property != null) {
+ return property.booleanValue();
+ } else {
+ ValueBinding binding =
+ (ValueBinding) component.getValueBinding(key);
+
+ if (binding != null) {
+ Boolean value =
+ (Boolean) binding.getValue(
+ FacesContext.getCurrentInstance()
+ );
+
+ if (value != null) {
+ return value.booleanValue();
+ }
+ }
+ }
+
+ return defaultValue;
+ }
+
+ /**
+ * <p>
+ * Get the boolean value of an attribute
+ * </p>
+ *
+ * @param attributeValue the attribute value
+ * @param valueIfNull the default value
+ *
+ * @return the boolean value
+ */
+ public static boolean getBooleanValue(
+ Object attributeValue,
+ boolean valueIfNull
+ )
+ {
+ if (attributeValue == null) {
+ return valueIfNull;
+ }
+
+ if (attributeValue instanceof String) {
+ return ((String) attributeValue).equalsIgnoreCase("true");
+ } else {
+ return ((Boolean) attributeValue).booleanValue();
+ }
+ }
+
+ /**
+ * <p>
+ * Get the float value of a UIComponent, even if it is a value
+ * binding expression.
+ * </p>
+ *
+ * @param component the component
+ * @param property the property
+ * @param key the key of the value binding
+ * @param defaultValue the default value
+ *
+ * @return the float value
+ */
+ public static float getFloatProperty(
+ UIComponent component,
+ Float property,
+ String key,
+ float defaultValue
+ )
+ {
+ if (property != null) {
+ return property.floatValue();
+ } else {
+ ValueBinding binding =
+ (ValueBinding) component.getValueBinding(key);
+
+ if (binding != null) {
+ Float value =
+ (Float) binding.getValue(FacesContext.getCurrentInstance());
+
+ if (value != null) {
+ return value.floatValue();
+ }
+ }
+ }
+
+ return defaultValue;
+ }
+
+ /**
+ * <p>
+ * Get the hashcode for the truncated date
+ * </p>
+ *
+ * @param date the date
+ *
+ * @return the hashCode of the truncated date
+ */
+ public static int getHashCodeForDay(Date date)
+ {
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(date);
+
+ return new Integer(calendar.get(Calendar.ERA)).hashCode() ^
+ new Integer(calendar.get(Calendar.YEAR)).hashCode() ^
+ new Integer(calendar.get(Calendar.DAY_OF_YEAR)).hashCode();
+ }
+
+ /**
+ * <p>
+ * Get the int value of a UIComponent, even if it is a value
+ * binding expression.
+ * </p>
+ *
+ * @param component the component
+ * @param property the property
+ * @param key the key of the value binding
+ * @param defaultValue the default value
+ *
+ * @return the int value
+ */
+ public static int getIntegerProperty(
+ UIComponent component,
+ Integer property,
+ String key,
+ int defaultValue
+ )
+ {
+ if (property != null) {
+ return property.intValue();
+ } else {
+ ValueBinding binding =
+ (ValueBinding) component.getValueBinding(key);
+
+ if (binding != null) {
+ Integer value =
+ (Integer) binding.getValue(
+ FacesContext.getCurrentInstance()
+ );
+
+ if (value != null) {
+ return value.intValue();
+ }
+ }
+ }
+
+ return defaultValue;
+ }
+
+ /**
+ * <p>
+ * Get the object value of a UIComponent, even if it is a value
+ * binding expression.
+ * </p>
+ *
+ * @param component the component
+ * @param property the property
+ * @param key the key of the value binding
+ * @param defaultValue the default value
+ *
+ * @return the object value
+ */
+ public static Object getObjectProperty(
+ UIComponent component,
+ Object property,
+ String key,
+ Object defaultValue
+ )
+ {
+ if (property != null) {
+ return property;
+ } else {
+ ValueBinding binding =
+ (ValueBinding) component.getValueBinding(key);
+
+ if (binding != null) {
+ return binding.getValue(FacesContext.getCurrentInstance());
+ }
+ }
+
+ return defaultValue;
+ }
+
+ /**
+ * <p>
+ * Check if the 2 dates are in the same day.
+ * </p>
+ *
+ * @param date1 the first date
+ * @param date2 the second date
+ *
+ * @return whether the dates are in the same day
+ */
+ public static boolean isSameDay(
+ Date date1,
+ Date date2
+ )
+ {
+ if ((date1 == null) || (date2 == null)) {
+ return false;
+ }
+
+ Calendar calendar1 = Calendar.getInstance();
+ calendar1.setTime(date1);
+
+ Calendar calendar2 = Calendar.getInstance();
+ calendar2.setTime(date2);
+
+ return (calendar1.get(Calendar.ERA) == calendar2.get(Calendar.ERA) &&
+ calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR) &&
+ calendar1.get(Calendar.DAY_OF_YEAR) == calendar2.get(Calendar.DAY_OF_YEAR));
+ }
+
+ /**
+ * <p>
+ * Get the String value of a UIComponent, even if it is a value
+ * binding expression.
+ * </p>
+ *
+ * @param component the component
+ * @param property the property
+ * @param key the key of the value binding
+ * @param defaultValue the default value
+ *
+ * @return the String value
+ */
+ public static String getStringProperty(
+ UIComponent component,
+ String property,
+ String key,
+ String defaultValue
+ )
+ {
+ if (property != null) {
+ return property;
+ } else {
+ ValueBinding binding =
+ (ValueBinding) component.getValueBinding(key);
+
+ if (binding != null) {
+ return (String) binding.getValue(
+ FacesContext.getCurrentInstance()
+ );
+ }
+ }
+
+ return defaultValue;
+ }
+
+ /**
+ * <p>
+ * Check if the value of the given component can be modified
+ * </p>
+ *
+ * @param component the component
+ *
+ * @return whether the value can be modified
+ */
+ public static boolean canModifyValue(UIComponent component)
+ {
+ boolean returnboolean =
+ (component.isRendered() &&
+ !getBooleanValue(component.getAttributes().get("readonly"), false) &&
+ !getBooleanValue(component.getAttributes().get("disabled"), false));
+
+ return returnboolean;
+ }
+
+ /**
+ * <p>
+ * Compare 2 dates after truncating them.
+ * </p>
+ *
+ * @param date1 the first date
+ * @param date2 the second date
+ *
+ * @return the comparison
+ */
+ public static int compareDays(
+ Date date1,
+ Date date2
+ )
+ {
+ if (date1 == null) {
+ return -1;
+ }
+
+ if (date2 == null) {
+ return 1;
+ }
+
+ return truncate(date1).compareTo(truncate(date2));
+ }
+
+ /**
+ * truncate the given Date to 00:00:00 that same day
+ *
+ * @param date the date that should be truncated
+ * @return the truncated date
+ */
+ public static Date truncate(Date date) {
+ if (date == null) return null;
+ Calendar cal = GregorianCalendar.getInstance();
+ cal.setTime(date);
+ cal.set(Calendar.HOUR_OF_DAY, 0);
+ cal.set(Calendar.MINUTE, 0);
+ cal.set(Calendar.SECOND, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+ return cal.getTime();
+ }
+
+ /**
+ * get a String identifying this date
+ *
+ * @param date the date
+ * @return the identifier for this date
+ */
+ public static String getDateId(Date date) {
+ if (date == null) return "NULL";
+ return DATE_ID_FORMATTER.format(date);
+ }
+
+ /**
+ * get a date from the given date ID
+ *
+ * @param id the date ID
+ * @return the date
+ */
+ public static Date getDateFromId(String id) {
+ if (id == null || id.length() == 0 || "null".equals(id)) return null;
+ try
+ {
+ return DATE_ID_FORMATTER.parse(id);
+ }
+ catch (ParseException e)
+ {
+ return null;
+ }
+ }
+}
+//The End
Modified: myfaces/tomahawk/trunk/core/src/main/resources-facesconfig/META-INF/faces-config.xml
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/resources-facesconfig/META-INF/faces-config.xml?rev=410011&r1=410010&r2=410011&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/resources-facesconfig/META-INF/faces-config.xml (original)
+++ myfaces/tomahawk/trunk/core/src/main/resources-facesconfig/META-INF/faces-config.xml Sun May 28 18:59:05 2006
@@ -359,6 +359,11 @@
<component-class>org.apache.myfaces.custom.savestate.UISaveState</component-class>
</component>
+ <component>
+ <component-type>org.apache.myfaces.Schedule</component-type>
+ <component-class>org.apache.myfaces.custom.schedule.HtmlSchedule</component-class>
+ </component>
+
<component>
<component-type>org.apache.myfaces.SelectOneCountry</component-type>
<component-class>org.apache.myfaces.custom.selectOneCountry.SelectOneCountry</component-class>
@@ -373,6 +378,7 @@
<component-type>org.apache.myfaces.Stylesheet</component-type>
<component-class>org.apache.myfaces.custom.stylesheet.Stylesheet</component-class>
</component>
+
<!-- additional "by type" converters -->
@@ -779,6 +785,16 @@
<renderer-type>org.apache.myfaces.SwapImage</renderer-type>
<renderer-class>org.apache.myfaces.custom.swapimage.HtmlSwapImageRenderer</renderer-class>
</renderer>
+
+ <renderer>
+ <component-family>javax.faces.Panel</component-family>
+ <renderer-type>org.apache.myfaces.Schedule</renderer-type>
+ <renderer-class>
+ org.apache.myfaces.custom.schedule.renderer.ScheduleDelegatingRenderer
+ </renderer-class>
+ </renderer>
+
+
</render-kit>
Added: myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/schedule/HtmlSchedule.xml
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/schedule/HtmlSchedule.xml?rev=410011&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/schedule/HtmlSchedule.xml (added)
+++ myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/schedule/HtmlSchedule.xml Sun May 28 18:59:05 2006
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE component PUBLIC
+ "-//MyFaces//DTD MyFaces component def 1.0//EN"
+ "http://myfaces.apache.org/dtd/Component.dtd">
+<component>
+ <component-class>org.apache.myfaces.custom.schedule.HtmlSchedule</component-class>
+ <base-class>org.apache.myfaces.custom.schedule.UISchedule</base-class>
+ <component-type>org.apache.myfaces.Schedule</component-type>
+ <component-family>javax.faces.Panel</component-family>
+ <renderer-type>org.apache.myfaces.Schedule</renderer-type>
+ <field>
+ <name>enabledOnUserRole</name>
+ <type>java.lang.String</type>
+ </field>
+ <field>
+ <name>visibleOnUserRole</name>
+ <type>java.lang.String</type>
+ </field>
+</component>
Added: myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/schedule/resource/css/schedule.css
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/schedule/resource/css/schedule.css?rev=410011&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/schedule/resource/css/schedule.css (added)
+++ myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/schedule/resource/css/schedule.css Sun May 28 18:59:05 2006
@@ -0,0 +1,682 @@
+/******************************************************************************/
+/* Default theme */
+/******************************************************************************/
+
+/* PART I: Detailed Day Renderer */
+
+div.schedule-detailed-default {
+ border-style: solid;
+ border-width: 1px;
+ border-color: rgb(153,153,153);
+ position: relative;
+ width: 100%;
+ left: 0px;
+ right: 0px;
+}
+
+div.schedule-detailed-default table.background {
+ background-color: rgb(255,255,255);
+}
+
+div.schedule-detailed-default td.gutter {
+ background-color: rgb(181,200,207);
+ color: rgb(0,0,0);
+ text-align: right;
+ vertical-align: top;
+}
+
+div.schedule-detailed-default table.background td.header, div.schedule-detailed-default table.foreground td.header {
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 10px;
+ color: rgb(0,0,0);
+ text-align: center;
+ vertical-align: middle;
+}
+
+div.schedule-detailed-default table.background td.header {
+ background-color: rgb(181,200,207);
+}
+
+div.schedule-detailed-default td.header span.date, div.schedule-detailed-default td.header span.holiday {
+ text-align: center;
+}
+
+div.schedule-detailed-default td.header span.date {
+}
+
+div.schedule-detailed-default td.header span.holiday {
+}
+
+div.schedule-detailed-default td.gutter span.hours {
+ font-size: 26px;
+}
+
+div.schedule-detailed-default td.gutter span.minutes {
+ font-size: 13px;
+}
+
+div.schedule-detailed-default table.background td.even,
+div.schedule-detailed-default table.background td.uneven,
+div.schedule-detailed-default table.background td.free {
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 10px;
+ text-align: center;
+}
+
+div.schedule-detailed-default table.background td.uneven {
+ background-color: rgb(240,240,240);
+ color: rgb(240,240,240);
+}
+
+div.schedule-detailed-default table.background td.even {
+ background-color: rgb(235,235,235);
+ color: rgb(235,235,235);
+}
+
+div.schedule-detailed-default table.background td.free {
+ background-color: rgb(221,221,221);
+ color: rgb(221,221,221);
+}
+
+div.schedule-detailed-default .entry, div.schedule-detailed-default div.entry-selected {
+ background-color: rgb(255,255,255);
+ text-align: center;
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 11px;
+ vertical-align: middle;
+ border-color: rgb(153,153,153);
+ text-decoration: none;
+}
+
+div.schedule-detailed-default a.entry:hover,
+div.schedule-detailed-default div.entry-selected {
+ border-color: rgb(153,0,0);
+}
+
+div.schedule-detailed-default div.entry-selected div.text {
+ border-left: solid rgb(153,0,0) 5.0px;
+}
+
+div.schedule-detailed-default .entry span.subtitle,
+div.schedule-detailed-default .entry-selected span.subtitle {
+ font-style: italic;
+ font-size: 9px;
+}
+
+div.schedule-detailed-default .entry span.title,
+div.schedule-detailed-default .entry-selected span.title {
+ font-size: 11px;
+}
+
+
+
+/* PART II: Compact Renderer */
+div.schedule-compact-default {
+ position: relative;
+ width: 100%;
+ left: 0px;
+ background-color: rgb(153,153,153);
+}
+
+div.schedule-compact-default table.day {
+ background-color: rgb(255,255,255);
+}
+
+div.schedule-compact-default table.day td.header {
+ background-color: rgb(181,200,207);
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 10px;
+ color: rgb(0,0,0);
+ text-align: left;
+ vertical-align: middle;
+}
+
+div.schedule-compact-default td.content div {
+}
+
+div.schedule-compact-default td.content td {
+ background-color: rgb(255,255,255);
+ color: rgb(0,0,0);
+ text-align: left;
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 11px;
+ padding: 1px;
+ border-color: rgb(255,255,255);
+ border-width: 1.0px;
+ border-style: solid;
+}
+
+div.schedule-compact-default a {
+ text-decoration: none;
+ color: rgb(0,0,0);
+ text-align: left;
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 11px;
+}
+
+div.schedule-compact-default td.content td.selected {
+ background-color: rgb(153,0,0);
+ border-color: rgb(153,0,0);
+ color: rgb(255,255,255);
+}
+
+div.schedule-compact-default td.inactive-day td.content {
+ background-color: rgb(221,221,221);
+ visibility: visible;
+}
+
+div.schedule-compact-default td.inactive-day td.content td {
+ background-color: rgb(221,221,221);
+ border-color: rgb(221,221,221);
+}
+
+div.schedule-compact-default td.inactive-day td.content td.selected {
+ background-color: rgb(153,0,0);
+ border-color: rgb(153,0,0);
+ color: rgb(255,255,255);
+}
+
+div.schedule-compact-default td.inactive-day td.header {
+ background-color: rgb(221,221,221);
+ visibility: visible;
+}
+
+
+/******************************************************************************/
+/* Evolution theme */
+/******************************************************************************/
+/* PART I: Detailed Day Renderer */
+
+div.schedule-detailed-evolution {
+ border-style: solid;
+ border-width: 1px;
+ border-color: rgb(255,255,255);
+ position: relative;
+ width: 100%;
+ left: 0px;
+ right: 0px;
+}
+
+div.schedule-detailed-evolution table.background {
+ background-color: rgb(172,172,172);
+}
+
+div.schedule-detailed-evolution td.gutter {
+ background-color: rgb(246,246,246);
+ color: rgb(0,0,0);
+ text-align: right;
+ vertical-align: top;
+}
+
+div.schedule-detailed-evolution table.background td.header, div.schedule-detailed-evolution table.foreground td.header {
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 10px;
+ color: rgb(0,0,0);
+ text-align: center;
+ vertical-align: middle;
+}
+
+div.schedule-detailed-evolution table.background td.header {
+ background-color: rgb(246,246,246);
+}
+
+div.schedule-detailed-evolution td.header span.date, div.schedule-detailed-evolution td.header span.holiday {
+ text-align: center;
+}
+
+div.schedule-detailed-evolution td.header span.date {
+}
+
+div.schedule-detailed-evolution td.header span.holiday {
+}
+
+div.schedule-detailed-evolution td.gutter span.hours {
+ font-size: 26px;
+}
+
+div.schedule-detailed-evolution td.gutter span.minutes {
+ font-size: 13px;
+}
+
+div.schedule-detailed-evolution table.background td.even,
+div.schedule-detailed-evolution table.background td.uneven,
+div.schedule-detailed-evolution table.background td.free {
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 10px;
+ text-align: center;
+}
+
+div.schedule-detailed-evolution table.background td.uneven {
+ background-color: rgb(255,255,255);
+ color: rgb(255,255,255);
+}
+
+div.schedule-detailed-evolution table.background td.even {
+ background-color: rgb(255,255,255);
+ color: rgb(255,255,255);
+}
+
+div.schedule-detailed-evolution table.background td.free {
+ background-color: rgb(217,217,217);
+ color: rgb(217,217,217);
+}
+
+div.schedule-detailed-evolution .entry, div.schedule-detailed-evolution div.entry-selected {
+ background-color: rgb(190,206,221);
+ text-align: center;
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 11px;
+ vertical-align: middle;
+ border-color: rgb(172,172,172);
+ text-decoration: none;
+}
+
+div.schedule-detailed-evolution a.entry:hover,
+div.schedule-detailed-evolution div.entry-selected {
+ border-color: rgb(100,132,164);
+}
+
+div.schedule-detailed-evolution div.entry-selected div.text {
+ border-left: solid rgb(100,132,164) 5.0px;
+}
+
+div.schedule-detailed-evolution .entry span.subtitle,
+div.schedule-detailed-evolution .entry-selected span.subtitle {
+ font-style: italic;
+ font-size: 9px;
+}
+
+div.schedule-detailed-evolution .entry span.title,
+div.schedule-detailed-evolution .entry-selected span.title {
+ font-size: 11px;
+}
+
+
+
+/* PART II: Compact Renderer */
+div.schedule-compact-evolution {
+ position: relative;
+ width: 100%;
+ left: 0px;
+ background-color: rgb(172,172,172);
+}
+
+div.schedule-compact-evolution table.day {
+ background-color: rgb(255,255,255);
+}
+
+div.schedule-compact-evolution table.day td.header {
+ background-color: rgb(255,255,255);
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 10px;
+ color: rgb(0,0,0);
+ text-align: left;
+ vertical-align: middle;
+ border-bottom-color: rgb(172,172,172);
+ border-bottom-style: solid;
+ border-bottom-width: 1px;
+}
+
+div.schedule-compact-evolution td.content div {
+}
+
+div.schedule-compact-evolution td.content td {
+ background-color: rgb(255,255,255);
+ color: rgb(0,0,0);
+ text-align: left;
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 11px;
+ padding: 1px;
+ border-color: rgb(255,255,255);
+ border-width: 1.0px;
+ border-style: solid;
+}
+
+div.schedule-compact-evolution a {
+ text-decoration: none;
+ color: rgb(0,0,0);
+ text-align: left;
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 11px;
+}
+
+div.schedule-compact-evolution td.content td.selected {
+ background-color: rgb(190,206,221);
+ border-color: rgb(190,206,221);
+}
+
+div.schedule-compact-evolution td.inactive-day td.content {
+ background-color: rgb(238,235,231);
+ visibility: visible;
+}
+
+div.schedule-compact-evolution td.inactive-day td.content td {
+ background-color: rgb(238,235,231);
+ border-color: rgb(238,235,231);
+}
+
+div.schedule-compact-evolution td.inactive-day td.content td.selected {
+ background-color: rgb(190,206,221);
+ border-color: rgb(190,206,221);
+}
+
+div.schedule-compact-evolution td.inactive-day td.header {
+ background-color: rgb(238,235,231);
+ visibility: visible;
+}
+
+
+/******************************************************************************/
+/* Outlook XP theme */
+/******************************************************************************/
+/* PART I: Detailed Day Renderer */
+
+div.schedule-detailed-outlookxp {
+ border-style: solid;
+ border-width: 1px;
+ border-color: rgb(128,128,128);
+ position: relative;
+ width: 100%;
+ left: 0px;
+ right: 0px;
+}
+
+div.schedule-detailed-outlookxp table.background {
+ background-color: rgb(128,128,128);
+}
+
+div.schedule-detailed-outlookxp td.gutter {
+ background-color: rgb(219,216,209);
+ color: rgb(0,0,0);
+ text-align: right;
+ vertical-align: top;
+}
+
+div.schedule-detailed-outlookxp table.background td.header, div.schedule-detailed-outlookxp table.foreground td.header {
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 10px;
+ color: rgb(0,0,0);
+ text-align: center;
+ vertical-align: middle;
+}
+
+div.schedule-detailed-outlookxp table.background td.header {
+ background-color: rgb(219,216,209);
+}
+
+div.schedule-detailed-outlookxp td.header span.date, div.schedule-detailed-outlookxp td.header span.holiday {
+ text-align: center;
+}
+
+div.schedule-detailed-outlookxp td.header span.date {
+}
+
+div.schedule-detailed-outlookxp td.header span.holiday {
+}
+
+div.schedule-detailed-outlookxp td.gutter span.hours {
+ font-size: 26px;
+}
+
+div.schedule-detailed-outlookxp td.gutter span.minutes {
+ font-size: 13px;
+}
+
+div.schedule-detailed-outlookxp table.background td.even,
+div.schedule-detailed-outlookxp table.background td.uneven,
+div.schedule-detailed-outlookxp table.background td.free {
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 10px;
+ text-align: center;
+}
+
+div.schedule-detailed-outlookxp table.background td.uneven {
+ background-color: rgb(255,255,143);
+ color: rgb(255,255,143);
+}
+
+div.schedule-detailed-outlookxp table.background td.even {
+ background-color: rgb(255,255,143);
+ color: rgb(255,255,143);
+}
+
+div.schedule-detailed-outlookxp table.background td.free {
+ background-color: rgb(239,240,112);
+ color: rgb(239,240,112);
+}
+
+div.schedule-detailed-outlookxp .entry, div.schedule-detailed-outlookxp div.entry-selected {
+ background-color: rgb(255,255,255);
+ text-align: center;
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 11px;
+ vertical-align: middle;
+ border-color: rgb(0,0,0);
+ text-decoration: none;
+}
+
+div.schedule-detailed-outlookxp a.entry:hover,
+div.schedule-detailed-outlookxp div.entry-selected {
+ border-color: rgb(1,2,217);
+}
+
+div.schedule-detailed-outlookxp div.entry-selected div.text {
+ border-left: solid rgb(1,2,217) 5.0px;
+}
+
+div.schedule-detailed-outlookxp .entry span.subtitle,
+div.schedule-detailed-outlookxp .entry-selected span.subtitle {
+ font-style: italic;
+ font-size: 9px;
+}
+
+div.schedule-detailed-outlookxp .entry span.title,
+div.schedule-detailed-outlookxp .entry-selected span.title {
+ font-size: 11px;
+}
+
+
+
+/* PART II: Compact Renderer */
+div.schedule-compact-outlookxp {
+ position: relative;
+ width: 100%;
+ left: 0px;
+ background-color: rgb(128,128,128);
+}
+
+div.schedule-compact-outlookxp table.day {
+ background-color: rgb(255,255,255);
+}
+
+div.schedule-compact-outlookxp table.day td.header {
+ background-color: rgb(219,216,209);
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 10px;
+ color: rgb(0,0,0);
+ text-align: left;
+ vertical-align: middle;
+}
+
+div.schedule-compact-outlookxp td.content div {
+}
+
+div.schedule-compact-outlookxp td.content td {
+ background-color: rgb(255,255,255);
+ color: rgb(0,0,0);
+ text-align: left;
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 11px;
+ padding: 1px;
+ border-color: rgb(255,255,255);
+ border-width: 1.0px;
+ border-style: solid;
+}
+
+div.schedule-compact-outlookxp a {
+ text-decoration: none;
+ color: rgb(0,0,0);
+ text-align: left;
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 11px;
+}
+
+div.schedule-compact-outlookxp td.content td.selected {
+ background-color: rgb(1,2,217);
+ border-color: rgb(1,2,217);
+ color: rgb(255,255,255);
+}
+
+div.schedule-compact-outlookxp td.inactive-day td.content {
+ background-color: rgb(219,216,209);
+ visibility: visible;
+}
+
+div.schedule-compact-outlookxp td.inactive-day td.content td {
+ background-color: rgb(219,216,209);
+ border-color: rgb(219,216,209);
+}
+
+div.schedule-compact-outlookxp td.inactive-day td.content td.selected {
+ background-color: rgb(1,2,217);
+ border-color: rgb(1,2,217);
+ color: rgb(255,255,255);
+}
+
+
+div.schedule-compact-outlookxp td.inactive-day td.header {
+ background-color: rgb(219,216,209);
+ visibility: visible;
+}
+
+
+
+
+/******************************************************************************/
+/* Everything after this line is not yet themed */
+/******************************************************************************/
+
+
+/* Part III: Planner renderer */
+div.planner {
+ border-style: solid;
+ border-width: 1px;
+ border-color: rgb(163,177,140);
+ position: relative;
+ width: 100%;
+ left: 0px;
+}
+
+div.planner table.background {
+ background-color: rgb(255,255,255);
+}
+
+div.planner div.background td.gutter, div.planner div.foreground td.gutter {
+ color: rgb(0,0,0);
+ text-align: right;
+}
+
+div.planner div.background td.gutter {
+ background-color: rgb(205,214,198);
+}
+
+
+div.planner div.background td.header, div.planner div.foreground td.header, div.planner div.background td.hours {
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 10px;
+ color: rgb(0,0,0);
+ text-align: center;
+ vertical-align: middle;
+ border-style: none;
+ border-width: 0px;
+}
+
+div.planner div.background td.hours {
+ border-color: rgb(255,255,255);
+ background-color: rgb(205,214,198);
+}
+
+div.planner div.foreground td.hours {
+ text-align: center;
+ vertical-align: middle;
+}
+
+div.planner div.background td.header {
+ background-color: rgb(205,214,198);
+}
+
+div.planner div.background div.header span.date {
+ text-align: left;
+ font-weight: bold;
+ vertical-align: top;
+}
+
+div.planner div.background div.header span.holiday {
+ text-align: left;
+ vertical-align: top;
+}
+
+div.planner div.background div.header span.hours {
+ text-align: left;
+ vertical-align: middle;
+}
+
+div.planner td.gutter span.title {
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ vertical-align: middle;
+ padding: 1px;
+ font-size: 10px;
+ font-weight: bold;
+}
+
+div.planner td.even, div.planner td.uneven, div.planner td.free {
+ border-color : rgb(255,255,255);
+ font-family: Verdana, Arial, Helvetica, Sans-Serif;
+ font-size: 10px;
+ text-align: center;
+}
+
+div.planner td.uneven {
+ background-color: rgb(240,244,233);
+ color: rgb(240,244,233);
+}
+
+div.planner td.even {
+ background-color: rgb(235,239,228);
+ color: rgb(235,239,228);
+}
+
+div.planner td.free {
+ background-color: rgb(215,219,208);
+ color: rgb(215,219,208);
+}
+
+div.planner table.foreground td.row {
+ border-color: rgb(255,255,255);
+}
+
+div.planner div.row div.entry {
+ background-color: rgb(0,0,255);
+ vertical-align: middle;
+ text-decoration: none;
+}
+
+
+
+/* PART IV: Tooltips */
+div.domTT {
+ border: 1px solid #333366;
+ background-color: #333366;
+}
+div.domTT .caption {
+ font-family: Verdana, Helvetica;
+ font-size: 10px;
+ font-weight: bold;
+ color: #FFFFFF;
+}
+div.domTT .contents {
+ font-size: 10px;
+ font-family: Verdana, Helvetica;
+ padding: 2px;
+ background-color: #F1F1FF;
+}
Added: myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/schedule/resource/javascript/alphaAPI.js
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/schedule/resource/javascript/alphaAPI.js?rev=410011&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/schedule/resource/javascript/alphaAPI.js (added)
+++ myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/schedule/resource/javascript/alphaAPI.js Sun May 28 18:59:05 2006
@@ -0,0 +1,294 @@
+/** $Id: alphaAPI.js 349804 2005-11-29 20:12:53Z skitching $ */
+// {{{ license
+
+/*
+ * Copyright 2002-2005 Dan Allen, Mojavelinux.com (dan.allen@mojavelinux.com)
+ *
+ * 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.
+ */
+
+// }}}
+// {{{ intro
+
+/**
+ * Title: alphaAPI
+ * Original Author: chrisken
+ * Original Url: http://www.cs.utexas.edu/users/chrisken/alphaapi.html
+ *
+ * Modified by Dan Allen <da...@mojavelinux.com>
+ * Note: When the stopAlpha is reached and it is equal to 0, the element's
+ * style is set to display: none to fix a bug in domTT
+ */
+
+// }}}
+function alphaAPI(element, fadeInDelay, fadeOutDelay, startAlpha, stopAlpha, offsetTime, deltaAlpha)
+{
+ // {{{ properties
+
+ this.element = typeof(element) == 'object' ? element : document.getElementById(element);
+ this.fadeInDelay = fadeInDelay || 40;
+ this.fadeOutDelay = fadeOutDelay || this.fadeInDelay;
+ this.startAlpha = startAlpha;
+ this.stopAlpha = stopAlpha;
+ // make sure a filter exists so an error is not thrown
+ if (typeof(this.element.filters) == 'object')
+ {
+ if (typeof(this.element.filters.alpha) == 'undefined')
+ {
+ this.element.style.filter += 'alpha(opacity=100)';
+ }
+ }
+
+ this.offsetTime = (offsetTime || 0) * 1000;
+ this.deltaAlpha = deltaAlpha || 10;
+ this.timer = null;
+ this.paused = false;
+ this.started = false;
+ this.cycle = false;
+ this.command = function() {};
+ return this;
+
+ // }}}
+}
+
+// use prototype methods to save memory
+// {{{ repeat()
+
+alphaAPI.prototype.repeat = function(repeat)
+{
+ this.cycle = repeat ? true : false;
+}
+
+// }}}
+// {{{ setAlphaBy()
+
+alphaAPI.prototype.setAlphaBy = function(deltaAlpha)
+{
+ this.setAlpha(this.getAlpha() + deltaAlpha);
+}
+
+// }}}
+// {{{ toggle()
+
+alphaAPI.prototype.toggle = function()
+{
+ if (!this.started)
+ {
+ this.start();
+ }
+ else if (this.paused)
+ {
+ this.unpause();
+ }
+ else
+ {
+ this.pause();
+ }
+}
+
+// }}}
+// {{{ timeout()
+
+alphaAPI.prototype.timeout = function(command, delay)
+{
+ this.command = command;
+ this.timer = setTimeout(command, delay);
+}
+
+// }}}
+// {{{ setAlpha()
+
+alphaAPI.prototype.setAlpha = function(opacity)
+{
+ if (typeof(this.element.filters) == 'object')
+ {
+ this.element.filters.alpha.opacity = opacity;
+ }
+ else if (this.element.style.setProperty)
+ {
+ this.element.style.setProperty('opacity', opacity / 100, '');
+ // handle the case of mozilla < 1.7
+ this.element.style.setProperty('-moz-opacity', opacity / 100, '');
+ // handle the case of old kthml
+ this.element.style.setProperty('-khtml-opacity', opacity / 100, '');
+ }
+}
+
+// }}}
+// {{{ getAlpha()
+
+alphaAPI.prototype.getAlpha = function()
+{
+ if (typeof(this.element.filters) == 'object')
+ {
+ return this.element.filters.alpha.opacity;
+ }
+ else if (this.element.style.getPropertyValue)
+ {
+ var opacityValue = this.element.style.getPropertyValue('opacity');
+ // handle the case of mozilla < 1.7
+ if (opacityValue == '')
+ {
+ opacityValue = this.element.style.getPropertyValue('-moz-opacity');
+ }
+
+ // handle the case of old khtml
+ if (opacityValue == '')
+ {
+ opacityValue = this.element.style.getPropertyValue('-khtml-opacity');
+ }
+
+ return opacityValue * 100;
+ }
+
+ return 100;
+}
+
+// }}}
+// {{{ start()
+
+alphaAPI.prototype.start = function()
+{
+ this.started = true;
+ this.setAlpha(this.startAlpha);
+ // determine direction
+ if (this.startAlpha > this.stopAlpha)
+ {
+ var instance = this;
+ this.timeout(function() { instance.fadeOut(); }, this.offsetTime);
+ }
+ else
+ {
+ var instance = this;
+ this.timeout(function() { instance.fadeIn(); }, this.offsetTime);
+ }
+}
+
+// }}}
+// {{{ stop()
+
+alphaAPI.prototype.stop = function()
+{
+ this.started = false;
+ this.setAlpha(this.stopAlpha);
+ if (this.stopAlpha == 0)
+ {
+ this.element.style.display = 'none';
+ }
+
+ this.stopTimer();
+ this.command = function() {};
+}
+
+// }}}
+// {{{ reset()
+
+alphaAPI.prototype.reset = function()
+{
+ this.started = false;
+ this.setAlpha(this.startAlpha);
+ this.stopTimer();
+ this.command = function() {};
+}
+
+// }}}
+// {{{ pause()
+
+alphaAPI.prototype.pause = function()
+{
+ this.paused = true;
+ this.stopTimer();
+}
+
+// }}}
+// {{{ unpause()
+
+alphaAPI.prototype.unpause = function()
+{
+ this.paused = false;
+ if (!this.started)
+ {
+ this.start();
+ }
+ else
+ {
+ this.command();
+ }
+}
+
+// }}}
+// {{{ stopTimer()
+
+alphaAPI.prototype.stopTimer = function()
+{
+ clearTimeout(this.timer);
+ this.timer = null;
+}
+
+// }}}
+// {{{ fadeOut()
+
+alphaAPI.prototype.fadeOut = function()
+{
+ this.stopTimer();
+ if (this.getAlpha() > this.stopAlpha)
+ {
+ this.setAlphaBy(-1 * this.deltaAlpha);
+ var instance = this;
+ this.timeout(function() { instance.fadeOut(); }, this.fadeOutDelay);
+ }
+ else
+ {
+ if (this.cycle)
+ {
+ var instance = this;
+ this.timeout(function() { instance.fadeIn(); }, this.fadeInDelay);
+ }
+ else
+ {
+ if (this.stopAlpha == 0)
+ {
+ this.element.style.display = 'none';
+ }
+ this.started = false;
+ }
+ }
+}
+
+// }}}
+// {{{ fadeIn()
+
+alphaAPI.prototype.fadeIn = function()
+{
+ this.stopTimer();
+ if (this.getAlpha() < this.startAlpha)
+ {
+ this.setAlphaBy(this.deltaAlpha);
+ var instance = this;
+ this.timeout(function() { instance.fadeIn(); }, this.fadeInDelay);
+ }
+ else
+ {
+ if (this.cycle)
+ {
+ var instance = this;
+ this.timeout(function() { instance.fadeOut(); }, this.fadeOutDelay);
+ }
+ else
+ {
+ this.started = false;
+ }
+ }
+}
+
+// }}}