org.adempiere.webui.dashboard.CalendarWindow.java Source code

Java tutorial

Introduction

Here is the source code for org.adempiere.webui.dashboard.CalendarWindow.java

Source

/******************************************************************************
 * Copyright (C) 2008 Elaine Tan                                              *
 * Copyright (C) 2008 Idalica Corporation                                     *
 * This program is free software; you can redistribute it and/or modify it    *
 * under the terms version 2 of the GNU General Public License as published   *
 * by the Free Software Foundation. This program is distributed in the hope   *
 * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.           *
 * See the GNU General Public License for more details.                       *
 * You should have received a copy of the GNU General Public License along    *
 * with this program; if not, write to the Free Software Foundation, Inc.,    *
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.                     *
 *****************************************************************************/
package org.adempiere.webui.dashboard;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TimeZone;

import org.adempiere.webui.component.Tabpanel;
import org.adempiere.webui.component.Window;
import org.adempiere.webui.panel.ITabOnCloseHandler;
import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.theme.ThemeManager;
import org.compiere.model.MSysConfig;
import org.compiere.model.X_R_RequestType;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.Util;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.encoders.EncoderUtil;
import org.jfree.chart.encoders.ImageFormat;
import org.jfree.chart.plot.PiePlot3D;
import org.jfree.data.general.DefaultPieDataset;
import org.zkoss.calendar.Calendars;
import org.zkoss.calendar.api.CalendarEvent;
import org.zkoss.calendar.event.CalendarsEvent;
import org.zkoss.calendar.impl.SimpleCalendarEvent;
import org.zkoss.calendar.impl.SimpleCalendarModel;
import org.zkoss.image.AImage;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Borderlayout;
import org.zkoss.zul.Button;
import org.zkoss.zul.Image;
import org.zkoss.zul.Label;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Popup;
import org.zkoss.zul.Span;
import org.zkoss.zul.Tab;
import org.zkoss.zul.Timer;
import org.zkoss.zul.Toolbarbutton;

/**
 * 
 * @author Elaine
 *
 */
public class CalendarWindow extends Window implements EventListener<Event>, ITabOnCloseHandler {
    /**
     * 
     */
    private static final long serialVersionUID = 1576992746053720647L;

    private Calendars calendars;
    private SimpleCalendarModel scm;
    private Toolbarbutton btnRefresh;
    private Listbox lbxRequestTypes;
    private Image myChart;
    private Button btnCurrentDate, btnSwitchTimeZone;
    private Label lblDate;
    private Component divArrowLeft, divArrowRight;
    private Span FDOW;
    private Listbox lbxFDOW;
    private Component divTabDay, divTabWeek, divTabWeekdays, divTabMonth;
    private Popup updateMsg;
    private Label popupLabel;
    private Timer timer;

    private EventWindow eventWin;

    public CalendarWindow(SimpleCalendarModel scm) {

        super();

        this.scm = scm;
        Properties ctx = Env.getCtx();
        setTitle(Msg.getMsg(ctx, "Calendar"));
        setAttribute(Window.MODE_KEY, Window.MODE_EMBEDDED);

        Component component = Executions
                .createComponents(ThemeManager.getThemeResource("zul/calendar/calendar.zul"), this, null);

        Borderlayout borderlayout = (Borderlayout) component.getFellow("main");
        borderlayout.setStyle("position: absolute");
        borderlayout.setWidth("100%");
        borderlayout.setHeight("100%");

        calendars = (Calendars) component.getFellow("cal");
        calendars.setModel(scm);
        if (calendars.getCurrentDate() != null)
            calendars.setCurrentDate(calendars.getCurrentDate());
        setTimeZone();

        btnRefresh = (Toolbarbutton) component.getFellow("btnRefresh");
        btnRefresh.addEventListener(Events.ON_CLICK, this);

        lbxRequestTypes = (Listbox) component.getFellow("lbxRequestTypes");
        lbxRequestTypes.addEventListener(Events.ON_SELECT, this);

        lbxRequestTypes.appendItem(Msg.getMsg(ctx, "ShowAll"), "0");
        ArrayList<X_R_RequestType> types = DPCalendar.getRequestTypes(Env.getCtx());
        for (X_R_RequestType type : types)
            lbxRequestTypes.appendItem(type.getName(), type.getR_RequestType_ID() + "");
        lbxRequestTypes.setSelectedIndex(0);

        myChart = (Image) component.getFellow("mychart");
        myChart.addEventListener(Events.ON_CREATE, this);

        btnCurrentDate = (Button) component.getFellow("btnCurrentDate");
        btnCurrentDate.addEventListener(Events.ON_CLICK, this);

        btnSwitchTimeZone = (Button) component.getFellow("btnSwitchTimeZone");
        btnSwitchTimeZone.addEventListener(Events.ON_CLICK, this);

        lblDate = (Label) component.getFellow("lblDate");
        lblDate.addEventListener(Events.ON_CREATE, this);

        divArrowLeft = component.getFellow("divArrowLeft");
        divArrowLeft.addEventListener("onMoveDate", this);

        divArrowRight = component.getFellow("divArrowRight");
        divArrowRight.addEventListener("onMoveDate", this);

        FDOW = (Span) component.getFellow("FDOW");
        FDOW.addEventListener(Events.ON_CREATE, this);

        lbxFDOW = (Listbox) component.getFellow("lbxFDOW");
        lbxFDOW.addEventListener(Events.ON_SELECT, this);
        lbxFDOW.addEventListener(Events.ON_CREATE, this);

        String[] days = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
        for (String day : days) {
            lbxFDOW.appendItem(Msg.getMsg(Env.getCtx(), day), day);
        }

        divTabDay = component.getFellow("divTabDay");
        divTabDay.addEventListener("onUpdateView", this);

        divTabWeek = component.getFellow("divTabWeek");
        divTabWeek.addEventListener("onUpdateView", this);

        divTabWeekdays = component.getFellow("divTabWeekdays");
        divTabWeekdays.addEventListener("onUpdateView", this);

        divTabMonth = component.getFellow("divTabMonth");
        divTabMonth.addEventListener("onUpdateView", this);

        updateMsg = (Popup) component.getFellow("updateMsg");

        popupLabel = (Label) component.getFellow("popupLabel");

        timer = (Timer) component.getFellow("timer");

        this.appendChild(component);

        calendars.addEventListener("onEventCreate", this);
        calendars.addEventListener("onEventEdit", this);
        calendars.addEventListener("onEventUpdate", this);
        calendars.addEventListener("onMouseOver", this);

        SessionManager.getAppDesktop().showWindow(this);

        // IDEMPIERE-1457: when show this window on tab, handle event close to remove calendars away scm
        Component parentTab = this.getParent();
        if (parentTab != null && parentTab.getClass().equals(Tabpanel.class)) {
            ((Tabpanel) parentTab).setOnCloseHandler(this);
        }
    }

    public void onClose(Tabpanel tabPanel) {
        //IDEMPIERE-1457: On close, remove calendars away scm         
        calendars.setModel(null);
        Tab tab = tabPanel.getLinkedTab();
        tab.close();
    }

    public void onEvent(Event e) throws Exception {
        String type = e.getName();

        if (type.equals(Events.ON_CLICK)) {
            if (e.getTarget() == btnRefresh)
                btnRefreshClicked();
            else if (e.getTarget() == btnCurrentDate)
                btnCurrentDateClicked();
            else if (e.getTarget() == btnSwitchTimeZone)
                btnSwitchTimeZoneClicked();
        } else if (type.equals(Events.ON_CREATE)) {
            if (e.getTarget() == lblDate)
                updateDateLabel();
            else if (e.getTarget() == FDOW)
                FDOW.setVisible("month".equals(calendars.getMold()) || calendars.getDays() == 7);
            else if (e.getTarget() == myChart)
                syncModel();
            else if (e.getTarget() == lbxFDOW)
                lbxFDOW.setSelectedIndex(0);
        } else if (type.equals("onMoveDate")) {
            if (e.getTarget() == divArrowLeft)
                divArrowClicked(false);
            else if (e.getTarget() == divArrowRight)
                divArrowClicked(true);
        } else if (type.equals("onUpdateView")) {
            String text = String.valueOf(e.getData());
            int days = Msg.getMsg(Env.getCtx(), "Day").equals(text) ? 1
                    : Msg.getMsg(Env.getCtx(), "5Days").equals(text) ? 5
                            : Msg.getMsg(Env.getCtx(), "Week").equals(text) ? 7 : 0;
            divTabClicked(days);
        } else if (type.equals(Events.ON_SELECT)) {
            if (e.getTarget() == lbxRequestTypes) {
                Listitem li = lbxRequestTypes.getSelectedItem();
                if (li == null)
                    return;

                if (li.getValue() == null)
                    return;
                int R_RequestType_ID = Integer.parseInt(li.getValue().toString());

                scm.clear();
                ArrayList<ADCalendarEvent> events = DPCalendar.getEvents(R_RequestType_ID, Env.getCtx());
                for (ADCalendarEvent event : events)
                    scm.add(event);

                calendars.invalidate();
                syncModel();
            } else if (e.getTarget() == lbxFDOW) {
                calendars.setFirstDayOfWeek(lbxFDOW.getSelectedItem().getValue().toString());
                syncModel();
            }
        } else if (type.equals("onEventCreate")) {
            if (e instanceof CalendarsEvent) {
                CalendarsEvent calendarsEvent = (CalendarsEvent) e;
                RequestWindow requestWin = new RequestWindow(calendarsEvent, this);
                SessionManager.getAppDesktop().showWindow(requestWin);
            }
        } else if (type.equals("onEventEdit")) {
            if (e instanceof CalendarsEvent) {
                CalendarsEvent calendarsEvent = (CalendarsEvent) e;
                CalendarEvent calendarEvent = calendarsEvent.getCalendarEvent();

                if (calendarEvent instanceof ADCalendarEvent) {
                    ADCalendarEvent ce = (ADCalendarEvent) calendarEvent;

                    if (eventWin == null)
                        eventWin = new EventWindow();
                    eventWin.setData(ce);
                    SessionManager.getAppDesktop().showWindow(eventWin);
                }
            }
        } else if (type.equals("onEventUpdate")) {
            if (e instanceof CalendarsEvent) {
                CalendarsEvent evt = (CalendarsEvent) e;
                SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/d");
                sdf1.setTimeZone(calendars.getDefaultTimeZone());
                StringBuilder sb = new StringBuilder("Update... from ");
                sb.append(sdf1.format(evt.getCalendarEvent().getBeginDate()));
                sb.append(" to ");
                sb.append(sdf1.format(evt.getBeginDate()));
                popupLabel.setValue(sb.toString());
                int left = evt.getX();
                int top = evt.getY();
                if (top + 100 > evt.getDesktopHeight())
                    top = evt.getDesktopHeight() - 100;
                if (left + 330 > evt.getDesktopWidth())
                    left = evt.getDesktopWidth() - 330;
                updateMsg.open(left, top);
                timer.start();
                org.zkoss.calendar.Calendars cal = (org.zkoss.calendar.Calendars) evt.getTarget();
                SimpleCalendarModel m = (SimpleCalendarModel) cal.getModel();
                SimpleCalendarEvent sce = (SimpleCalendarEvent) evt.getCalendarEvent();
                sce.setBeginDate(evt.getBeginDate());
                sce.setEndDate(evt.getEndDate());
                m.update(sce);
            }
        }
    }

    private void syncModel() {
        Hashtable<String, BigDecimal> ht = new Hashtable<String, BigDecimal>();

        List<?> list = calendars.getModel().get(calendars.getBeginDate(), calendars.getEndDate(), null);
        int size = list.size();
        for (Iterator<?> it = list.iterator(); it.hasNext();) {
            String key = ((ADCalendarEvent) it.next()).getR_RequestType_ID() + "";

            if (!ht.containsKey(key))
                ht.put(key, BigDecimal.ONE);
            else {
                BigDecimal value = ht.get(key);
                ht.put(key, value.add(BigDecimal.ONE));
            }
        }

        Hashtable<Object, String> htTypes = new Hashtable<Object, String>();
        for (int i = 0; i < lbxRequestTypes.getItemCount(); i++) {
            Listitem li = lbxRequestTypes.getItemAtIndex(i);
            if (li != null && li.getValue() != null)
                htTypes.put(li.getValue(), li.getLabel());
        }

        DefaultPieDataset pieDataset = new DefaultPieDataset();
        Enumeration<?> keys = ht.keys();
        while (keys.hasMoreElements()) {
            String key = (String) keys.nextElement();
            BigDecimal value = ht.get(key);
            String name = (String) htTypes.get(key);
            pieDataset.setValue(name == null ? "" : name,
                    new Double(size > 0 ? value.doubleValue() / size * 100 : 0));
        }

        JFreeChart chart = ChartFactory.createPieChart3D(Msg.getMsg(Env.getCtx(), "EventsAnalysis"), pieDataset,
                true, true, true);
        PiePlot3D plot = (PiePlot3D) chart.getPlot();
        plot.setForegroundAlpha(0.5f);
        BufferedImage bi = chart.createBufferedImage(600, 250);
        try {
            byte[] bytes = EncoderUtil.encode(bi, ImageFormat.PNG, true);
            AImage image = new AImage("Pie Chart", bytes);
            myChart.setContent(image);
        } catch (IOException e) {
            e.printStackTrace();
        }
        htTypes = null;
        ht = null;
    }

    public void onRefresh() {
        btnRefreshClicked();
    }

    private void btnRefreshClicked() {
        int R_RequestType_ID = 0;
        Listitem li = lbxRequestTypes.getSelectedItem();
        if (li != null && li.getValue() != null)
            R_RequestType_ID = Integer.parseInt(li.getValue().toString());

        int cnt = lbxRequestTypes.getItemCount();
        for (int i = cnt - 1; i >= 0; i--)
            lbxRequestTypes.removeItemAt(i);

        lbxRequestTypes.appendItem(Msg.getMsg(Env.getCtx(), "ShowAll"), "0");
        ArrayList<X_R_RequestType> types = DPCalendar.getRequestTypes(Env.getCtx());
        for (X_R_RequestType requestType : types) {
            Listitem item = lbxRequestTypes.appendItem(requestType.getName(),
                    requestType.getR_RequestType_ID() + "");
            if (R_RequestType_ID == requestType.getR_RequestType_ID())
                lbxRequestTypes.setSelectedItem(item);
        }
        if (lbxRequestTypes.getSelectedIndex() < 0)
            lbxRequestTypes.setSelectedIndex(0);

        scm.clear();
        ArrayList<ADCalendarEvent> events = DPCalendar.getEvents(R_RequestType_ID, Env.getCtx());
        for (ADCalendarEvent event : events)
            scm.add(event);

        calendars.invalidate();
        syncModel();
    }

    private void setTimeZone() {
        String alternateTimeZone = MSysConfig.getValue(MSysConfig.CALENDAR_ALTERNATE_TIMEZONE, "Pacific Time=PST",
                Env.getAD_Client_ID(Env.getCtx()));
        TimeZone defaultTimeZone = TimeZone.getDefault();
        calendars.addTimeZone(defaultTimeZone.getDisplayName(), defaultTimeZone);
        if (!Util.isEmpty(alternateTimeZone, true)) {
            if (!alternateTimeZone.equalsIgnoreCase(defaultTimeZone.getDisplayName())) {
                String[] pair = alternateTimeZone.split("=");
                calendars.addTimeZone(pair[0].trim(), pair[1].trim());
            }
        }
    }

    private void updateDateLabel() {
        Date b = calendars.getBeginDate();
        Date e = calendars.getEndDate();
        SimpleDateFormat sdfV = DisplayType.getDateFormat();
        sdfV.setTimeZone(calendars.getDefaultTimeZone());
        lblDate.setValue(sdfV.format(b) + " - " + sdfV.format(e));
    }

    private void btnCurrentDateClicked() {
        calendars.setCurrentDate(Calendar.getInstance(calendars.getDefaultTimeZone()).getTime());
        updateDateLabel();
        syncModel();
    }

    private void btnSwitchTimeZoneClicked() {
        Map<?, ?> zone = calendars.getTimeZones();
        if (!zone.isEmpty()) {
            @SuppressWarnings("unchecked")
            Map.Entry<TimeZone, String> me = (Map.Entry<TimeZone, String>) zone.entrySet().iterator().next();
            calendars.removeTimeZone((TimeZone) me.getKey());
            calendars.addTimeZone((String) me.getValue(), (TimeZone) me.getKey());
        }
        syncModel();
    }

    private void divArrowClicked(boolean isNext) {
        if (isNext)
            calendars.nextPage();
        else
            calendars.previousPage();
        updateDateLabel();
        syncModel();
    }

    private void divTabClicked(int days) {
        if (days > 0) {
            calendars.setMold("default");
            calendars.setDays(days);
        } else
            calendars.setMold("month");
        updateDateLabel();
        FDOW.setVisible("month".equals(calendars.getMold()) || calendars.getDays() == 7);
    }
}