Package org.apache.myfaces.custom.schedule.renderer

Source Code of org.apache.myfaces.custom.schedule.renderer.PlannerRenderer$EntryWrapper

/*
* 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.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.el.ValueBinding;
import javax.faces.render.Renderer;

import org.apache.myfaces.component.html.util.AddResource;
import org.apache.myfaces.custom.schedule.HtmlPlanner;
import org.apache.myfaces.custom.schedule.model.Day;
import org.apache.myfaces.custom.schedule.model.PlannerEntity;
import org.apache.myfaces.custom.schedule.model.ScheduleEntry;
import org.apache.myfaces.custom.schedule.util.ScheduleEntryComparator;
import org.apache.myfaces.renderkit.html.HTML;

/**
* <p>
* Renderer for the UIPlanner component
* </p>
*
* @author Jurgen Lust (latest modification by $Author$)
* @author Bruno Aranda (adaptation of Jurgen's code to myfaces)
* @version $Revision$
*/
public class PlannerRenderer extends Renderer
{
    //~ Static fields/initializers ---------------------------------------------

    private static final ScheduleEntryComparator comparator = new ScheduleEntryComparator();

    //~ Instance fields --------------------------------------------------------

    private final int ROW_HEIGHT_IN_PIXELS = 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;
        }

        HtmlPlanner planner = (HtmlPlanner) component;
        ResponseWriter writer = context.getResponseWriter();
       
        //determine the CSS file for the chosen theme
        String theme = getTheme(planner);
        if (theme == null || theme.length() < 1) theme = "default";
        String css = "css/" + theme + ".css";
       
        //add needed CSS and Javascript files to the header

        AddResource.addStyleSheet(HtmlPlanner.class, css,
                context);
        AddResource.addJavaScriptToHeader(HtmlPlanner.class,
                "javascript/alphaAPI.js", context);
        AddResource.addJavaScriptToHeader(HtmlPlanner.class,
                "javascript/domLib.js", context);
        AddResource.addJavaScriptToHeader(HtmlPlanner.class,
                "javascript/domTT.js", context);
        AddResource.addJavaScriptToHeader(HtmlPlanner.class,
                "javascript/fadomatic.js", context);


        int numberOfRows = planner.getModel().numberOfEntities();

        int gridHeight = (numberOfRows * 22) + 3 + 47;

        writer.startElement(HTML.DIV_ELEM, planner);
        writer.writeAttribute(HTML.CLASS_ATTR, "planner", null);
        writer.writeAttribute(HTML.STYLE_ATTR, "height: "
                + String.valueOf(gridHeight) + "px; overflow: hidden;", null);
        writeBackground(context, planner, writer);
        writeForegroundStart(context, planner, 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;
        }

        HtmlPlanner planner = (HtmlPlanner) component;
        ResponseWriter writer = context.getResponseWriter();

        for (Iterator entityIterator = planner.getModel().entityIterator(); entityIterator
                .hasNext();)
        {
            PlannerEntity entity = (PlannerEntity) entityIterator.next();
            writer.startElement(HTML.TR_ELEM, planner);
            writer.startElement(HTML.TD_ELEM, planner);
            writer.writeAttribute(HTML.CLASS_ATTR, "gutter", null);
            writer.startElement(HTML.DIV_ELEM, planner);
            writer.writeAttribute(HTML.STYLE_ATTR, "height: 1px; width: "
                    + String.valueOf(getGutterWidth(planner))
                    + "px", null);
            writer.endElement(HTML.DIV_ELEM);
            writer.endElement(HTML.TD_ELEM);

            int numberOfDays = planner.getModel().numberOfDays();
            float columnWidth = (numberOfDays == 0) ? 100f
                    : (100 / numberOfDays);

            for (Iterator dayIterator = planner.getModel().dayIterator(); dayIterator
                    .hasNext();)
            {
                Day day = (Day) dayIterator.next();
                writer.startElement(HTML.TD_ELEM, planner);
                writer.writeAttribute(HTML.CLASS_ATTR, "row", null);
                writer.writeAttribute(HTML.WIDTH_ATTR, String
                        .valueOf(columnWidth)
                        + "%", null);
                writer
                        .writeAttribute(
                                HTML.STYLE_ATTR,
                                "height: 21px; border-left-style: solid; border-left-width: 1px; border-top-style: none; border-right-style: none; border-bottom-style: none;",
                                null);
                writer.startElement(HTML.DIV_ELEM, null);
                writer.writeAttribute(HTML.CLASS_ATTR, "row", null);
                writer
                        .writeAttribute(
                                HTML.STYLE_CLASS_ATTR,
                                "position: relative; top: 0px; left: 0px; width: 100%; height: 100%; padding: 0px; z-index: 0; vertical-align: middle;",
                                null);
                writeEntries(context, planner, entity, day, writer);
                writer.endElement(HTML.DIV_ELEM);
                writer.endElement(HTML.TD_ELEM);
            }

            writer.endElement(HTML.TR_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;
        }

        HtmlPlanner planner = (HtmlPlanner) component;
        ResponseWriter writer = context.getResponseWriter();
        writeForegroundEnd(context, planner, writer);
        writer.endElement(HTML.DIV_ELEM);
    }

    /**
     * <p>
     * Determine the width of the left gutter
     * </p>
     *
     * @param component the component
     *
     * @return the gutter width in pixels
     */
    protected int getGutterWidth(UIComponent component)
    {
        try
        {
            //first check if the gutterWidthInPixels property is a
            //value binding expression
            ValueBinding binding = component.getValueBinding("gutterWidthInPixels");
            if (binding != null) {
                Integer value =
                    (Integer) binding.getValue(
                        FacesContext.getCurrentInstance()
                    );

                if (value != null) {
                    return value.intValue();
                }
            }
            //it's not a value binding expression, so check for the string value
            //in the attributes
            Map attributes = component.getAttributes();
            Integer width = Integer.valueOf((String) attributes
                    .get("gutterWidthInPixels"));

            return width.intValue();
        }
        catch (NumberFormatException nfe)
        {
            return 200;
        }
    }

    /**
     * <p>
     * The date format that is used in the planner header
     * </p>
     *
     * @param component the component
     *
     * @return Returns the headerDateFormat.
     */
    protected String getHeaderDateFormat(UIComponent component)
    {
        //first check if the headerDateFormat property is a value binding expression
        ValueBinding binding = component.getValueBinding("headerDateFormat");
        if (binding != null) {
            String value =
                (String) binding.getValue(
                    FacesContext.getCurrentInstance()
                );

            if (value != null) {
                return value;
            }
        }
        //it's not a value binding expression, so check for the string value
        //in the attributes
        Map attributes = component.getAttributes();
        return (String) attributes.get("headerDateFormat");
    }

    /**
     * <p>
     * Get the parent form of the planner component
     * </p>
     *
     * @param component the component
     *
     * @return the parent form
     */
    protected UIForm getParentForm(UIComponent component)
    {
        UIComponent parent = component.getParent();

        while (parent != null)
        {
            if (parent instanceof UIForm)
            {
                break;
            }

            parent = parent.getParent();
        }

        return (UIForm) parent;
    }

    /**
     * <p>
     * Should the legend be rendered?
     * </p>
     *
     * TODO the rendering of the legend has not been implemented yet
     *
     * @param component the component
     *
     * @return whether to render the legend
     */
    protected boolean showLegend(UIComponent component)
    {
        //first check if the tooltip property is a value binding expression
        ValueBinding binding = component.getValueBinding("legend");
        if (binding != null) {
            Boolean value =
                (Boolean) binding.getValue(
                    FacesContext.getCurrentInstance()
                );

            if (value != null) {
                return value.booleanValue();
            }
        }
        //it's not a value binding expression, so check for the string value
        //in the attributes
        Map attributes = component.getAttributes();
        return Boolean.valueOf((String) attributes.get("legend"))
                .booleanValue();
    }

    /**
     * <p>
     * The theme used when rendering the planner
     * </p>
     *
     * @param component the component
     *
     * @return the theme
     */
    protected String getTheme(UIComponent component) {
        //first check if the theme property is a value binding expression
        ValueBinding binding = component.getValueBinding("theme");
        if (binding != null) {
            String value =
                (String) binding.getValue(
                    FacesContext.getCurrentInstance()
                );

            if (value != null) {
                return value;
            }
        }
        //it's not a value binding expression, so check for the string value
        //in the attributes
        Map attributes = component.getAttributes();
        return (String)attributes.get("theme");
    }
   
    /**
     * <p>
     * Should the tooltip be rendered?
     * </p>
     *
     * @param component the component
     *
     * @return whether or not tooltips should be rendered
     */
    protected boolean showTooltip(UIComponent component)
    {
        //first check if the tooltip property is a value binding expression
        ValueBinding binding = component.getValueBinding("tooltip");
        if (binding != null) {
            Boolean value =
                (Boolean) binding.getValue(
                    FacesContext.getCurrentInstance()
                );

            if (value != null) {
                return value.booleanValue();
            }
        }
        //it's not a value binding expression, so check for the string value
        //in the attributes
        Map attributes = component.getAttributes();
        return Boolean.valueOf((String) attributes.get("tooltip")).booleanValue();
    }

    private String getCellClass(HtmlPlanner planner, Day day, int hour)
    {
        if (!day.isWorkingDay())
        {
            return "free";
        }

        if ((hour >= planner.getWorkingStartHour())
                && (hour < planner.getWorkingEndHour()))
        {
            return ((hour % 2) == 0) ? "even" : "uneven";
        }

        return "free";
    }

    private String getDateString(FacesContext context, UIComponent component, Date date)
    {
        DateFormat format;
        String pattern = getHeaderDateFormat(component);

        if ((pattern != null) && (pattern.length() > 0))
        {
            format = new SimpleDateFormat(pattern);
        }
        else
        {
            if (context.getApplication().getDefaultLocale() != null)
            {
                format = DateFormat.getDateInstance(DateFormat.MEDIUM, context
                        .getApplication().getDefaultLocale());
            }
            else
            {
                format = DateFormat.getDateInstance(DateFormat.MEDIUM);
            }
        }

        return format.format(date);
    }

    private String getTooltipText(ScheduleEntry entry, UIComponent component)
    {
        if (!showTooltip(component))
        {
            return null;
        }

         StringBuffer buffer = new StringBuffer();
         buffer.append(
         "return makeTrue(domTT_activate(this, event, 'caption', '"
         );

         if (entry.getTitle() != null) {
         buffer.append(escape(entry.getTitle()));
         }

         buffer.append("', 'content', '<i>");

         if (entry.getSubtitle() != null) {
         buffer.append(escape(entry.getSubtitle()));
         }

         buffer.append("</i>");

         if (entry.getDescription() != null) {
         buffer.append("<br/>");
         buffer.append(escape(entry.getDescription()));
         }

         buffer.append("', 'trail', true));");

         return buffer.toString();
    }

    private boolean containsEntry(HtmlPlanner planner, Day day,
            ScheduleEntry entry)
    {
        if ((day == null) || (entry == null))
        {
            return false;
        }

        Calendar cal = GregorianCalendar.getInstance();
        cal.setTime(day.getDate());
        cal.set(Calendar.HOUR_OF_DAY, planner.getVisibleStartHour());
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);

        Date dayStart = cal.getTime();
        cal.set(Calendar.HOUR_OF_DAY, planner.getVisibleEndHour());

        Date dayEnd = cal.getTime();

        return entry.getEndTime().after(dayStart)
                && entry.getStartTime().before(dayEnd);
    }

    private String escape(String text)
    {
        if (text == null)
        {
            return null;
        }

        return text.replaceAll("'", "&quot;");
    }

    /**
     * <p>
     * Draw the planner background, i.e. the grid
     * </p>
     *
     * @param context the FacesContext
     * @param planner the Planner component
     * @param writer the ResponseWriter
     *
     * @throws IOException when the background cannot be drawn
     * @throws NullPointerException
     */
    private void writeBackground(FacesContext context, HtmlPlanner planner,
            ResponseWriter writer) throws IOException
    {
        //a planner component should always be inside a UIForm
        UIForm parentForm = getParentForm(planner);

        if (parentForm == null)
        {
            throw new NullPointerException("No parent UIForm found");
        }

        writer.startElement(HTML.DIV_ELEM, planner);
        writer.writeAttribute(HTML.CLASS_ATTR, "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, planner);
        writer.writeAttribute(HTML.CLASS_ATTR, "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, planner);

        //header row, containing the day names
        writer.startElement(HTML.TR_ELEM, planner);
        writer.startElement(HTML.TD_ELEM, planner);
        writer.writeAttribute(HTML.CLASS_ATTR, "gutter", null);
        writer.writeAttribute("rowspan", "2", null);
        writer
                .writeAttribute(
                        HTML.STYLE_ATTR,
                        "padding: 0px; vertical-align: middle; height: 21px; border-style: none; border-width: 0px; overflow: hidden; whitespace: nowrap;",
                        null);
        writer.startElement(HTML.DIV_ELEM, planner);
        writer.writeAttribute(HTML.STYLE_ATTR, "height: 1px; width: "
                + String.valueOf(getGutterWidth(planner))
                + "px", null);
        writer.endElement(HTML.DIV_ELEM);
        writer.endElement(HTML.TD_ELEM);

        int numberOfDays = planner.getModel().numberOfDays();
        float columnWidth = (numberOfDays == 0) ? 100f : (100 / numberOfDays);

        for (Iterator dayIterator = planner.getModel().dayIterator(); dayIterator
                .hasNext();)
        {
            Day day = (Day) dayIterator.next();
            writer.startElement(HTML.TD_ELEM, planner);
            writer.writeAttribute(HTML.CLASS_ATTR, "header", null);
            writer.writeAttribute(HTML.WIDTH_ATTR, String.valueOf(columnWidth)
                    + "%", null);
            writer.writeAttribute(HTML.STYLE_ATTR,
                    "overflow: hidden; height: 31px;", null);
            writer.startElement(HTML.DIV_ELEM, planner);
            writer.writeAttribute(HTML.CLASS_ATTR, "header", null);
            writer
                    .writeAttribute(
                            HTML.STYLE_ATTR,
                            "position: relative; left: 0px; top: 0px; width: 100%; height: 100%;",
                            null);
            writer.startElement(HTML.SPAN_ELEM, planner);
            writer.writeAttribute(HTML.CLASS_ATTR, "date", null);
            writer
                    .writeAttribute(
                            HTML.STYLE_ATTR,
                            "position: absolute; left: 0px; top: 0px; width: 100%; height: 15px; overflow: hidden; white-space: nowrap;",
                            null);
            writer.writeText(getDateString(context, planner,
                    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, planner);
                writer.writeAttribute(HTML.CLASS_ATTR, "holiday", null);
                writer
                        .writeAttribute(
                                HTML.STYLE_ATTR,
                                "position: absolute; left: 0px; top: 15px; width: 100%; 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);

        //second header row, containing the hours
        writer.startElement(HTML.TR_ELEM, planner);

        int numberOfHours = planner.getVisibleEndHour()
                - planner.getVisibleStartHour();
        float hourWidth = (numberOfHours <= 0) ? 100f : (100 / numberOfHours);

        for (Iterator dayIterator = planner.getModel().dayIterator(); dayIterator
                .hasNext();)
        {
            Day day = (Day) dayIterator.next();
            writer.startElement(HTML.TD_ELEM, planner);
            writer.writeAttribute(HTML.WIDTH_ATTR, String.valueOf(columnWidth)
                    + "%", null);
            writer.startElement(HTML.TABLE_ELEM, planner);
            writer.writeAttribute(HTML.STYLE_ATTR, "height: 100%; width: 100%",
                    null);
            writer.writeAttribute(HTML.CELLPADDING_ATTR, "0", null);
            writer.writeAttribute(HTML.CELLSPACING_ATTR, "0", null);
            writer.writeAttribute("border", "0", null);
            writer.startElement(HTML.TR_ELEM, planner);

            for (int hcol = planner.getVisibleStartHour(); hcol < planner
                    .getVisibleEndHour(); hcol++)
            {
                writer.startElement(HTML.TD_ELEM, planner);
                writer.writeAttribute(HTML.CLASS_ATTR, "hours", null);
                writer.writeAttribute(HTML.WIDTH_ATTR, String
                        .valueOf(hourWidth)
                        + "%", null);
                writer
                        .writeAttribute(
                                HTML.STYLE_ATTR,
                                "overflow: hidden; height: 15px; border-left-style: solid; border-left-width: 1px; border-top-style: none; border-right-style: none; border-bottom-style: none;",
                                null);
                writer.startElement(HTML.DIV_ELEM, planner);
                writer.writeAttribute(HTML.CLASS_ATTR, "header", null);
                writer
                        .writeAttribute(
                                HTML.STYLE_ATTR,
                                "position: relative; left: 0px; top: 0px; width: 100%; height: 100%;",
                                null);
                writer.startElement(HTML.SPAN_ELEM, planner);
                writer.writeAttribute(HTML.CLASS_ATTR, "hours", null);
                writer
                        .writeAttribute(
                                HTML.STYLE_ATTR,
                                "position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; overflow: hidden; white-space: nowrap;",
                                null);
                writer.writeText(String.valueOf(hcol) + ":00", null);
                writer.endElement(HTML.SPAN_ELEM);
                writer.endElement(HTML.DIV_ELEM);
                writer.endElement(HTML.TD_ELEM);
            }

            writer.endElement(HTML.TR_ELEM);
            writer.endElement(HTML.TABLE_ELEM);
            writer.endElement(HTML.TD_ELEM);
        }

        writer.endElement(HTML.TR_ELEM);

        //the actual entity rows start here
        for (Iterator entityIterator = planner.getModel().entityIterator(); entityIterator
                .hasNext();)
        {
            PlannerEntity entity = (PlannerEntity) entityIterator.next();
            writer.startElement(HTML.TR_ELEM, planner);
            writer.startElement(HTML.TD_ELEM, planner);
            writer.writeAttribute(HTML.CLASS_ATTR, "gutter", null);
            writer
                    .writeAttribute(
                            HTML.STYLE_ATTR,
                            "padding: 0px; vertical-align: middle; height: 21px; border-style: none; border-width: 0px; overflow: hidden; whitespace: nowrap;",
                            null);
            writer.startElement(HTML.SPAN_ELEM, planner);
            writer.writeAttribute(HTML.CLASS_ATTR, "title", null);
            writer.writeAttribute(HTML.STYLE_ATTR, "height: 100%;", null);
            writer.writeText(entity.getName(), null);
            writer.endElement(HTML.SPAN_ELEM);
            writer.endElement(HTML.TD_ELEM);

            for (Iterator dayIterator = planner.getModel().dayIterator(); dayIterator
                    .hasNext();)
            {
                Day day = (Day) dayIterator.next();
                writer.startElement(HTML.TD_ELEM, planner);
                writer.writeAttribute(HTML.WIDTH_ATTR, String
                        .valueOf(columnWidth)
                        + "%", null);
                writer.startElement(HTML.TABLE_ELEM, planner);
                writer.writeAttribute(HTML.STYLE_ATTR,
                        "height: 100%; width: 100%", null);
                writer.writeAttribute(HTML.CELLPADDING_ATTR, "0", null);
                writer.writeAttribute(HTML.CELLSPACING_ATTR, "0", null);
                writer.writeAttribute("border", "0", null);
                writer.startElement(HTML.TR_ELEM, planner);

                for (int hcol = planner.getVisibleStartHour(); hcol < planner
                        .getVisibleEndHour(); hcol++)
                {
                    writer.startElement(HTML.TD_ELEM, planner);
                    writer.writeAttribute(HTML.CLASS_ATTR, getCellClass(
                            planner, day, hcol), null);
                    writer.writeAttribute(HTML.WIDTH_ATTR, String
                            .valueOf(hourWidth)
                            + "%", null);
                    writer
                            .writeAttribute(
                                    HTML.STYLE_ATTR,
                                    "height: 21px; overflow: hidden; border-left-style: solid; border-left-width: 1px; border-top-style: none; border-right-style: none; border-bottom-style: none;",
                                    null);
                    writer.write(HTML.NBSP_ENTITY);
                    writer.endElement(HTML.TD_ELEM);
                }

                writer.endElement(HTML.TR_ELEM);
                writer.endElement(HTML.TABLE_ELEM);
                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);
    }

    /**
     * <p>
     * Draw the entries on the planner
     * </p>
     *
     * @param context the FacesContext
     * @param planner the Planner component
     * @param entity the planner entity
     * @param day the day
     * @param writer the responsewriter
     *
     * @throws IOException when the entries cannot be drawn
     */
    private void writeEntries(FacesContext context, HtmlPlanner planner,
            PlannerEntity entity, Day day, ResponseWriter writer)
            throws IOException
    {
        for (Iterator entryIterator = entity.iterator(); entryIterator
                .hasNext();)
        {
            ScheduleEntry entry = (ScheduleEntry) entryIterator.next();

            if (containsEntry(planner, day, entry))
            {
                EntryWrapper wrapper = new EntryWrapper(entry, day, entity);
                writer.startElement(HTML.DIV_ELEM, planner);

                //draw the tooltip
                if (showTooltip(planner))
                {
                    writer.writeAttribute("onmouseover", getTooltipText(
                            wrapper.entry, planner), null);
                }

                writer.writeAttribute(HTML.CLASS_ATTR, "entry", null);
                writer.writeAttribute(HTML.STYLE_ATTR, wrapper
                        .getBounds(planner), null);
                writer.endElement(HTML.DIV_ELEM);
            }
        }
    }

    private void writeForegroundEnd(FacesContext context, HtmlPlanner planner,
            ResponseWriter writer) throws IOException
    {
        writer.endElement(HTML.TBODY_ELEM);
        writer.endElement(HTML.TABLE_ELEM);
        writer.endElement(HTML.DIV_ELEM);
    }

    private void writeForegroundStart(FacesContext context,
            HtmlPlanner planner, ResponseWriter writer) throws IOException
    {
        writer.startElement(HTML.DIV_ELEM, planner);
        writer.writeAttribute(HTML.CLASS_ATTR, "foreground", null);
        writer
                .writeAttribute(
                        HTML.STYLE_ATTR,
                        "position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; z-index: 1;",
                        null);

        //foreground table for the planner grid
        writer.startElement(HTML.TABLE_ELEM, planner);
        writer.writeAttribute(HTML.CLASS_ATTR, "foreground", 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, planner);

        //header row containing the day names
        writer.startElement(HTML.TR_ELEM, planner);
        writer.startElement(HTML.TD_ELEM, planner);
        writer.writeAttribute(HTML.CLASS_ATTR, "gutter", null);
        writer.writeAttribute("rowspan", "2", null);
        writer
                .writeAttribute(
                        HTML.STYLE_ATTR,
                        "padding: 0px; vertical-align: middle; height: 21px; border-style: none; border-width: 0px; overflow: hidden; whitespace: nowrap;",
                        null);
        writer.startElement(HTML.DIV_ELEM, planner);
        writer.writeAttribute(HTML.STYLE_ATTR, "height: 1px; width: "
                + String.valueOf(getGutterWidth(planner))
                + "px", null);
        writer.endElement(HTML.DIV_ELEM);
        writer.endElement(HTML.TD_ELEM);

        int numberOfDays = planner.getModel().numberOfDays();
        float columnWidth = (numberOfDays == 0) ? 100f : (100 / numberOfDays);

        for (Iterator dayIterator = planner.getModel().dayIterator(); dayIterator
                .hasNext();)
        {
            Day day = (Day) dayIterator.next();
            writer.startElement(HTML.TD_ELEM, planner);
            writer.writeAttribute(HTML.CLASS_ATTR, "header", null);
            writer.writeAttribute(HTML.WIDTH_ATTR, String.valueOf(columnWidth)
                    + "%", null);
            writer.writeAttribute(HTML.STYLE_ATTR,
                    "overflow: hidden; height: 31px;", null);
            writer.endElement(HTML.TD_ELEM);
        }

        writer.endElement(HTML.TR_ELEM);

        //header row containing the hours
        writer.startElement(HTML.TR_ELEM, planner);

        for (Iterator dayIterator = planner.getModel().dayIterator(); dayIterator
                .hasNext();)
        {
            Day day = (Day) dayIterator.next();
            writer.startElement(HTML.TD_ELEM, planner);
            writer.writeAttribute(HTML.CLASS_ATTR, "hours", null);
            writer.writeAttribute(HTML.WIDTH_ATTR, String.valueOf(columnWidth)
                    + "%", null);
            writer
                    .writeAttribute(
                            HTML.STYLE_ATTR,
                            "overflow: hidden; height: 15px; border-style: none; border-width: 0px",
                            null);
            writer.endElement(HTML.TD_ELEM);
        }

        writer.endElement(HTML.TR_ELEM);
    }

    //~ Inner Classes ----------------------------------------------------------

    /**
     *
     */
    private class EntryWrapper implements Comparable
    {
        //~ Static fields/initializers -----------------------------------------

        private static final int HOUR = 1000 * 3600;

        //~ Instance fields ----------------------------------------------------

        private final Day day;
        private final PlannerEntity entity;
        private final ScheduleEntry entry;

        //~ Constructors -------------------------------------------------------

        EntryWrapper(ScheduleEntry entry, Day day, PlannerEntity entity)
        {
            this.entry = entry;
            this.day = day;
            this.entity = entity;
        }

        //~ 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 the entry
         * </p>
         *
         * @param planner the planner component
         *
         * @return the bounds, as CSS position attributes
         */
        String getBounds(HtmlPlanner planner)
        {
            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, planner.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, planner.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;

            float left = (float) ((startMillis - visibleStartMillis) * 100)
                    / (float) (visibleEndMillis - visibleStartMillis);
            float width = (float) ((endMillis - startMillis) * 100)
                    / (float) (visibleEndMillis - visibleStartMillis);
            StringBuffer buffer = new StringBuffer();
            buffer
                    .append("position: absolute; padding: 0px; top: 0px; height: 21px; left: ");
            buffer.append(String.valueOf(left));
            buffer.append("%; width: ");
            buffer.append(String.valueOf(width));
            buffer
                    .append("%; overflow: hidden; border-style-none; border-width: 0px;");

            return buffer.toString();
        }
    }
}
//The End
TOP

Related Classes of org.apache.myfaces.custom.schedule.renderer.PlannerRenderer$EntryWrapper

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.