From 0330d31ac607efaa967b2626eaa88c791a081a0b Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Sun, 8 Jul 2007 09:38:56 +0000 Subject: [PATCH] [ 1748932 ] enhanced dashboard / graph package --- .../org/adempiere/apps/graph/BarGraph.java | 523 ++++++++++++++++++ .../adempiere/apps/graph/BarGraphColumn.java | 487 ++++++++++++++++ .../adempiere/apps/graph/BarGraphLayout.java | 156 ++++++ .../adempiere/apps/graph/FCHtmlEditorKit.java | 90 +++ .../org/adempiere/apps/graph/GraphUtil.java | 168 ++++++ .../adempiere/apps/graph/HtmlDashboard.java | 467 ++++++++++++++++ .../src/org/adempiere/apps/graph/PAPanel.java | 175 ++++++ .../apps/graph/PerformanceDetail.java | 75 +++ .../apps/graph/PerformanceIndicator.java | 358 ++++++++++++ client/src/org/compiere/apps/AMenu.java | 2 +- client/src/org/compiere/images/PAPanel.css | 53 ++ client/src/org/compiere/images/logo_ad.png | Bin 0 -> 9060 bytes 12 files changed, 2553 insertions(+), 1 deletion(-) create mode 100644 client/src/org/adempiere/apps/graph/BarGraph.java create mode 100644 client/src/org/adempiere/apps/graph/BarGraphColumn.java create mode 100644 client/src/org/adempiere/apps/graph/BarGraphLayout.java create mode 100644 client/src/org/adempiere/apps/graph/FCHtmlEditorKit.java create mode 100644 client/src/org/adempiere/apps/graph/GraphUtil.java create mode 100644 client/src/org/adempiere/apps/graph/HtmlDashboard.java create mode 100644 client/src/org/adempiere/apps/graph/PAPanel.java create mode 100644 client/src/org/adempiere/apps/graph/PerformanceDetail.java create mode 100644 client/src/org/adempiere/apps/graph/PerformanceIndicator.java create mode 100644 client/src/org/compiere/images/PAPanel.css create mode 100644 client/src/org/compiere/images/logo_ad.png diff --git a/client/src/org/adempiere/apps/graph/BarGraph.java b/client/src/org/adempiere/apps/graph/BarGraph.java new file mode 100644 index 0000000000..74621f0e2c --- /dev/null +++ b/client/src/org/adempiere/apps/graph/BarGraph.java @@ -0,0 +1,523 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.adempiere.apps.graph; + +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.*; +import java.util.*; +import java.util.logging.*; +import java.math.*; +import java.sql.*; + +import org.compiere.apps.*; +import org.compiere.model.*; +import org.compiere.swing.*; +import org.compiere.util.*; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartMouseEvent; +import org.jfree.chart.ChartMouseListener; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.entity.CategoryItemEntity; +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.CategoryDataset; +import org.jfree.data.category.DefaultCategoryDataset; +import org.jfree.data.general.DefaultValueDataset; + +/** + * Bar Graph + * + * @author Jorg Janke + * @version $Id: BarGraph.java,v 1.2 2006/07/30 00:51:28 jjanke Exp $ + */ +public class BarGraph extends CPanel implements ChartMouseListener //, ComponentListener //, ActionListener +{ + /** + * Constructor + */ + public BarGraph() + { + super(); + this.setLayout(new BorderLayout()); + } // BarGraph + + /** + * Constructor + * @param goal goal + */ + public BarGraph(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 (BarGraph.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; + try + { + pstmt = DB.prepareStatement (sql, null); + ResultSet 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); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + 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; + try + { + pstmt = DB.prepareStatement (sql.toString(), null); + pstmt.setInt(1, measure.getPA_Measure_ID()); + ResultSet 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); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql.toString(), e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + 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; + try + { + pstmt = DB.prepareStatement (sql, null); + ResultSet 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); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + 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; + try + { + pstmt = DB.prepareStatement (sql, null); + ResultSet 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); + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log (Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + 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)); + + chartPanel = new ChartPanel(chart); + chartPanel.setSize(getSize()); + chartPanel.addChartMouseListener(this); + add(chartPanel,BorderLayout.CENTER); + this.setMinimumSize(paneldimension); + } // loadData + private ChartPanel chartPanel; + /** + * 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(ChartMouseEvent event){ + if ((event.getEntity()!=null) && (event.getTrigger().getClickCount() > 1)) { + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + BarGraphColumn bgc = null; + String eventUrl = event.getEntity().toString(); + for (int i = 0; i < list.size(); i++){ + if ( eventUrl.substring(eventUrl.length() - list.get(i).getLabel().length()).equals(list.get(i).getLabel())) + bgc = list.get(i); + } + 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); + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + + 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; + } + + /* + public void componentHidden(ComponentEvent e) { + // TODO Auto-generated method stub + + } + public void componentMoved(ComponentEvent e) { + // TODO Auto-generated method stub + + } + public void componentResized(ComponentEvent e) { + // TODO Auto-generated method stub + float aspectRatio = 1.6f; + Dimension size = getSize(); + if (size.width > size.height * aspectRatio) + chartPanel.setSize( new Dimension( + java.lang.Math.round(size.height*aspectRatio), + size.height)); + else + chartPanel.setSize(new Dimension( + size.width, + java.lang.Math.round(size.width / aspectRatio))); + } + public void componentShown(ComponentEvent e) { + // TODO Auto-generated method stub + } + */ +} // BarGraph diff --git a/client/src/org/adempiere/apps/graph/BarGraphColumn.java b/client/src/org/adempiere/apps/graph/BarGraphColumn.java new file mode 100644 index 0000000000..7a6bfd7be2 --- /dev/null +++ b/client/src/org/adempiere/apps/graph/BarGraphColumn.java @@ -0,0 +1,487 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.adempiere.apps.graph; + +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.*; +import javax.swing.*; +import javax.swing.event.*; +import java.math.*; +import java.sql.*; +import java.text.*; + +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * Bar Graph Column + * + * @author Jorg Janke + * @version $Id: BarGraphColumn.java,v 1.2 2006/07/30 00:51:28 jjanke Exp $ + */ +public class BarGraphColumn extends JComponent implements MouseListener +{ + /** + * Base Constructor + * @param label label + * @param value value + */ + public BarGraphColumn (String label, double value) + { + m_label = label; + setValue(value); + addMouseListener(this); + } // BarGraphColumn + + /** + * Single Achievement Constructor + * @param achievement achievement + */ + public BarGraphColumn (MAchievement achievement) + { + this (achievement.getName(), achievement.getManualActual().doubleValue()); + m_achievement = achievement; + } // BarGraphColumn + + /** + * Achievement Goal Constructor + * @param goal goal + * @param data count + */ + public BarGraphColumn (MGoal goal, BigDecimal data) + { + this ("", data == null ? 0 : data.doubleValue()); + m_goal = goal; + } // BarGraphColumn + + /** + * Measure Calc Constructor + * @param mc MeasureCalc + */ + public BarGraphColumn (MMeasureCalc mc, BigDecimal data) + { + this ("", data == null ? 0 : data.doubleValue()); + m_mc = mc; + } // BarGraphColumn + + /** + * Request Type Constructor + * @param rt Request Type + */ + public BarGraphColumn (MRequestType rt, BigDecimal data, int id) + { + this ("", data == null ? 0 : data.doubleValue()); + m_rt = rt; + m_id = id; + } // BarGraphColumn + + /** + * Project Type Constructor + * @param pt Procet Type + */ + public BarGraphColumn (MProjectType pt, BigDecimal data, int id) + { + this ("", data == null ? 0 : data.doubleValue()); + m_pt = pt; + m_id = id; + } // BarGraphColumn + + /** Optional Achievement */ + private MAchievement m_achievement = null; + /** Measure Calc */ + private MMeasureCalc m_mc = null; + /** Goal */ + private MGoal m_goal = null; + + private MRequestType m_rt = null; + private MProjectType m_pt = null; + private int m_id = 0; + + /** Display */ + private String m_measureDisplay = null; + private Timestamp m_date = null; + + /** Column Label */ + private String m_label = null; + /** Column Data Value */ + private double m_value = 0; + /** Column Label Value */ + private String m_labelValue = ""; + /** Column Data Target Value */ + private double m_targetValue = 0; + /** Column Width in pixles */ + private double m_width = 0; + /** Column Height in pixles */ + private double m_height = 0; + + /** Logger */ + private static CLogger log = CLogger.getCLogger (BarGraphColumn.class); + /** Integer Number Format */ + private static DecimalFormat s_format = DisplayType.getNumberFormat(DisplayType.Integer); + + /** + * Get Achievement Goal + * @return achievement or null + */ + public MGoal getGoal() + { + return m_goal; + } // getGoal + + + /** + * Get Single Achievement + * @return achievement or null + */ + public MAchievement getAchievement() + { + return m_achievement; + } // getAchievement + + /** + * Get MeasureCalc + * @return measure + */ + public MMeasureCalc getMeasureCalc() + { + return m_mc; + } // getMeasureCalc + + public MRequestType getRequestType() + { + return m_rt; + } + + public MProjectType getProjectType() + { + return m_pt; + } + + public String getMeasureDisplay() + { + return m_measureDisplay; + } // getMeasureDisplay + + public Timestamp getDate() + { + return m_date; + } // getDate + + public int getID() + { + return m_id; + } + + /** + * Set Background and matching Foreground + * @param bg background + */ + public void setBackground (Color bg) + { + super.setBackground (bg); + setForeground(GraphUtil.getForeground(bg)); + } // setBackground + + /** + * @return Returns the label. + */ + public String getLabel () + { + return m_label; + } // getLabel + + /** + * @param label The label to set. + */ + public void setLabel (String label) + { + m_label = label; + if (m_label != null) + m_labelValue = s_format.format(m_value) + " - " + m_label; + else + m_labelValue = s_format.format(m_value); + setToolTipText(m_labelValue); + setName(m_labelValue); + } // setLabel + + /** + * @param date for label. + * @param MeasureDisplay measure display + */ + public void setLabel (Timestamp date, String MeasureDisplay) + { + if (date == null) + return; + m_date = date; + m_measureDisplay = MeasureDisplay; + // + SimpleDateFormat format = DisplayType.getDateFormat(DisplayType.Date); + String text = format.format(date); + // Month only + if (MGoal.MEASUREDISPLAY_Month.equals(MeasureDisplay) + || MGoal.MEASUREDISPLAY_Quarter.equals(MeasureDisplay)) + { + String pattern = format.toPattern(); + String mmText = text; + int index = pattern.indexOf("dd"); + if (index == 0) // dd.MM.yyyy + mmText = text.substring(3); + else if (index > 0) // MM/dd/yyyy + { + mmText = text.substring(0, index-1); + if (text.length() > index+2) + mmText += text.substring(index+2); + } + setLabel(mmText); + } + else // Day + setLabel(text); + } // setLabel + + /** + * @return Returns the targetValue. + */ + public double getTargetValue () + { + return m_targetValue; + } // getTargetValue + + /** + * @param targetValue The targetValue to set. + */ + public void setTargetValue (double targetValue) + { + m_targetValue = targetValue; + } // setTargetValue + + /** + * @return Returns the data value. + */ + public double getValue () + { + return m_value; + } // getValue + + /** + * @param value The data value to set. + */ + public void setValue (double value) + { + m_value = value; + if (m_label != null) + m_labelValue = s_format.format(m_value) + " - " + m_label; + else + m_labelValue = s_format.format(m_value); + setToolTipText(m_labelValue); + setName(m_labelValue); + } // setValue + + /** + * @return Returns the column width in pixles. + */ + public double getColWidth () + { + return m_width; + } // getColWidth + + /** + * @param width The column width in pixles. + */ + public void setColWidth (double width) + { + m_width = width; + if (isPreferredSizeSet()) + setPreferredSize(null); + } // getColWidth + + /** + * @return Returns the height in pixles. + */ + public double getColHeight() + { + return m_height; + } // getHeight + + /** + * @param height The hight in pixles. + */ + public void setColHeight (double height) + { + m_height = height; + if (isPreferredSizeSet()) + setPreferredSize(null); + } // setHeight + + /** + * Get Maximum Size + * @return size + */ + public Dimension getMaximumSize () + { + return getPreferredSize(); + } // getMaximumSize + + /** + * Get Minimum Size + * @return size + */ + public Dimension getMinimumSize () + { + return getPreferredSize(); + } // getMinimumSize + + /** + * Get Preferred Size + * @return size + */ + public Dimension getPreferredSize () + { + if (!isPreferredSizeSet()) + { + Dimension size = new Dimension((int)m_width, (int)m_height); + setPreferredSize(size); + } + return super.getPreferredSize (); + } // getPreferredSize + + + /** + * Paint Component + * @param g graphics + */ + protected void paintComponent (Graphics g) + { + Graphics2D g2D = (Graphics2D)g; + Rectangle bounds = getBounds(); + // Background + g2D.setColor(getBackground()); + //Dimension size = getPreferredSize(); + Dimension size =getSize(); + System.out.println("bgc: " + size.width + " x " + size.height); + g2D.fill3DRect(0, 0, size.width, size.height, true); + + // Paint Label & Value + Color color = getForeground(); + g2D.setPaint(color); + // + Font font = getFont(); + FontMetrics fm = g2D.getFontMetrics(font); + int fontHeight = fm.getHeight(); + AffineTransform transform = AffineTransform.getRotateInstance(Math.PI*3/2); + font = font.deriveFont(transform); + g2D.setFont(font); + // + int x = (int)(size.width/2)+((fontHeight-2)/2); + if (x < fontHeight) + x = fontHeight-2; + int y = (int)(size.height-3); + g2D.drawString(m_labelValue, x, y); + log.finest("x=" + x + ",fontHeight=" + fontHeight + ", y=" + y + " - " + m_labelValue); + // Paint Target + if (m_targetValue != 0) + { + + } + } // paintComponent + + + /************************************************************************** + * 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, + "column"+m_label, 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); + } // mouseClicked + + public void mousePressed (MouseEvent e) + { + } + + public void mouseReleased (MouseEvent e) + { + } + + public void mouseEntered (MouseEvent e) + { + } + + public void mouseExited (MouseEvent e) + { + } + +} // BarGraphColumn diff --git a/client/src/org/adempiere/apps/graph/BarGraphLayout.java b/client/src/org/adempiere/apps/graph/BarGraphLayout.java new file mode 100644 index 0000000000..922b8bfae5 --- /dev/null +++ b/client/src/org/adempiere/apps/graph/BarGraphLayout.java @@ -0,0 +1,156 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.adempiere.apps.graph; + +import java.awt.*; +import java.util.*; + +import org.compiere.util.*; + +/** + * Bar Graph Layout + * + * @author Jorg Janke + * @version $Id: BarGraphLayout.java,v 1.2 2006/07/30 00:51:28 jjanke Exp $ + */ +public class BarGraphLayout + implements LayoutManager +{ + /** + * Bar Graph Layout + * @param parent parenr + */ + public BarGraphLayout (BarGraph parent) + { + m_parent = parent; + } // BarGraphLayout + + /** Parent Container */ + private BarGraph m_parent; + /** List of Components */ + private ArrayList m_list = new ArrayList(); + /** Layout Complete */ + private boolean m_layoutComplete = false; + /** Gap between columns */ + private static int XGAP = 2; + /** Gap to Axix */ + private static int YGAP = 1; + + /** Logger */ + private static CLogger log = CLogger.getCLogger (BarGraphLayout.class); + + /** + * Add Layout Component + * @param name name + * @param comp component + */ + public void addLayoutComponent (String name, Component comp) + { + if (comp instanceof BarGraphColumn) + m_list.add((BarGraphColumn)comp); + else + log.severe("Invalid Class: " + comp); + m_layoutComplete = false; + } // addLayoutComponent + + /** + * Remove Layout Component + * @param comp component + */ + public void removeLayoutComponent (Component comp) + { + m_list.remove(comp); + m_layoutComplete = false; + } // removeLayoutComponent + + /** + * Preferred Layout Size + * @param parent parent + * @return size + */ + public Dimension preferredLayoutSize (Container parent) + { + return parent.getPreferredSize(); + } // preferredLayoutSize + + /** + * Minimum Layout Size + * @param parent parent + * @return size + */ + public Dimension minimumLayoutSize (Container parent) + { + return parent.getMinimumSize(); + } // minimumLayoutSize + + + /** + * Layout Container + * @param parent + */ + public void layoutContainer (Container parent) + { + if (m_layoutComplete) + return; + + // Find Max + double maxValue = 0; + for (int i = 0; i < m_list.size(); i++) + { + BarGraphColumn column = m_list.get(i); + maxValue = Math.max(maxValue, column.getValue()); + } + // + //Dimension size = m_parent.getPreferredSize(); + Dimension size =m_parent.getSize(); + System.out.println("bgl: " +size.width + " x " + size.height); + + Point point0_0 = m_parent.getPoint0_0(); + + double graphHeight = size.height - (size.height-point0_0.y) - (2*YGAP); + double graphWidth = size.width - point0_0.x - XGAP; + double columnWidth = (graphWidth - (XGAP*m_list.size())) / m_list.size(); + columnWidth = Math.min(30, columnWidth); + FontMetrics fm = m_parent.getFontMetrics(m_parent.getFont()); + int fontHeight = fm.getHeight(); + columnWidth = Math.max(fontHeight, columnWidth); + + log.fine("Height=" + graphHeight + ", MaxValue=" + maxValue + + ", Width=" + graphWidth + ", ColumnWidth=" + columnWidth); + + int x = point0_0.x + (2*XGAP); + // Set Values + for (int i = 0; i < m_list.size(); i++) + { + BarGraphColumn column = m_list.get(i); + double multiplier = column.getValue() / maxValue; + double height = graphHeight * multiplier; + column.setColHeight(height); + column.setColWidth(columnWidth); + Dimension ps = column.getPreferredSize(); + column.setBackground(GraphUtil.getBackground(i)); + // + int y = point0_0.y - ps.height - YGAP; + column.setLocation(x, y); + column.setBounds(x, y, ps.width, ps.height); + x += ps.width + XGAP; + log.finer(i + " - " + ((int)(multiplier*100)) + "% - " + column.getBounds()); + } + m_layoutComplete = true; + } // layoutContainer + +} // BarGraphLayout diff --git a/client/src/org/adempiere/apps/graph/FCHtmlEditorKit.java b/client/src/org/adempiere/apps/graph/FCHtmlEditorKit.java new file mode 100644 index 0000000000..2e3a87db5b --- /dev/null +++ b/client/src/org/adempiere/apps/graph/FCHtmlEditorKit.java @@ -0,0 +1,90 @@ +package org.adempiere.apps.graph; + +import javax.swing.*; +import javax.swing.text.*; +import javax.swing.text.html.*; +import java.awt.*; +import java.awt.image.*; +import java.net.MalformedURLException; +import java.net.URL; +import java.sql.SQLException; + +public class FCHtmlEditorKit extends HTMLEditorKit { + public ViewFactory getViewFactory() { + if (defaultFactory == null) { + defaultFactory = new FCHtmlFactory(super.getViewFactory()); + } + return defaultFactory; + } + + private static class FCHtmlFactory implements ViewFactory { + public FCHtmlFactory(ViewFactory factory) { + oldFactory = factory; + } + public View create(Element elem) { + View result; + result = oldFactory.create(elem); + if (result instanceof ImageView) { + String src = (String)elem.getAttributes(). + getAttribute(HTML.Attribute.SRC); + if ("res:".equals(src.substring(0, 4))) { + result = new NewImageView(elem); + } + } + return result; + } + private static class NewImageView extends ImageView { + Element elem; + public NewImageView(Element elem) { + super(elem); + this.elem=elem; + } + public Image getImage() { + //return smile image + //java.awt.Toolkit.getDefaultToolkit().getImage(getImageURL()).flush(); + //if (smileImage == null) { + String src = (String)elem.getAttributes(). + getAttribute(HTML.Attribute.SRC); + //System.out.println("img load: " + src.substring(4)); + URL url = getClass().getClassLoader(). + getResource(src.substring(4)); + //getResource("at/freecom/apps/images/freecom.gif"); + //getResource("javax/swing/text/html/icons/image-delayed.gif"); + if (url == null) return null; + smileImage = Toolkit.getDefaultToolkit().getImage(url); + if (smileImage==null) return null; + //forcing image to load synchronously + ImageIcon ii = new ImageIcon(); + ii.setImage(smileImage); + //} + return smileImage; + } + public URL getImageURL() { + // here we return url to some image. It might be any + // existing image. we need to move ImageView to the + // state where it thinks that image was loaded. + // ImageView is calling getImage to get image for + // measurement and painting when image was loaded + if (false) { + return getClass().getClassLoader(). + getResource("javax/swing/text/html/icons/image-delayed.gif"); + } else { + String src = (String)elem.getAttributes(). + getAttribute(HTML.Attribute.SRC); + //System.out.println("img load: " + src.substring(4)); + URL url = getClass().getClassLoader(). + getResource(src.substring(4)); + if (url != null) { + System.out.println("load image: " + url); + return url; + } + } + return null; + } + private static Image smileImage = null; + } + + private ViewFactory oldFactory; + } + private static ViewFactory defaultFactory = null; +} \ No newline at end of file diff --git a/client/src/org/adempiere/apps/graph/GraphUtil.java b/client/src/org/adempiere/apps/graph/GraphUtil.java new file mode 100644 index 0000000000..edb05d60f9 --- /dev/null +++ b/client/src/org/adempiere/apps/graph/GraphUtil.java @@ -0,0 +1,168 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.adempiere.apps.graph; + +import java.awt.*; +import java.util.*; +import org.compiere.util.*; + +/** + * Graphic Utilities + * + * @author Jorg Janke + * @version $Id: GraphUtil.java,v 1.3 2006/07/30 00:51:28 jjanke Exp $ + */ +public class GraphUtil +{ + /** Logger */ + private static CLogger log = CLogger.getCLogger (GraphUtil.class); + + /** + * Get Foreground for back + * @param background back + * @return while or black + */ + public static Color getForeground (Color background) + { + if (background != null && isDark(background)) + return Color.white; + return Color.black; + } // getForeground + + /** + * Get Column Background + * @param index index + * @return random color + */ + public static Color getBackground (int index) + { + while (s_colors.size() <= index) + { + int rr = (index+1) * 47; + int gg = 100; + while (rr > 255) + { + rr -= 255; + gg += 50; + } + while (gg > 255) + gg -= 255; + s_colors.add(new Color(255-rr, gg, rr)); + } + return s_colors.get(index); + } // getBackGround + + /** List of Colors */ + private static ArrayList s_colors = new ArrayList(); + + + /** + * Is the Color dark? + * @param color color + * @return true if dark + */ + public static boolean isDark (Color color) + { + float r = color.getRed() / 255.0f; + float g = color.getGreen() / 255.0f; + float b = color.getBlue() / 255.0f; + double whiteDistance = colorDistance (r, g, b, 1.0, 1.0, 1.0); + double blackDistance = colorDistance (r, g, b, 0.0, 0.0, 0.0); + boolean dark = blackDistance < whiteDistance; + if (r+g+b == 1.0) + dark = false; + // log.info("r=" + r + ",g=" + g + ",b=" + b + " - black=" + blackDistance + // + (dark ? " ") + "white=" + whiteDistance + // + " - Alpha=" + color.getAlpha() + ", Trans=" + color.getTransparency()); + return dark; + } // isDark + + /** + * Is Color more white or black? + * @param r red + * @param g green + * @param b blue + * @return true if dark + */ + public static boolean isDark (double r, double g, double b) + { + double whiteDistance = colorDistance (r, g, b, 1.0, 1.0, 1.0); + double blackDistance = colorDistance (r, g, b, 0.0, 0.0, 0.0); + boolean dark = blackDistance < whiteDistance; + // log.finest("r=" + r + ",g=" + g + ",b=" + b + " - white=" + whiteDistance + ",black=" + blackDistance); + return dark; + } // isDark + + /** + * Simple Color Distance. + * (3d point distance) + * @param r1 first red + * @param g1 first green + * @param b1 first blue + * @param r2 second red + * @param g2 second green + * @param b2 second blue + * @return 3d distance for relative comparison + */ + public static double colorDistance (double r1, double g1, double b1, + double r2, double g2, double b2) + { + double a = (r2 - r1) + 0.1; + double b = (g2 - g1) + 0.1; + double c = (b2 - b1) + 0.1; + return Math.sqrt (a*a + b*b + c*c); + } // colorDistance + + + /** + * Get darker color + * @param color color + * @param factor factor 0..1 (AWT 0.7) the smaller, the darker + * @return darker color + */ + public static Color darker(Color color, double factor) + { + if (factor < 0.0) + factor = 0.7; + else if (factor > 1.0) + factor = 0.7; + return new Color( + Math.max((int)(color.getRed() * factor), 0), + Math.max((int)(color.getGreen() * factor), 0), + Math.max((int)(color.getBlue() * factor), 0)); + } // darker + + /** + * Get brighter color + * @param color color + * @param factor factor 0..1 (AWT 0.7) the smaller, the lighter + * @return brighter color + */ + public static Color brighter (Color color, double factor) + { + if (factor < 0.0) + factor = 0.7; + else if (factor > 1.0) + factor = 0.7; + + return new Color( + Math.min((int)(color.getRed() / factor), 255), + Math.min((int)(color.getGreen() / factor), 255), + Math.min((int)(color.getBlue() / factor), 255)); + } // brighter + +} // GraphUtil diff --git a/client/src/org/adempiere/apps/graph/HtmlDashboard.java b/client/src/org/adempiere/apps/graph/HtmlDashboard.java new file mode 100644 index 0000000000..3140ce0311 --- /dev/null +++ b/client/src/org/adempiere/apps/graph/HtmlDashboard.java @@ -0,0 +1,467 @@ +/** + * + */ +package org.adempiere.apps.graph; + +import javax.swing.JPanel; +import javax.swing.event.*; +import javax.swing.text.Document; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; + +import javax.swing.JEditorPane; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; + +import org.compiere.model.MAchievement; +import org.compiere.model.MGoal; +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.swing.CMenuItem; +import org.compiere.util.CLogger; +import org.compiere.util.DB; +import org.compiere.util.Env; +import org.compiere.util.Ini; +import org.compiere.util.Msg; + +import org.compiere.apps.AEnv; +import org.compiere.apps.AWindow; + +/** + * @author fcsku + * + */ +public class HtmlDashboard extends JPanel implements MouseListener, + ActionListener, HyperlinkListener { + + private static Dimension paneldimensionMin = new Dimension(80, 80); + private JEditorPane html; + private enum PAGE_TYPE {PAGE_HOME, PAGE_PERFORMANCE, PAGE_LOGO}; + private static CLogger log = CLogger.getCLogger (HtmlDashboard.class); + MGoal[] m_goals = null; + JPopupMenu popupMenu = new JPopupMenu(); + private CMenuItem mRefresh = new CMenuItem(Msg.getMsg(Env.getCtx(), "Refresh"), Env.getImageIcon("Refresh16.gif")); + URL lastUrl = null; + + + /** + * Constructor + */ + public HtmlDashboard(String url, MGoal[] m_goals, boolean scrolling) + { + super(); + //+param VTreePanel treePanel, + //this.treePanel = treePanel; + setName("test title"); + this.setLayout( new BorderLayout() ); + this.m_goals = m_goals; + // Create an HTML viewer + JEditorPane.registerEditorKitForContentType("text/html", "org.adempiere.apps.graph.FCHtmlEditorKit"); + html = new JEditorPane(); + html.setContentType("text/html"); + html.setEditable( false ); + htmlUpdate(url); + JScrollPane scrollPane = null; + if (scrolling) + scrollPane = new JScrollPane(); + else + scrollPane = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.getViewport().add( html, BorderLayout.CENTER ); + this.add( scrollPane, BorderLayout.CENTER ); + this.setMinimumSize(paneldimensionMin); + addMouseListener(this); + html.addHyperlinkListener( this ); + mRefresh.addActionListener(this); + popupMenu.add(mRefresh); + html.addMouseListener(this); + html.setBackground(getBackground()); + } + + public HtmlDashboard(String url) + { + new HtmlDashboard(url, null, true); + } + + private String createHTML(PAGE_TYPE requestPage){ + + String result = ""; + + // READ CSS + URL url = getClass().getClassLoader(). + getResource("org/compiere/images/PAPanel.css"); + InputStreamReader ins; + try { + ins = new InputStreamReader(url.openStream()); + BufferedReader bufferedReader = new BufferedReader( ins ); + String cssLine; + while ((cssLine = bufferedReader.readLine()) != null) + result += cssLine + "\n"; + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + //System.out.println(result); + switch (requestPage) { + case PAGE_LOGO: + result += "" + + "
" + + "" + + "" + //+ "" + + "
" + + ""; + break; + case PAGE_HOME: //************************************************************** + result += // "" + "
\n"; + queryZoom = null; + queryZoom = new ArrayList(); + String appendToHome = null; + String sql = " SELECT x.AD_CLIENT_ID, x.NAME, x.DESCRIPTION, x.AD_WINDOW_ID, x.PA_GOAL_ID, x.LINE, x.HTML, m.AD_MENU_ID" + + " FROM PA_DASHBOARDCONTENT x" + + " LEFT OUTER JOIN AD_MENU m ON x.ad_window_id=m.ad_window_id" + + " WHERE x.AD_Client_ID=0 OR x.AD_Client_ID=?" + + " ORDER BY LINE"; + try + { + PreparedStatement pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, Env.getAD_Client_ID(Env.getCtx())); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + appendToHome = rs.getString("HTML"); + if (appendToHome != null) { + if (rs.getString("DESCRIPTION") != null) + result += "

" + rs.getString("DESCRIPTION") + "

\n"; + result += stripHtml(appendToHome, false) + "
\n"; + } + + if (rs.getInt("AD_MENU_ID") > 0) { + result += "" + + rs.getString("DESCRIPTION") + + "
\n"); + } + result += "
\n"; + //result += "table id: " + rs.getInt("AD_TABLE_ID"); + if (rs.getInt("PA_GOAL_ID") > 0) + result += goalsDetail(rs.getInt("PA_GOAL_ID")); + //result += goalsDetail(rs.getInt("AD_TABLE_ID")); + } + rs.close(); + pstmt.close(); + } + catch (SQLException e) + { + System.out.println("dashboard: " + e); //TODO catch-block + } + result += "


\n" + + "
\n\n\n"; + break; + default: //************************************************************** + System.out.println("error"); + } + //System.out.println(result); + return result; + } + + + ArrayList queryZoom = null; //new ArrayList(); + + private String goalsDetail(int AD_Table_ID) { //TODO link to goals + String output = ""; + if (m_goals==null) return output; + for (int i = 0; i < m_goals.length; i++) { + MMeasureCalc mc = MMeasureCalc.get(Env.getCtx(), m_goals[i].getMeasure().getPA_MeasureCalc_ID()); + if (AD_Table_ID == m_goals[i].getPA_Goal_ID()){// mc.getAD_Table_ID()) { + output += "\n\n"; + output += "\n"; + output += "\n"; + //if (mc.getTableName()!=null) output += "table: " + mc.getAD_Table_ID() + "
\n"; + BarGraph barPanel = new BarGraph(m_goals[i]); + BarGraphColumn[] bList = barPanel.getBarGraphColumnList(); + MQuery query = null; + output += "\n"; + for (int k=0; k0) output += ""; + 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 + { + mc = bgc.getMeasureCalc(); + query = mc.getQuery(m_goals[i].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_goals[i].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_goals[i].getRestrictions(false), + bgc.getMeasureDisplay(), bgc.getDate(), bgc.getID(), + MRole.getDefault()); // logged in role + } + output += ""; + } + output += "" + + "" + + "
" + m_goals[i].getName() + "
Target" + m_goals[i].getMeasureTarget() + "
Actual" + m_goals[i].getMeasureActual() + "
" + m_goals[i].getXAxisText() + "
"+ bgc.getLabel() + ""; + if (query != null) { + output += "" + + bgc.getValue() + + "
\n"; + queryZoom.add(query); + } + else { + log.info("Nothing to zoom to - " + bgc); + output += bgc.getValue(); + } + output += "
" + + m_goals[i].getDescription() + + "
" + + stripHtml(m_goals[i].getColorSchema().getDescription(), true) + + "
\n"; + bList = null; + barPanel = null; + } + } + return output; + } + + private String stripHtml(String htmlString, boolean all) { + htmlString = htmlString + .replace("", "") + .replace("", "") + .replace("", "") + .replace("", "") + .replace("", "") + .replace("", ""); + + if (all) + htmlString = htmlString + .replace(">", ">") + .replace("<", "<"); + return htmlString; + } + private void htmlUpdate(String url) { + try { + htmlUpdate( new URL( url ) ); + } catch( MalformedURLException e ) { + System.out.println( "Malformed URL: " + e ); + } + } + + private void htmlUpdate(URL url) { + if ((url==null) || (url.getPath().equals("/local/home"))){ + html.setText(createHTML(PAGE_TYPE.PAGE_HOME)); + html.setCaretPosition(0); + lastUrl = url; + } + else if (url.getPath().equals("/local/logo")){ + html.setText(createHTML(PAGE_TYPE.PAGE_LOGO)); + html.setCaretPosition(0); + lastUrl = url; + } + else if (url.getPath().equals("/local/performance")){ + html.setText(createHTML(PAGE_TYPE.PAGE_PERFORMANCE)); + } + else if (url.getPath().equals("/window/node")){ + /* fcsku 3.7.07 + CButton button = new CButton(""); // Create the button + button.setActionCommand(String.valueOf(url.getRef())); //getNode_ID() + button.addActionListener(treePanel); //VTreePanel + //AEnv.zoom(130, 0); + html.setCursor(Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR )); + button.doClick(); + html.setCursor(Cursor.getPredefinedCursor( Cursor.DEFAULT_CURSOR )); + */ + int AD_Window_ID=Integer.parseInt(url.getRef()); + AWindow frame = new AWindow(); + if (!frame.initWindow(AD_Window_ID, null))//MQuery.getEqualQuery(TableName + "_ID", Record_ID))) + return; + AEnv.addToWindowManager(frame); + if (Ini.isPropertyBool(Ini.P_OPEN_WINDOW_MAXIMIZED)) + { + AEnv.showMaximized(frame); + } + else + { + AEnv.showCenterScreen(frame); + } + frame = null; + html.setCursor(Cursor.getPredefinedCursor( Cursor.DEFAULT_CURSOR )); + } + else if (url.getPath().equals("/window/zoom")){ + int index = Integer.parseInt(String.valueOf(url.getRef())); + if ((index >= 0) && (index < queryZoom.size())) { + html.setCursor(Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR )); + AEnv.zoom(queryZoom.get(index)); + html.setCursor(Cursor.getPredefinedCursor( Cursor.DEFAULT_CURSOR )); + } + } + else if (url != null){ + // Load some cursors + Cursor cursor = html.getCursor(); + html.setCursor( Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR ) ); + SwingUtilities.invokeLater( new PageLoader( html, url, cursor ) ); + lastUrl = url; + } + } + + + public void hyperlinkUpdate( HyperlinkEvent event ) + { + if( event.getEventType() == HyperlinkEvent.EventType.ACTIVATED ) + { + //System.out.println("parsed url: " + event.getURL());// +" from: " +event.getDescription()); + htmlUpdate(event.getURL()); + } + } + + /* (non-Javadoc) + * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent) + */ + public void mouseClicked(MouseEvent e) { + // TODO Auto-generated method stub + if (SwingUtilities.isRightMouseButton(e)) + popupMenu.show((Component)e.getSource(), e.getX(), e.getY()); + } + + /* (non-Javadoc) + * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent) + */ + public void mouseEntered(MouseEvent e) { + // TODO Auto-generated method stub + } + + /* (non-Javadoc) + * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent) + */ + public void mouseExited(MouseEvent e) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent) + */ + public void mousePressed(MouseEvent e) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent) + */ + public void mouseReleased(MouseEvent e) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + */ + public void actionPerformed(ActionEvent e) { + // TODO Auto-generated method stub + if (e.getSource() == mRefresh) + { + if (m_goals != null) + for (int i=0; i < m_goals.length; i++) + m_goals[i].updateGoal(true); + htmlUpdate(lastUrl); + Container parent = getParent(); + if (parent != null) + parent.invalidate(); + invalidate(); + if (parent != null) + parent.repaint(); + else + repaint(); + } + } + + class PageLoader implements Runnable + { + private JEditorPane html; + private URL url; + private Cursor cursor; + + PageLoader( JEditorPane html, URL url, Cursor cursor ) + { + this.html = html; + this.url = url; + this.cursor = cursor; + } + + public void run() + { + if( url == null ) + { + // restore the original cursor + html.setCursor( cursor ); + + // PENDING(prinz) remove this hack when + // automatic validation is activated. + Container parent = html.getParent(); + parent.repaint(); + } + else + { + Document doc = html.getDocument(); + try { + html.setPage( url ); + } + catch( IOException ioe ) + { + html.setDocument( doc ); + } + finally + { + // schedule the cursor to revert after + // the paint has happended. + url = null; + SwingUtilities.invokeLater( this ); + } + } + } + } +} diff --git a/client/src/org/adempiere/apps/graph/PAPanel.java b/client/src/org/adempiere/apps/graph/PAPanel.java new file mode 100644 index 0000000000..29cacf20e7 --- /dev/null +++ b/client/src/org/adempiere/apps/graph/PAPanel.java @@ -0,0 +1,175 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.adempiere.apps.graph; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.*; + +import javax.swing.*; + +import org.compiere.model.*; +import org.compiere.swing.*; +import org.compiere.util.*; + +/** + * Performance Analysis Panel. + * Key Performace Indicators + * + * @author Jorg Janke + * @version $Id: PAPanel.java,v 1.2 2006/07/30 00:51:28 jjanke Exp $ + */ +public class PAPanel extends CPanel implements ActionListener +{ + /** + * Get Panel if User has Perfpormance Goals + * @return panel pr null + */ + public static PAPanel 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 PAPanel(goals); + } // get + + + /************************************************************************** + * Constructor + * @param goals + */ + private PAPanel (MGoal[] goals) + { + super (); + m_goals = goals; + init(); + } // PAPanel + + /** Goals */ + private MGoal[] m_goals = null; + + /** Logger */ + private static CLogger log = CLogger.getCLogger (PAPanel.class); + + /** + * Static/Dynamic Init + */ + private void init() + { + /* BOXES: + * + * boxV Header + * ******** + * boxH + * + * boxH * * * + * * boxV1 * boxV2 * + * * * * + * + * boxV1 dial1 + * ******** + * dial2 + * + * boxV2 HTML + * ******** + * boxH1 + * + * boxH1 * * * + * * bar1 * bar2 * + * * * * + * + * + * V1 + HTML in scrollpane + */ + + this.setLayout(new BorderLayout()); + + // HEADER + Box boxV = Box.createVerticalBox(); + // DIALS/HTML+Bars + Box boxH = Box.createHorizontalBox(); + // DIALS + Box boxV1 = Box.createVerticalBox(); + // HTML/Bars + Box boxV2 = Box.createVerticalBox(); + // barChart + Box boxH1 = Box.createHorizontalBox(); + //boxH_V.setPreferredSize(new Dimension(180, 1500)); + //boxH1.setPreferredSize(new Dimension(400, 180)); + boxV2.setPreferredSize(new Dimension(120, 120)); + + // DIALS below HEADER, LEFT + for (int i = 0; i < m_goals.length; i++) + { + PerformanceIndicator pi = new PerformanceIndicator(m_goals[i]); + pi.addActionListener(this); + boxV1.add (pi, BorderLayout.NORTH); + } + boxV1.add(Box.createVerticalGlue(), BorderLayout.CENTER); + JScrollPane scrollPane = new JScrollPane(); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.getViewport().add(boxV1, BorderLayout.CENTER ); + scrollPane.setMinimumSize(new Dimension(190, 180)); + + // RIGHT, HTML + Bars + HtmlDashboard contentHtml = new HtmlDashboard("http:///local/home", m_goals, true); + boxV2.add(contentHtml, BorderLayout.CENTER); + + for (int i = 0; i < java.lang.Math.min(2, m_goals.length); i++) + { + if (m_goals[i].getMeasure() != null) //MGoal goal = pi.getGoal(); + boxH1.add ( new BarGraph(m_goals[i]), BorderLayout.SOUTH); + } + boxV2.add(boxH1, BorderLayout.SOUTH); + + // below HEADER + boxH.add(scrollPane, BorderLayout.WEST ); + boxH.add(Box.createHorizontalStrut(5)); //space + boxH.add(boxV2, BorderLayout.CENTER); + + // HEADER + below + HtmlDashboard t = new HtmlDashboard("http:///local/logo", null, false); + t.setMaximumSize(new Dimension(2000,80)); + //t.setPreferredSize(new Dimension(200,10)); + //t.setMaximumSize(new Dimension(2000,10)); + boxV.add(t, BorderLayout.NORTH); + boxV.add(Box.createVerticalStrut(5)); //space + boxV.add(boxH, BorderLayout.CENTER); + boxV.add(Box.createVerticalGlue()); + + // WINDOW + add(boxV, BorderLayout.CENTER); + } // init + + /** + * Action Listener for Drill Down + * @param e event + */ + public void actionPerformed (ActionEvent e) + { + if (e.getSource() instanceof PerformanceIndicator) + { + PerformanceIndicator pi = (PerformanceIndicator)e.getSource(); + log.info(pi.getName()); + MGoal goal = pi.getGoal(); + if (goal.getMeasure() != null) + new PerformanceDetail(goal); + } + } // actionPerformed + +} // PAPanel diff --git a/client/src/org/adempiere/apps/graph/PerformanceDetail.java b/client/src/org/adempiere/apps/graph/PerformanceDetail.java new file mode 100644 index 0000000000..da0e5e70b4 --- /dev/null +++ b/client/src/org/adempiere/apps/graph/PerformanceDetail.java @@ -0,0 +1,75 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.adempiere.apps.graph; + +import java.awt.*; +import java.awt.event.*; + +import org.compiere.*; +import org.compiere.apps.*; +import org.compiere.swing.*; +import org.compiere.model.*; + + +/** + * 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 PerformanceDetail extends CFrame + implements ActionListener +{ + /** + * Constructor. + * Called from PAPanel, ViewPI (Performance Indicator) + * @param goal goal + */ + public PerformanceDetail (MGoal goal) + { + super (goal.getName()); + setIconImage(Adempiere.getImage16()); + barPanel = new BarGraph(goal); + init(); + AEnv.showCenterScreen(this); + } // PerformanceDetail + + BarGraph barPanel = null; + ConfirmPanel confirmPanel = new ConfirmPanel(); + + /** + * Static init + */ + private void init() + { + getContentPane().add(barPanel, BorderLayout.CENTER); + getContentPane().add(confirmPanel, BorderLayout.SOUTH); + confirmPanel.addActionListener(this); + } // init + + /** + * Action Listener + * @param e event + */ + public void actionPerformed (ActionEvent e) + { + if (e.getActionCommand().equals(ConfirmPanel.A_OK)) + dispose(); + } // actionPerformed + +} // PerformanceDetail diff --git a/client/src/org/adempiere/apps/graph/PerformanceIndicator.java b/client/src/org/adempiere/apps/graph/PerformanceIndicator.java new file mode 100644 index 0000000000..76a321353a --- /dev/null +++ b/client/src/org/adempiere/apps/graph/PerformanceIndicator.java @@ -0,0 +1,358 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.adempiere.apps.graph; + +import java.awt.*; +import java.awt.event.*; +import java.awt.font.*; +import java.text.*; +import javax.swing.*; +import javax.swing.border.*; +import javax.swing.event.*; + +//vpj-cd e-evolution +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +//import java.awt.R`; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.*; +import org.jfree.data.general.*; +import org.jfree.data.Range; +import org.jfree.ui.RectangleInsets; +//vpj-cd e-evolution + +import org.compiere.model.*; +import org.compiere.swing.*; +import org.compiere.util.*; +import org.compiere.apps.graph.*; +import java.net.*; +import java.io.*; +import org.jfree.chart.ChartUtilities; + +/** + * Performance Indicator + * + * @author Jorg Janke + * @version $Id: PerformanceIndicator.java,v 1.2 2006/07/30 00:51:28 jjanke Exp $ + */ +//vpj-cd e-evolution public class PerformanceIndicator extends JComponent +public class PerformanceIndicator extends JPanel + implements MouseListener, ActionListener +{ + /** + * Constructor + * @param goal goal model + */ + public PerformanceIndicator(MGoal goal) + { + super(); + m_goal = goal; + setName(m_goal.getName()); + //vpj-cd e-evolution getPreferredSize(); // calculate size + init(); + // + setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); + setOpaque(true); + //vpj-cd e-evolution updateDisplay(); + + // + mRefresh.addActionListener(this); + popupMenu.add(mRefresh); + // + addMouseListener(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); + + JPopupMenu popupMenu = new JPopupMenu(); + private CMenuItem mRefresh = new CMenuItem(Msg.getMsg(Env.getCtx(), "Refresh"), Env.getImageIcon("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, 15), plot,false); + + return chart; + } + /** + * Init Graph Display + * Kinamo (pelgrim) + */ + private void init() { + chartPanel = new ChartPanel(createChart(), //chart + false, //boolean properties + false, // boolean save + false, //boolean print + false, //boolean zoom + true //boolean tooltips + ); + chartPanel.setPreferredSize(indicatordimension); + + chartPanel.addChartMouseListener( new org.jfree.chart.ChartMouseListener() + { + public void chartMouseClicked(org.jfree.chart.ChartMouseEvent e) + { + //plot p = (MeterPlot) e.getSource(); + MouseEvent me = e.getTrigger(); + if (SwingUtilities.isLeftMouseButton(me) && me.getClickCount() > 1) + fireActionPerformed(me); + if (SwingUtilities.isRightMouseButton(me)) + popupMenu.show((Component)me.getSource(), me.getX(), me.getY()); + } + public void chartMouseMoved(org.jfree.chart.ChartMouseEvent e) + { + + } + }); + + this.add(chartPanel, BorderLayout.NORTH); + this.setMinimumSize(paneldimension); + this.setMaximumSize(paneldimension); + //--------------------------------------------- + + 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 + + + +} // PerformanceIndicator diff --git a/client/src/org/compiere/apps/AMenu.java b/client/src/org/compiere/apps/AMenu.java index 86347d4f6e..ac31206c69 100644 --- a/client/src/org/compiere/apps/AMenu.java +++ b/client/src/org/compiere/apps/AMenu.java @@ -29,7 +29,7 @@ import javax.swing.event.*; // import org.compiere.*; import org.compiere.apps.wf.*; -import org.compiere.apps.graph.*; +import org.adempiere.apps.graph.*; import org.compiere.db.*; import org.compiere.grid.tree.*; import org.compiere.model.*; diff --git a/client/src/org/compiere/images/PAPanel.css b/client/src/org/compiere/images/PAPanel.css new file mode 100644 index 0000000000..39d31a11ed --- /dev/null +++ b/client/src/org/compiere/images/PAPanel.css @@ -0,0 +1,53 @@ + \ No newline at end of file diff --git a/client/src/org/compiere/images/logo_ad.png b/client/src/org/compiere/images/logo_ad.png new file mode 100644 index 0000000000000000000000000000000000000000..a79ccb61ef134cffe1b16e0ee477f2d40dc097d6 GIT binary patch literal 9060 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