From 6d5dc34f342927a3da90fab0913ae11a05dd3507 Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Wed, 23 Jul 2008 10:36:23 +0000 Subject: [PATCH] Performance Analysis implemented --- .../src/org/adempiere/webui/Desktop.java | 139 ++--- .../adempiere/webui/apps/graph/WBarGraph.java | 514 ++++++++++++++++++ .../adempiere/webui/apps/graph/WPAPanel.java | 95 ++++ .../webui/apps/graph/WPerformanceDetail.java | 34 ++ .../apps/graph/WPerformanceIndicator.java | 322 +++++++++++ .../src/org/compiere/apps/wf/WFActivity.java | 2 +- 6 files changed, 1039 insertions(+), 67 deletions(-) create mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WBarGraph.java create mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WPAPanel.java create mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WPerformanceDetail.java create mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WPerformanceIndicator.java diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/Desktop.java b/zkwebui/WEB-INF/src/org/adempiere/webui/Desktop.java index ce86e21c64..7675f2b038 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/Desktop.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/Desktop.java @@ -27,10 +27,8 @@ import java.util.logging.Level; import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.apps.ProcessDialog; +import org.adempiere.webui.apps.graph.WPAPanel; import org.adempiere.webui.component.Button; -import org.adempiere.webui.component.Grid; -import org.adempiere.webui.component.Row; -import org.adempiere.webui.component.Rows; import org.adempiere.webui.component.Tabpanel; import org.adempiere.webui.component.ToolBarButton; import org.adempiere.webui.component.Window; @@ -66,14 +64,12 @@ import org.zkoss.zk.ui.event.Events; import org.zkoss.zkex.zul.Borderlayout; import org.zkoss.zkex.zul.Center; import org.zkoss.zkex.zul.North; -import org.zkoss.zkex.zul.South; import org.zkoss.zkex.zul.West; import org.zkoss.zul.Box; import org.zkoss.zul.Caption; import org.zkoss.zul.Groupbox; import org.zkoss.zul.Hbox; import org.zkoss.zul.Iframe; -import org.zkoss.zul.Label; import org.zkoss.zul.Separator; import org.zkoss.zul.Vbox; @@ -151,28 +147,81 @@ public class Desktop extends AbstractUIPart implements MenuListener, Serializabl return layout; } - private void createHomeTab() { + private void createHomeTab() + { Tabpanel homeTab = new Tabpanel(); windowContainer.addWindow(homeTab, "Home", false); + Hbox hbox = new Hbox(); + homeTab.appendChild(hbox); + hbox.setWidths("30%, 70%"); + + Vbox vbGroupBox = new Vbox(); + hbox.appendChild(vbGroupBox); + vbGroupBox.setWidth("100%"); + Groupbox gbxFav = new Groupbox(); - gbxFav.setMold("3d"); - gbxFav.setClosable(true); - gbxFav.setHeight("100%"); + vbGroupBox.appendChild(gbxFav); gbxFav.appendChild(new Caption("Favourites")); gbxFav.appendChild(createFavouritesPanel()); + gbxFav.setMold("3d"); + gbxFav.setClosable(true); Groupbox gbxView = new Groupbox(); - gbxView.setMold("3d"); - gbxView.setClosable(true); - gbxView.setHeight("100%"); + vbGroupBox.appendChild(gbxView); gbxView.appendChild(new Caption("Views")); gbxView.appendChild(createViewPanel()); + gbxView.setMold("3d"); + gbxView.setClosable(true); - final Hbox hbox = new Hbox(); + final Groupbox gbxAct = new Groupbox(); + vbGroupBox.appendChild(gbxAct); + gbxAct.appendChild(new Caption("Activities")); + gbxAct.appendChild(createActivitiesPanel()); + gbxAct.setMold("3d"); + gbxAct.setClosable(true); + + WPAPanel panel = WPAPanel.get(); + hbox.appendChild(panel); + + //register as 0 + registerWindow(homeTab); + + // enable server push for this desktop + if (!gbxAct.getDesktop().isServerPushEnabled()) + gbxAct.getDesktop().enableServerPush(true); + + updateInfo(); + + new Thread(new Runnable() + { + public void run() + { + try { + // get full control of desktop + Executions.activate(gbxAct.getDesktop()); + try { + updateInfo(); + Threads.sleep(500);// Update each 0.5 seconds + } catch (Error ex) { + throw ex; + } finally { + // release full control of desktop + Executions.deactivate(gbxAct.getDesktop()); + } + } catch (Exception e) { + logger.log(Level.WARNING, "Failed to run NRW", e); + } + } + }).start(); + } + + private Box createActivitiesPanel() + { + Vbox vbox = new Vbox(); btnNotice = new Button(); - hbox.appendChild(btnNotice); + vbox.appendChild(btnNotice); btnNotice.setLabel("Notice : 0"); btnNotice.setTooltiptext("Notice"); btnNotice.setImage("/images/GetMail16.gif"); @@ -181,7 +230,7 @@ public class Desktop extends AbstractUIPart implements MenuListener, Serializabl btnNotice.addEventListener(Events.ON_CLICK, this); btnRequest = new Button(); - hbox.appendChild(btnRequest); + vbox.appendChild(btnRequest); btnRequest.setLabel("Request : 0"); btnRequest.setTooltiptext("Request"); btnRequest.setImage("/images/Request16.gif"); @@ -190,64 +239,15 @@ public class Desktop extends AbstractUIPart implements MenuListener, Serializabl btnRequest.addEventListener(Events.ON_CLICK, this); btnWorkflow = new Button(); - hbox.appendChild(btnWorkflow); + vbox.appendChild(btnWorkflow); btnWorkflow.setLabel("Workflow Activities : 0"); btnWorkflow.setTooltiptext("Workflow Activities"); btnWorkflow.setImage("/images/Assignment16.gif"); AD_Menu_ID = DB.getSQLValue(null, "SELECT AD_Menu_ID FROM AD_Menu WHERE Name = 'Workflow Activities' AND IsSummary = 'N'"); btnWorkflow.setName(String.valueOf(AD_Menu_ID)); btnWorkflow.addEventListener(Events.ON_CLICK, this); - - Borderlayout borderlayout = new Borderlayout(); - homeTab.appendChild(borderlayout); - borderlayout.setWidth("100%"); - borderlayout.setHeight("100%"); - borderlayout.setStyle("background-color: transparent; position: absolute;"); - West west = new West(); - west.appendChild(gbxFav); - borderlayout.appendChild(west); - west.setSplittable(true); - west.setStyle("background-color: transparent"); - - Center center = new Center(); - center.appendChild(gbxView); - borderlayout.appendChild(center); - center.setStyle("background-color: transparent"); - - South south = new South(); - south.appendChild(hbox); - borderlayout.appendChild(south); - south.setStyle("background-color: transparent"); - - //register as 0 - registerWindow(homeTab); - - // enable server push for this desktop - if (!hbox.getDesktop().isServerPushEnabled()) - hbox.getDesktop().enableServerPush(true); - - updateInfo(); - - new Thread(new Runnable() { - public void run() { - try { - // get full control of desktop - Executions.activate(hbox.getDesktop()); - try { - updateInfo(); - Threads.sleep(500);// Update each 0.5 seconds - } catch (Error ex) { - throw ex; - } finally { - // release full control of desktop - Executions.deactivate(hbox.getDesktop()); - } - } catch (Exception e) { - logger.log(Level.WARNING, "Failed to run NRW", e); - } - } - }).start(); + return vbox; } private Box createFavouritesPanel() @@ -452,6 +452,13 @@ public class Desktop extends AbstractUIPart implements MenuListener, Serializabl windowContainer.setTabTitle(0, "Home (" + total + ")", "Notice : " + noOfNotice + ", Request : " + noOfRequest + ", Workflow Activities : " + noOfWorkflow); } + + public void addWindow2TabPanel(Window window) + { + Tabpanel tabPanel = new Tabpanel(); + window.setParent(tabPanel); + windowContainer.addWindow(tabPanel, window.getTitle(), true); + } public void onEvent(Event event) { diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WBarGraph.java b/zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WBarGraph.java new file mode 100644 index 0000000000..c6b3eb897f --- /dev/null +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WBarGraph.java @@ -0,0 +1,514 @@ +package org.adempiere.webui.apps.graph; + +import java.awt.Color; +import java.awt.Point; +import java.awt.image.BufferedImage; +import java.math.BigDecimal; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.logging.Level; + +import org.adempiere.apps.graph.BarGraphColumn; +import org.adempiere.webui.apps.AEnv; +import org.adempiere.webui.component.Panel; +import org.compiere.model.MAchievement; +import org.compiere.model.MGoal; +import org.compiere.model.MMeasure; +import org.compiere.model.MMeasureCalc; +import org.compiere.model.MProjectType; +import org.compiere.model.MQuery; +import org.compiere.model.MRequestType; +import org.compiere.model.MRole; +import org.compiere.model.MStatus; +import org.compiere.util.CLogger; +import org.compiere.util.DB; +import org.compiere.util.Env; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartMouseEvent; +import org.jfree.chart.ChartRenderingInfo; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.encoders.EncoderUtil; +import org.jfree.chart.encoders.ImageFormat; +import org.jfree.chart.entity.ChartEntity; +import org.jfree.chart.plot.CategoryPlot; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.renderer.category.BarRenderer; +import org.jfree.data.category.DefaultCategoryDataset; +import org.zkoss.image.AImage; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.event.MouseEvent; +import org.zkoss.zul.Area; +import org.zkoss.zul.Imagemap; + +/** + * Bar Graph + * + * @author Jorg Janke + * @version $Id: BarGraph.java,v 1.2 2006/07/30 00:51:28 jjanke Exp $ + */ +public class WBarGraph extends Panel +{ + private static final long serialVersionUID = 1L; + + /** + * Constructor + */ + public WBarGraph() + { + super(); + } // BarGraph + + /** + * Constructor + * @param goal goal + */ + public WBarGraph(MGoal goal) + { + this(); + m_goal = goal; + m_Y_AxisLabel = goal.getName(); + m_X_AxisLabel = goal.getXAxisText(); + loadData(); + //addComponentListener(this); + } // BarGraph + + /** The Goal */ + private MGoal m_goal = null; + /** Graph Size */ + //private Dimension m_size = null; + /** Zero/Zero Coordibate point */ + private Point m_point0_0 = null; + /** Layout */ +// private BarGraphLayout m_layout = new BarGraphLayout(this); + + /** Logger */ + private static CLogger log = CLogger.getCLogger (WBarGraph.class); + + /** X Axis Label */ + private String m_X_AxisLabel = "X Axis"; + /** Y Axis Label */ + private String m_Y_AxisLabel = "Y Axis"; + /** Y Axis Max */ +// private double m_Y_Max = 0; + /** Y Axis Target Line */ +// private double m_Y_Target = 0; + /** Y Axis Target Line Label */ + private String m_Y_TargetLabel = null; +// private static Dimension paneldimension = new Dimension(180, 150); + + final DefaultCategoryDataset dataset = new DefaultCategoryDataset(); + + /** + * Load Performance Data + */ + ArrayList list = new ArrayList(); + + private void loadData() + { + // Calculated + MMeasure measure = m_goal.getMeasure(); + if (measure == null) + { + log.warning("No Measure for " + m_goal); + return; + } + if (MMeasure.MEASURETYPE_Calculated.equals(measure.getMeasureType())) + { + MMeasureCalc mc = MMeasureCalc.get(Env.getCtx(), measure.getPA_MeasureCalc_ID()); + String sql = mc.getSqlBarChart(m_goal.getRestrictions(false), + m_goal.getMeasureDisplay(), null, + MRole.getDefault()); // logged in role + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement (sql, null); + rs = pstmt.executeQuery (); + ArrayList dataList = new ArrayList(); + while (rs.next ()) + { + BigDecimal data = rs.getBigDecimal(1); + Timestamp date = rs.getTimestamp(2); + BarGraphColumn bgc = new BarGraphColumn(mc, data); + bgc.setLabel(date, m_goal.getMeasureDisplay()); //TODO copy order-loop to other measures + int pos=0; + for (int i = 0; i < dataList.size(); i++) + if (dataList.get(i).before(date)) pos++; + dataList.add(date); // list of dates + list.add(pos, bgc); + } + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + finally + { + DB.close(rs, pstmt); + rs = null; pstmt = null; + } + } + else if (MMeasure.MEASURETYPE_Achievements.equals(measure.getMeasureType())) + { + if (MMeasure.MEASUREDATATYPE_StatusQtyAmount.equals(measure.getMeasureDataType())) + { + MAchievement[] achievements = MAchievement.get(measure); + for (int i = 0; i < achievements.length; i++) + { + MAchievement achievement = achievements[i]; + BarGraphColumn bgc = new BarGraphColumn(achievement); + list.add(bgc); + } + } + else // MMeasure.MEASUREDATATYPE_QtyAmountInTime + { + String MeasureDisplay = m_goal.getMeasureDisplay(); + String trunc = "D"; + if (MGoal.MEASUREDISPLAY_Year.equals(MeasureDisplay)) + trunc = "Y"; + else if (MGoal.MEASUREDISPLAY_Quarter.equals(MeasureDisplay)) + trunc = "Q"; + else if (MGoal.MEASUREDISPLAY_Month.equals(MeasureDisplay)) + trunc = "MM"; + else if (MGoal.MEASUREDISPLAY_Week.equals(MeasureDisplay)) + trunc = "W"; + // else if (MGoal.MEASUREDISPLAY_Day.equals(MeasureDisplay)) + // trunc = "D"; + trunc = "TRUNC(DateDoc,'" + trunc + "')"; + StringBuffer sql = new StringBuffer ("SELECT SUM(ManualActual), ") + .append(trunc).append(" FROM PA_Achievement WHERE PA_Measure_ID=? AND IsAchieved='Y' ") + .append("GROUP BY ").append(trunc) + .append(" ORDER BY ").append(trunc); + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement (sql.toString(), null); + pstmt.setInt(1, measure.getPA_Measure_ID()); + rs = pstmt.executeQuery (); + while (rs.next ()) + { + BigDecimal data = rs.getBigDecimal(1); + Timestamp date = rs.getTimestamp(2); + BarGraphColumn bgc = new BarGraphColumn(m_goal, data); + bgc.setLabel(date, m_goal.getMeasureDisplay()); + list.add(bgc); + } + } + catch (Exception e) + { + log.log (Level.SEVERE, sql.toString(), e); + } + finally + { + DB.close(rs, pstmt); + rs = null; pstmt = null; + } + } // Achievement in time + } // Achievement + + // Request + else if (MMeasure.MEASURETYPE_Request.equals(measure.getMeasureType())) + { + MRequestType rt = MRequestType.get(Env.getCtx(), measure.getR_RequestType_ID()); + String sql = rt.getSqlBarChart(m_goal.getRestrictions(false), + m_goal.getMeasureDisplay(), measure.getMeasureDataType(), + null, MRole.getDefault()); // logged in role + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement (sql, null); + rs = pstmt.executeQuery (); + while (rs.next ()) + { + BigDecimal data = rs.getBigDecimal(1); + int R_Status_ID = rs.getInt(3); + BarGraphColumn bgc = new BarGraphColumn(rt, data, R_Status_ID); + if (R_Status_ID == 0) + { + Timestamp date = rs.getTimestamp(2); + bgc.setLabel(date, m_goal.getMeasureDisplay()); + } + else + { + MStatus status = MStatus.get(Env.getCtx(), R_Status_ID); + bgc.setLabel(status.getName()); + } + list.add(bgc); + } + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + finally + { + DB.close(rs, pstmt); + rs = null; pstmt = null; + } + } // Request + + // Project + else if (MMeasure.MEASURETYPE_Project.equals(measure.getMeasureType())) + { + MProjectType pt = MProjectType.get(Env.getCtx(), measure.getC_ProjectType_ID()); + String sql = pt.getSqlBarChart(m_goal.getRestrictions(false), + m_goal.getMeasureDisplay(), measure.getMeasureDataType(), + null, MRole.getDefault()); // logged in role + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement (sql, null); + rs = pstmt.executeQuery (); + while (rs.next ()) + { + BigDecimal data = rs.getBigDecimal(1); + Timestamp date = rs.getTimestamp(2); + int id = rs.getInt(3); + BarGraphColumn bgc = new BarGraphColumn(pt, data, id); + bgc.setLabel(date, m_goal.getMeasureDisplay()); + list.add(bgc); + } + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + finally + { + DB.close(rs, pstmt); + rs = null; pstmt = null; + } + } // Project + + // Add last 20 + int startValue = 0; + //if (list.size() > 20) //TODO CHECK + // startValue = list.size()-20; + /* + for (int i = startValue; i < list.size(); i++) + add (list.get(i)); + */ + for (int i = startValue; i < list.size(); i++){ + dataset.addValue(list.get(i).getValue(), list.get(i).getLabel(), list.get(i).getLabel()); + } + + // create the chart... + final JFreeChart chart = ChartFactory.createBarChart( + measure.getName(), // chart title + m_X_AxisLabel, // domain axis label + m_Y_AxisLabel, // range axis label + dataset, // data + PlotOrientation.VERTICAL, // orientation + false, // include legend + true, // tooltips? + true // URLs? + ); + + CategoryPlot plot = chart.getCategoryPlot(); + //plot.setBackgroundPaint(Color.lightGray); //GraphUtil.getForeground(getBackground()) + BarRenderer renderer = (BarRenderer) plot.getRenderer(); + chart.getCategoryPlot().setRenderer(renderer); + renderer.setSeriesPaint(0, new Color(92/255f, 178/255f, 232/255f)); + renderer.setSeriesPaint(1, new Color(56/255f, 97/255f, 119/255f)); + renderer.setSeriesPaint(2, new Color(242/255f, 70/255f, 78/255f)); + renderer.setSeriesPaint(3, Color.orange); + renderer.setSeriesPaint(4, new Color(147/255f, 196/255f, 51/255f)); + renderer.setSeriesPaint(5, new Color(210/255f, 247/255f, 91/255f)); + renderer.setSeriesPaint(6, new Color(129/255f, 235/255f, 249/255f)); + renderer.setSeriesPaint(7, new Color(60/255f, 84/255f, 8/255f)); + renderer.setSeriesPaint(8, new Color(0.8f, 0.8f, 0.8f)); + + ChartRenderingInfo info = new ChartRenderingInfo(); + BufferedImage bi = chart.createBufferedImage(700, 500, BufferedImage.TRANSLUCENT, info); + try { + byte[] bytes = EncoderUtil.encode(bi, ImageFormat.PNG, true); + + AImage image = new AImage("", bytes); + Imagemap myImage = new Imagemap(); + + myImage.setContent(image); + appendChild(myImage); + + int count = 0; + for(Iterator it = info.getEntityCollection().getEntities().iterator(); it.hasNext(); ) + { + ChartEntity ce = ( ChartEntity ) it.next(); + + String tooltip = ce.getToolTipText(); + if(tooltip == null) continue; + + Area area = new Area(); + myImage.appendChild(area); + area.setCoords(ce.getShapeCoords()); + area.setShape(ce.getShapeType()); + area.setId("WBG_"+tooltip); + count++; + } + + myImage.addEventListener(Events.ON_CLICK, new EventListener() + { + public void onEvent(Event event) throws Exception + { + MouseEvent me = (MouseEvent) event; + String areaId = me.getArea(); + if(areaId != null) + { + for(int i = 0; i < list.size(); i++) + { + String s = "WBG_(" + list.get(i).getLabel() + ", " + list.get(i).getLabel() + ") = "; + if(areaId.startsWith(s)) + { + chartMouseClicked(i); + return; + } + } + } + } + }); + } + catch (Exception e) { + log.log (Level.SEVERE, "", e); + } + } // loadData + /** + * Get Point 0_0 + * + * @return point + */ + public Point getPoint0_0() + { + return m_point0_0; + } // getPoint0_0 + + + /** + * @return Returns the x_AxisLabel. + */ + public String getX_AxisLabel () + { + return m_X_AxisLabel; + } // getX_AxisLabel + + /** + * @param axisLabel The x_AxisLabel to set. + */ + public void setX_AxisLabel (String axisLabel) + { + m_X_AxisLabel = axisLabel; + } // setX_AxisLabel + + /** + * @return Returns the y_AxisLabel. + */ + public String getY_AxisLabel () + { + return m_Y_AxisLabel; + } // getY_AxisLabel + + /** + * @param axisLabel The y_AxisLabel to set. + */ + public void setY_AxisLabel (String axisLabel) + { + m_Y_AxisLabel = axisLabel; + } // setY_AxisLabel + + /** + * @return Returns the y_TargetLabel. + */ + public String getY_TargetLabel () + { + return m_Y_TargetLabel; + } // getY_TargetLabel + + /** + * @param targetLabel The y_TargetLabel to set. + */ + public void setY_TargetLabel (String targetLabel, double target) + { + m_Y_TargetLabel = targetLabel; +// m_Y_Target = target; + } // setY_TargetLabel + + + /** + * Add Column + * @param column column + */ + public void add (BarGraphColumn column) + { +// super.add (column, "column"); + //column.addActionListener(this); + } // add + + + /************************************************************************** + * Paint Component + * @param g graphics + */ + + public void chartMouseClicked(int index) + { + BarGraphColumn bgc = list.get(index); + if (null == bgc) + return; + log.info(bgc.getName()); + MQuery query = null; + if (bgc.getAchievement() != null) // Single Achievement + { + MAchievement a = bgc.getAchievement(); + query = MQuery.getEqualQuery("PA_Measure_ID", a.getPA_Measure_ID()); + } + else if (bgc.getGoal() != null) // Multiple Achievements + { + MGoal goal = bgc.getGoal(); + query = MQuery.getEqualQuery("PA_Measure_ID", goal + .getPA_Measure_ID()); + } + else if (bgc.getMeasureCalc() != null) // Document + { + MMeasureCalc mc = bgc.getMeasureCalc(); + query = mc.getQuery(m_goal.getRestrictions(false), bgc + .getMeasureDisplay(), bgc.getDate(), MRole.getDefault()); // logged + // in + // role + } + else if (bgc.getProjectType() != null) // Document + { + MProjectType pt = bgc.getProjectType(); + query = pt.getQuery(m_goal.getRestrictions(false), bgc + .getMeasureDisplay(), bgc.getDate(), bgc.getID(), MRole + .getDefault()); // logged in role + } + else if (bgc.getRequestType() != null) // Document + { + MRequestType rt = bgc.getRequestType(); + query = rt.getQuery(m_goal.getRestrictions(false), bgc + .getMeasureDisplay(), bgc.getDate(), bgc.getID(), MRole + .getDefault()); // logged in role + } + if (query != null) + AEnv.zoom(query); + else + log.warning("Nothing to zoom to - " + bgc); + } + + public void chartMouseMoved(ChartMouseEvent event) {} + + public BarGraphColumn[] getBarGraphColumnList() + { + BarGraphColumn[] array = new BarGraphColumn[list.size()]; + for (int i = 0; i < list.size(); i++){ + array[i] = list.get(i); + } + return array; + } +} // BarGraph diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WPAPanel.java b/zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WPAPanel.java new file mode 100644 index 0000000000..4bc16a28fe --- /dev/null +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WPAPanel.java @@ -0,0 +1,95 @@ +package org.adempiere.webui.apps.graph; + +import org.adempiere.webui.component.Grid; +import org.adempiere.webui.component.Panel; +import org.adempiere.webui.component.Row; +import org.adempiere.webui.component.Rows; +import org.compiere.model.MGoal; +import org.compiere.util.CLogger; +import org.compiere.util.Env; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.Events; + +public class WPAPanel extends Panel implements EventListener +{ + private static final long serialVersionUID = 1L; + + /** + * Get Panel if User has Perfpormance Goals + * @return panel pr null + */ + public static WPAPanel get() + { + int AD_User_ID = Env.getAD_User_ID(Env.getCtx()); + MGoal[] goals = MGoal.getUserGoals(Env.getCtx(), AD_User_ID); + if (goals.length == 0) + return null; + return new WPAPanel(goals); + } + + /************************************************************************** + * Constructor + * @param goals + */ + private WPAPanel (MGoal[] goals) + { + super (); + m_goals = goals; + init(); + } + + /** Goals */ + private MGoal[] m_goals = null; + + /** Logger */ + private static CLogger log = CLogger.getCLogger (WPAPanel.class); + + /** + * Static/Dynamic Init + */ + private void init() + { + Grid grid = new Grid(); + appendChild(grid); + grid.setStyle("margin:0; padding:0; position: absolute"); + grid.setSclass("grid-no-striped"); + grid.setOddRowSclass("even"); + + Rows rows = new Rows(); + grid.appendChild(rows); + + Row row = new Row(); + rows.appendChild(row); + row.setWidth("50%, 50%"); + for (int i = 0; i < m_goals.length; i++) + { + WPerformanceIndicator pi = new WPerformanceIndicator(m_goals[i]); + row.appendChild(pi); + pi.addEventListener(Events.ON_CLICK, this); + + if( (i + 1) < m_goals.length && (i + 1) % 2 == 0 ) + { + row = new Row(); + rows.appendChild(row); + row.setWidth("50%, 50%"); + } + } + } // init + + /** + * Action Listener for Drill Down + * @param e event + */ + public void onEvent(Event e) throws Exception + { + if (e.getTarget() instanceof WPerformanceIndicator) + { + WPerformanceIndicator pi = (WPerformanceIndicator) e.getTarget(); + log.info(pi.toString()); + MGoal goal = pi.getGoal(); + if (goal.getMeasure() != null) + new WPerformanceDetail(goal); + } + } +} diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WPerformanceDetail.java b/zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WPerformanceDetail.java new file mode 100644 index 0000000000..e48826221a --- /dev/null +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WPerformanceDetail.java @@ -0,0 +1,34 @@ +package org.adempiere.webui.apps.graph; + +import org.adempiere.webui.Desktop; +import org.adempiere.webui.component.Window; +import org.adempiere.webui.session.SessionManager; +import org.compiere.model.MGoal; + +/** + * Performance Detail Frame. + * BarPanel for Drill-Down + * + * @author Jorg Janke + * @version $Id: PerformanceDetail.java,v 1.2 2006/07/30 00:51:28 jjanke Exp $ + */ +public class WPerformanceDetail extends Window +{ + private static final long serialVersionUID = 1L; + + /** + * Constructor. + * Called from PAPanel, ViewPI (Performance Indicator) + * @param goal goal + */ + public WPerformanceDetail (MGoal goal) + { + super(); + setTitle(goal.getName()); + + WBarGraph barPanel = new WBarGraph(goal); + appendChild(barPanel); + + ((Desktop) SessionManager.getAppDesktop()).addWindow2TabPanel(this); + } // PerformanceDetail +} diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WPerformanceIndicator.java b/zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WPerformanceIndicator.java new file mode 100644 index 0000000000..6cf28e9f34 --- /dev/null +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/apps/graph/WPerformanceIndicator.java @@ -0,0 +1,322 @@ +package org.adempiere.webui.apps.graph; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.image.BufferedImage; +import java.text.DecimalFormat; + +import org.adempiere.webui.component.Panel; +import org.compiere.model.MColorSchema; +import org.compiere.model.MGoal; +import org.compiere.util.DisplayType; +import org.compiere.util.Env; +import org.compiere.util.Msg; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.encoders.EncoderUtil; +import org.jfree.chart.encoders.ImageFormat; +import org.jfree.chart.plot.DialShape; +import org.jfree.chart.plot.MeterInterval; +import org.jfree.chart.plot.MeterPlot; +import org.jfree.data.Range; +import org.jfree.data.general.DefaultValueDataset; +import org.jfree.ui.RectangleInsets; +import org.zkoss.image.AImage; +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.Image; +import org.zkoss.zul.Menuitem; +import org.zkoss.zul.Menupopup; + +/** + * Performance Indicator + * + * @author Jorg Janke + * @version $Id: PerformanceIndicator.java,v 1.2 2006/07/30 00:51:28 jjanke Exp $ + */ +public class WPerformanceIndicator extends Panel implements EventListener +{ + private static final long serialVersionUID = 1L; + + /** + * Constructor + * @param goal goal model + */ + public WPerformanceIndicator(MGoal goal) + { + super(); + m_goal = goal; +// setName(m_goal.getName()); + + init(); + mRefresh.addEventListener(Events.ON_CLICK, this); + popupMenu.appendChild(mRefresh); + + addEventListener(Events.ON_DOUBLE_CLICK, this); + addEventListener(Events.ON_CLICK, this); + } // PerformanceIndicator + + private MGoal m_goal = null; + /** The Performance Name */ + private String m_text = null; + /** Performance Line */ +// private double m_line = 0; + + /** Height */ +// private static double s_height = 45; + /** 100% width */ +// private static double s_width100 = 150; + /** Max width */ +// private static double s_widthMax = 250; + /** Integer Number Format */ + private static DecimalFormat s_format = DisplayType.getNumberFormat(DisplayType.Integer); + + Menupopup popupMenu = new Menupopup(); + private Menuitem mRefresh = new Menuitem(Msg.getMsg(Env.getCtx(), "Refresh"), "/images/Refresh16.gif"); + + //Insert Pie Graph Kinamo (pelgrim) +// private static Color colorOK = Color.magenta; +// private static Color colorNotOK = Color.lightGray; +// private static Dimension indicatordimension = new Dimension(170,120); +// private static Dimension paneldimension = new Dimension(180, 150); + ChartPanel chartPanel; + //private static Dimension + + /** + * Get Goal + * @return goal + */ + public MGoal getGoal() + { + return m_goal; + } // getGoal + + private JFreeChart createChart() + { + JFreeChart chart = null; + + // Set Text + StringBuffer text = new StringBuffer(m_goal.getName()); + if (m_goal.isTarget()) + text.append(": ").append(m_goal.getPercent()).append("%"); + else + text.append(": ").append(s_format.format(m_goal.getMeasureActual())); + + m_text = text.toString(); + + // ToolTip + text = new StringBuffer(); + if (m_goal.getDescription() != null) + text.append(m_goal.getDescription()).append(": "); + text.append(s_format.format(m_goal.getMeasureActual())); + if (m_goal.isTarget()) + text.append(" ").append(Msg.getMsg(Env.getCtx(), "of")).append(" ") + .append(s_format.format(m_goal.getMeasureTarget())); + setTooltiptext(text.toString()); + // + //setBackground(m_goal.getColor()); +// setForeground(GraphUtil.getForeground(getBackground())); + // Performance Line +// int percent = m_goal.getPercent(); +// if (percent > 100) // draw 100% line +// m_line = s_width100; +// else // draw Performance Line +// m_line = s_width100 * m_goal.getGoalPerformanceDouble(); + + +// String title = m_text; + DefaultValueDataset data = new DefaultValueDataset((float)m_goal.getPercent()); + MeterPlot plot = new MeterPlot(data); + + MColorSchema colorSchema = m_goal.getColorSchema(); + int rangeLo = 0; int rangeHi=0; + for (int i=1; i<=4; i++){ + switch (i) { + case 1: rangeHi = colorSchema.getMark1Percent(); break; + case 2: rangeHi = colorSchema.getMark2Percent(); break; + case 3: rangeHi = colorSchema.getMark3Percent(); break; + case 4: rangeHi = colorSchema.getMark4Percent(); break; + } + if (rangeHi==9999) + rangeHi = (int) Math.floor(rangeLo*1.5); + if (rangeLo < rangeHi) { + plot.addInterval(new MeterInterval("Normal", //label + new Range(rangeLo, rangeHi), //range + colorSchema.getColor(rangeHi), + new BasicStroke(7.0f), + //Color.lightGray + new Color(-13091716) + //Color.gray + )); + rangeLo = rangeHi; + } + } + plot.setRange(new Range(0,rangeLo)); + + plot.setDialBackgroundPaint(new Color(-13091716));//Color.GRAY); + plot.setUnits(m_goal.getName()); + plot.setDialShape(DialShape.CHORD);//CIRCLE); + //plot.setDialBackgroundPaint(new GradientPaint(0, 0, m_goal.getColor(), 0, 1000, Color.black)); + plot.setNeedlePaint(Color.white); + plot.setTickSize(2000); + plot.setTickLabelFont(new Font("SansSerif", Font.BOLD, 12)); + plot.setTickLabelPaint(Color.white); + plot.setInsets(new RectangleInsets(1.0, 2.0, 3.0, 4.0)); + + chart = new JFreeChart( m_text, new Font("SansSerif", Font.BOLD, 12), plot,false); + + return chart; + } + + /** + * Init Graph Display + * Kinamo (pelgrim) + */ + private void init() + { + JFreeChart chart = createChart(); + + BufferedImage bi = chart.createBufferedImage(350, 250, BufferedImage.TRANSLUCENT , null); + try { + byte[] bytes = EncoderUtil.encode(bi, ImageFormat.PNG, true); + + AImage image = new AImage("", bytes); + Image myImage = new Image(); + myImage.setContent(image); + appendChild(myImage); + } + catch (Exception e) + { + // TODO: handle exception + } + + invalidate(); + } + + + /** + * Update Display Data + */ + protected void updateDisplay() + { + chartPanel.setChart(createChart()); + invalidate(); + } // updateData + + /************************************************************************** + * Adds an ActionListener to the indicator. + * @param l the ActionListener to be added + */ +/* public void addActionListener(ActionListener l) + { + if (l != null) + listenerList.add(ActionListener.class, l); + } // addActionListener +*/ + /** + * Removes an ActionListener from the indicator. + * @param l the listener to be removed + */ +/* public void removeActionListener(ActionListener l) + { + if (l != null) + listenerList.remove(ActionListener.class, l); + } // removeActionListener +*/ + /** + * Returns an array of all the ActionListeners added + * to this indicator with addActionListener(). + * + * @return all of the ActionListeners added or an empty + * array if no listeners have been added + */ +/* public ActionListener[] getActionListeners() + { + return (ActionListener[])(listenerList.getListeners(ActionListener.class)); + } // getActionListeners +*/ + /** + * Notifies all listeners that have registered interest for + * notification on this event type. The event instance + * is lazily created using the event + * parameter. + * + * @param event the ActionEvent object + * @see EventListenerList + */ +/* protected void fireActionPerformed(MouseEvent event) + { + // Guaranteed to return a non-null array + ActionListener[] listeners = getActionListeners(); + ActionEvent e = null; + // Process the listeners first to last + for (int i = 0; i < listeners.length; i++) + { + // Lazily create the event: + if (e == null) + e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, + "pi", event.getWhen(), event.getModifiers()); + listeners[i].actionPerformed(e); + } + } // fireActionPerformed +*/ + + /************************************************************************** + * Mouse Clicked + * @param e mouse event + */ +/* public void mouseClicked (MouseEvent e) + { + if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() > 1) + fireActionPerformed(e); + if (SwingUtilities.isRightMouseButton(e)) + popupMenu.show((Component)e.getSource(), e.getX(), e.getY()); + } // mouseClicked + + public void mousePressed (MouseEvent e) + { + } + + public void mouseReleased (MouseEvent e) + { + } + + public void mouseEntered (MouseEvent e) + { + } + + public void mouseExited (MouseEvent e) + { + } +*/ + /** + * Action Listener. + * Update Display + * @param e event + */ +/* public void actionPerformed (ActionEvent e) + { + if (e.getSource() == mRefresh) + { + m_goal.updateGoal(true); + updateDisplay(); + // + Container parent = getParent(); + if (parent != null) + parent.invalidate(); + invalidate(); + if (parent != null) + parent.repaint(); + else + repaint(); + } + } // actionPerformed +*/ + public void onEvent(Event event) throws Exception + { +// Component comp = event.getTarget(); +// String eventName = event.getName(); + } +} diff --git a/zkwebui/WEB-INF/src/org/compiere/apps/wf/WFActivity.java b/zkwebui/WEB-INF/src/org/compiere/apps/wf/WFActivity.java index 7eeec399dd..f0c344b70c 100644 --- a/zkwebui/WEB-INF/src/org/compiere/apps/wf/WFActivity.java +++ b/zkwebui/WEB-INF/src/org/compiere/apps/wf/WFActivity.java @@ -121,7 +121,7 @@ public class WFActivity extends ADForm implements EventListener Grid grid = new Grid(); grid.setWidth("99%"); grid.setHeight("100%"); - grid.setStyle("margin:0; padding:0; position: absolute"); + grid.setStyle("margin:0; padding:0; position: absolute; align: center; valign: center;"); grid.setSclass("grid-no-striped"); grid.setOddRowSclass("even");