Package org.openfaces.renderkit.timetable

Source Code of org.openfaces.renderkit.timetable.MonthTableRenderer

/*
* OpenFaces - JSF Component Library 2.0
* Copyright (C) 2007-2012, TeamDev Ltd.
* licensing@openfaces.org
* Unless agreed in writing the contents of this file are subject to
* the GNU Lesser General Public License Version 2.1 (the "LGPL" License).
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* Please visit http://openfaces.org/licensing/ for more details.
*/

package org.openfaces.renderkit.timetable;

import org.openfaces.component.timetable.AbstractTimetableEvent;
import org.openfaces.component.timetable.MonthTable;
import org.openfaces.component.timetable.ScrollButton;
import org.openfaces.component.timetable.ScrollDirection;
import org.openfaces.component.timetable.Timetable;
import org.openfaces.component.timetable.TimetableResource;
import org.openfaces.component.timetable.TimetableView;
import org.openfaces.component.timetable.UITimetableEvent;
import org.openfaces.org.json.JSONArray;
import org.openfaces.org.json.JSONException;
import org.openfaces.org.json.JSONObject;
import org.openfaces.renderkit.TableRenderer;
import org.openfaces.renderkit.TableUtil;
import org.openfaces.util.AjaxUtil;
import org.openfaces.util.DataUtil;
import org.openfaces.util.Log;
import org.openfaces.util.Rendering;
import org.openfaces.util.Resources;
import org.openfaces.util.ScriptBuilder;
import org.openfaces.util.StyleGroup;
import org.openfaces.util.Styles;

import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

/**
* @author Roman Porotnikov
*/
public class MonthTableRenderer extends TimetableViewRenderer {

    private static String EXPANDED_VIEW_SUFFIX = "::expandedDayView";

    private static final String DEFAULT_EXPANDED_DAY_VIEW_CLASS = "o_expandedDayView";

    @Override
    public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
        if (!component.isRendered())
            return;

        MonthTable timetableView = (MonthTable) component;
        Rendering.registerDateTimeFormatObject(timetableView.getLocale());
        AjaxUtil.prepareComponentForAjax(context, timetableView);
        ResponseWriter writer = context.getResponseWriter();
        String clientId = timetableView.getClientId(context);
        Styles.renderStyleClasses(context, timetableView);
        writer.startElement("table", timetableView);
        writer.writeAttribute("id", clientId, "id");
        writer.writeAttribute("cellspacing", "0", null);
        writer.writeAttribute("cellpadding", "0", null);
        writer.writeAttribute("border", "0", null);
        Timetable timetable = timetableView.getTimetable();
        writer.writeAttribute("class", Styles.getCSSClass(context,
                timetableView, timetableView.getStyle(),
                timetable == null ? "o_timetableView" : "o_timetableView o_timetableView_embedded",
                timetableView.getStyleClass()), null);
        Rendering.writeStandardEvents(writer, timetableView);
        writer.startElement("tbody", timetableView);

        renderHeader(context, timetableView);

        renderWeekdayHeadersRow(context, timetableView, clientId);

        ValueExpression resourcesExpression = timetableView.getResourcesValueExpression();
        List<TimetableResource> resources = resourcesExpression != null
                ? DataUtil.readDataModelExpressionAsList(context, resourcesExpression)
                : Collections.<TimetableResource>emptyList();

        writer.startElement("tr", timetableView);
        writer.writeAttribute("class", "o_timetableView_tableRow", null);
        writer.startElement("td", timetableView);
        writer.writeAttribute("style", "height: 100%", null);

        renderContentTable(context, timetableView, clientId, resources);

        encodeEventEditor(context, timetableView, resources);
        encodeActionBar(context, timetableView);

        writer.endElement("td");
        writer.endElement("tr");

        renderFooter(context, timetableView);

        writer.endElement("tbody");
        writer.endElement("table");
        timetableView.getExpandedDayViewFooter();



    }

    private void renderExpandedDayView(FacesContext context, MonthTable monthTable) throws IOException{
        UIComponent header = monthTable.getExpandedDayViewHeader();
        if (header == null ){
            header = new ScrollButton(ScrollDirection.UP);
            header.setParent(monthTable);
        }
        UIComponent footer = monthTable.getExpandedDayViewFooter();
        if (footer == null ){
            footer = new ScrollButton(ScrollDirection.DOWN);
            footer.setParent(monthTable);
        }
        String expandDayViewId = monthTable.getClientId(context) + EXPANDED_VIEW_SUFFIX;
        ResponseWriter writer = context.getResponseWriter();
        writer.startElement("div", monthTable);

        writer.writeAttribute("id", expandDayViewId , null);

        writer.writeAttribute("class",Styles.getCSSClass(context, monthTable, monthTable.getExpandedDayViewStyle(), StyleGroup.regularStyleGroup(),
                monthTable.getExpandedDayViewClass(), getDefaultExpandedDayViewClass()),null);
        writer.writeAttribute("style", "position: absolute;", null);

        writer.startElement("div", monthTable);
        //TODO: rework with z-index
        writer.writeAttribute("style", "width: 100%; z-index: 213123; position: relative;", null);
        writer.writeAttribute("id", expandDayViewId + "::header" , null);
        header.encodeAll(context);
        writer.endElement("div");

        writer.startElement("div", monthTable);
        writer.writeAttribute("style", "height: 100%; overflow:hidden; position: relative;", null);
        writer.writeAttribute("id", expandDayViewId + "::eventBlock" , null);
        writer.endElement("div");


        writer.startElement("div", monthTable);
        //TODO: move ID to static
        writer.writeAttribute("id", expandDayViewId + "::footer" , null);
        //TODO: rework with z-index
        writer.writeAttribute("style", "width: 100%; position: relative; ", null);
        footer.encodeAll(context);
        writer.endElement("div");

        writer.endElement("div");
    }


    private void renderWeekdayHeadersRow(FacesContext context, final MonthTable timetableView, String clientId) throws IOException {
        ResponseWriter writer = context.getResponseWriter();

        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(timetableView.getDay());
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        calendar.add(Calendar.DATE, 1 - dayOfWeek);

        writer.startElement("tr", timetableView);
        writer.startElement("td", timetableView);

        new TableRenderer(clientId + Rendering.CLIENT_ID_SUFFIX_SEPARATOR + "weekdayHeaders", 0, 0, 0, "o_weekdayHeadersTable")
                .render(timetableView, true, 1, 8);

        writer.endElement("td");
        writer.endElement("tr");
    }

    private void renderContentTable(
            FacesContext context,
            final MonthTable timetableView,
            final String clientId,
            final List<TimetableResource> resources) throws IOException {

        ResponseWriter writer = context.getResponseWriter();
        writer.startElement("div", timetableView);
        writer.writeAttribute("id", clientId + "::scroller", null);
        writer.writeAttribute("style""overflow : visible; overflow-x : visible; overflow-y = hidden;", null);
        writer.writeAttribute("class", "o_timetableView_scroller", null);
        renderExpandedDayView(context, timetableView);
        int colCount = 7;

        new TableRenderer(clientId + Rendering.CLIENT_ID_SUFFIX_SEPARATOR + "table", 0, 0, 0, "o_timetableView_table") {

            protected void encodeTFoot(ResponseWriter writer, UIComponent component) throws IOException {
                writer.startElement("tfoot", component);
                writer.writeAttribute("id", clientId + "::hiddenArea", null);
                writer.writeAttribute("style", "display: none", null);
                writer.startElement("tr", component);
                writer.startElement("td", component);

                FacesContext context = FacesContext.getCurrentInstance();
                encodeEventPreview(context, timetableView);
                encodeInitScript(context, timetableView, resources);

                writer.endElement("td");
                writer.endElement("tr");
                writer.endElement("tfoot");
            }

        }.render(timetableView, true, 0, colCount);

        writer.endElement("div");
    }

    private void encodeInitScript(FacesContext context, MonthTable timetableView, List<TimetableResource> resources) throws IOException {
        Map<String, TimeZone> timeZoneParam = getTimeZoneParamForJSONConverter(timetableView);
        JSONArray resourcesJsArray = DataUtil.listToJSONArray(resources, timeZoneParam);
        timetableView.getAttributes().put(USE_RESOURCE_SEPARATION_MODE_ATTR, resourcesJsArray.length() > 0);

        String clientId = timetableView.getClientId(context);

        JSONObject editingOptions = getEditingOptionsObj(timetableView);
        JSONObject stylingParams = getStylingParamsObj(context, timetableView);
        JSONObject calendarOptions = getCalendarOptionsObj(timetableView);

        TimeZone timeZone = (timetableView.getTimeZone() != null)
                ? timetableView.getTimeZone()
                : TimeZone.getDefault();

        boolean editable = timetableView.isEditable();
        boolean thereIsChangeListener = timetableView.getTimetableChangeListener() != null ||
                timetableView.getTimetableChangeListeners().length > 0;
        if (editable && !thereIsChangeListener) {
            Log.log(context, "The " + getComponentName() + " with clientID=[" + clientId + "] is set to be editable, but is not configured to accept the changes. " +
                    "You should either make it read-only explicitly (using editable=\"false\" attribute), or define timetableChangeListener attriubte to accept the changes (see " + getComponentName() + " reference).");
            editable = false;
        }
        List<AbstractTimetableEvent> events = new ArrayList<AbstractTimetableEvent>();
        JSONObject eventParams = composeEventParams(context, timetableView, events);
        Map<String, AbstractTimetableEvent> loadedEvents = timetableView.getLoadedEvents();
        loadedEvents.clear();
        for (AbstractTimetableEvent event : events) {
            loadedEvents.put(event.getId(), event);
        }


        JSONArray areaSettings = encodeEventAreas(context, timetableView, events);

        UITimetableEvent uiEvent = timetableView.getUITimetableEvent();

        Timetable timetable = timetableView.getTimetable();

        try {
            Rendering.renderInitScript(context,
                    new ScriptBuilder().initScript(
                            context,
                            timetableView,
                            "O$.MonthTable._init",
                            DataUtil.formatDateTimeForJs(timetableView.getDay(), timeZone),
                            timetableView.getLocale(),
                            "MMMM, dd yyyy",
                            timetableView.getScrollOffset(),
                            eventParams,
                            resourcesJsArray,
                            areaSettings,
                            editable,
                            timetableView.getOnchange(),
                            editingOptions,
                            stylingParams,
                            uiEvent != null ? uiEvent.toJSONObject(null) : null,
                            calendarOptions,
                            timetable
                    ),
                    Resources.utilJsURL(context),
                    Resources.jsonJsURL(context),
                    TableUtil.getTableUtilJsURL(context),
                    Resources.internalURL(context, "timetable/rangeMap.js"),
                    Resources.internalURL(context, "timetable/timetable.js"),
                    Resources.internalURL(context, "timetable/timeTableView.js"),
                    Resources.internalURL(context, "timetable/monthTable.js")
            );
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }

    }

    private JSONObject getCalendarOptionsObj(MonthTable monthTable) {
        JSONObject calendarOptionsObj = new JSONObject();

        int firstDayOfWeek = monthTable.getFirstDayOfWeek() - 1; // JS weekdays are 0-based while Java weekdays are 1-based
        Rendering.addJsonParam(calendarOptionsObj, "firstDayOfWeek", firstDayOfWeek);
        return calendarOptionsObj;
    }

    private JSONObject composeEventParams(FacesContext context, MonthTable timetableView, List putEventsHere) {
        Map<String, TimeZone> timeZoneParam = getTimeZoneParamForJSONConverter(timetableView);

        ValueExpression eventsExpression = timetableView.getEventsValueExpression();
        List events = eventsExpression == null ? Collections.EMPTY_LIST : DataUtil.readDataModelExpressionAsList(context, eventsExpression);
        if (putEventsHere != null) {
            putEventsHere.clear();
            putEventsHere.addAll(events);
        }

        JSONArray eventsJsArray = DataUtil.listToJSONArray(events, timeZoneParam);

        JSONObject eventParams = new JSONObject();
        try {
            eventParams.put("events", eventsJsArray);
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }
        return eventParams;
    }


    private JSONObject getStylingParamsObj(FacesContext context, MonthTable timetableView) {
        JSONObject stylingParams = new JSONObject();

        Styles.addStyleJsonParam(context, timetableView, stylingParams, "rolloverClass",
                timetableView.getRolloverStyle(), timetableView.getRolloverClass());

        Rendering.addJsonParam(stylingParams, "defaultEventColor", timetableView.getDefaultEventColor());
        Rendering.addJsonParam(stylingParams, "reservedTimeEventColor", timetableView.getReservedTimeEventColor());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "reservedTimeEventClass",
                timetableView.getReservedTimeEventStyle(), timetableView.getReservedTimeEventClass());

        Styles.addStyleJsonParam(context, timetableView, stylingParams, "weekdayHeadersRowClass",
                timetableView.getWeekdayHeadersRowStyle(), timetableView.getWeekdayHeadersRowClass());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "weekdayClass",
                timetableView.getWeekdayStyle(), timetableView.getWeekdayClass());
        Rendering.addJsonParam(stylingParams, "weekdayPattern", timetableView.getWeekdayPattern());
        Rendering.addJsonParam(stylingParams, "defaultEventColor", timetableView.getDefaultEventColor());
        Rendering.addJsonParam(stylingParams, "weekdayHeadersRowSeparator", timetableView.getWeekdayHeadersRowSeparator());
        Rendering.addJsonParam(stylingParams, "weekdayColumnSeparator", timetableView.getWeekdayColumnSeparator());
        Rendering.addJsonParam(stylingParams, "rowSeparator", timetableView.getRowSeparator());
        Rendering.addJsonParam(stylingParams, "columnSeparator", timetableView.getColumnSeparator());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "dayHeaderRowClass",
                timetableView.getDayHeaderRowStyle(), timetableView.getDayHeaderRowClass());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "rowClass",
                timetableView.getRowStyle(), timetableView.getRowClass());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "weekdayHeaderCellClass",
                timetableView.getWeekdayHeaderCellStyle(), timetableView.getWeekdayHeaderCellClass());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "weekendWeekdayHeaderCellClass",
                timetableView.getWeekendWeekdayHeaderCellStyle(), timetableView.getWeekendWeekdayHeaderCellClass());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "cellHeaderClass",
                timetableView.getCellHeaderStyle(), timetableView.getCellHeaderClass());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "cellClass",
                timetableView.getCellStyle(), timetableView.getCellClass());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "todayCellHeaderClass",
                timetableView.getTodayCellHeaderStyle(), timetableView.getTodayCellHeaderClass());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "todayCellClass",
                timetableView.getTodayCellStyle(), timetableView.getTodayCellClass());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "weekendCellHeaderClass",
                timetableView.getWeekendCellHeaderStyle(), timetableView.getWeekendCellHeaderClass());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "weekendCellClass",
                timetableView.getWeekendCellStyle(), timetableView.getWeekendCellClass());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "inactiveMonthCellHeaderClass",
                timetableView.getInactiveMonthCellHeaderStyle(), timetableView.getInactiveMonthCellHeaderClass());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "inactiveMonthCellClass",
                timetableView.getInactiveMonthCellStyle(), timetableView.getInactiveMonthCellClass());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "moreLinkElementClass",
                timetableView.getMoreLinkElementStyle(), timetableView.getMoreLinkElementClass());
        Styles.addStyleJsonParam(context, timetableView, stylingParams, "moreLinkClass",
                timetableView.getMoreLinkStyle(), timetableView.getMoreLinkClass());
        Rendering.addJsonParam(stylingParams, "moreLinkText", timetableView.getMoreLinkText());
        Rendering.addJsonParam(stylingParams, "expandTransitionPeriod", timetableView.getExpandTransitionPeriod().intValue());

        return stylingParams;
    }

    @Override
    public void decode(FacesContext context, UIComponent component) {
        super.decode(context, component);
        MonthTable timetableView = (MonthTable) component;

        Map<String, String> requestParams = context.getExternalContext().getRequestParameterMap();
        String clientId = timetableView.getClientId(context);
        String dayStr = requestParams.get(clientId + Rendering.CLIENT_ID_SUFFIX_SEPARATOR + "day");
        if (dayStr != null) {
            TimeZone timeZone = (timetableView.getTimeZone() != null)
                    ? timetableView.getTimeZone()
                    : TimeZone.getDefault();
            Date day = DataUtil.parseDateFromJs(dayStr, timeZone);
            timetableView.setDay(day);
        }
        int scrollOffset = 0;
        String scrollOffsetStr = requestParams.get(clientId + Rendering.CLIENT_ID_SUFFIX_SEPARATOR + "scrollPos");
        if (scrollOffsetStr != null) {
            try {
                scrollOffset = Integer.parseInt(scrollOffsetStr);
            } catch (NumberFormatException ignore) {
            }
        }
        timetableView.setScrollOffset(scrollOffset);
        decodeTimetableChanges(context, timetableView);
    }

    @Override
    protected JSONArray encodeRequestedEventsArray(
            FacesContext context,
            TimetableView timetableView,
            JSONObject jsonParam,
            Map<String, AbstractTimetableEvent> putLoadedEventsHere) throws JSONException, IOException {
        Map<String, TimeZone> timeZoneParam = getTimeZoneParamForJSONConverter(timetableView);
        ValueExpression eventsExpression = timetableView.getEventsValueExpression();
        List<AbstractTimetableEvent> events = eventsExpression == null
                ? Collections.emptyList()
                : DataUtil.readDataModelExpressionAsList(context, eventsExpression);

        if (putLoadedEventsHere != null)
            for (AbstractTimetableEvent event : events) {
                putLoadedEventsHere.put(event.getId(), event);
            }

        encodeEventAreas(context, timetableView, events);
        return DataUtil.listToJSONArray(events, timeZoneParam);
    }

    protected  String getDefaultExpandedDayViewClass(){
        return DEFAULT_EXPANDED_DAY_VIEW_CLASS;
    }

    protected String getComponentName() {
        return "MonthTable";
    }

    protected String getTagName() {
        return "<o:monthTable>";
    }

}
TOP

Related Classes of org.openfaces.renderkit.timetable.MonthTableRenderer

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.