1095 lines · 37.3 KB · Java
RawDownload
/* * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.tools.jconsole; import java.awt.*;import java.awt.event.*;import java.beans.*;import java.io.*;import java.lang.reflect.Array;import java.util.*; import javax.accessibility.*;import javax.swing.*;import javax.swing.border.*;import javax.swing.filechooser.*;import javax.swing.filechooser.FileFilter; import com.sun.tools.jconsole.JConsoleContext; import static com.sun.tools.jconsole.JConsoleContext.ConnectionState.*; import static sun.tools.jconsole.Formatter.*;import static sun.tools.jconsole.ProxyClient.*;import static sun.tools.jconsole.Resources.*;import static sun.tools.jconsole.Utilities.*; @SuppressWarnings("serial")public class Plotter extends JComponent                     implements Accessible, ActionListener, PropertyChangeListener {     public static enum Unit {        NONE, BYTES, PERCENT    }     static final String[] rangeNames = {        Resources.getText(" 1 min"),        Resources.getText(" 5 min"),        Resources.getText("10 min"),        Resources.getText("30 min"),        Resources.getText(" 1 hour"),        Resources.getText(" 2 hours"),        Resources.getText(" 3 hours"),        Resources.getText(" 6 hours"),        Resources.getText("12 hours"),        Resources.getText(" 1 day"),        Resources.getText(" 7 days"),        Resources.getText(" 1 month"),        Resources.getText(" 3 months"),        Resources.getText(" 6 months"),        Resources.getText(" 1 year"),        Resources.getText("All")    };     static final int[] rangeValues = {        1,        5,        10,        30,        1 * 60,        2 * 60,        3 * 60,        6 * 60,        12 * 60,        1 * 24 * 60,        7 * 24 * 60,        1 * 31 * 24 * 60,        3 * 31 * 24 * 60,        6 * 31 * 24 * 60,        366 * 24 * 60,        -1    };      final static long SECOND = 1000;    final static long MINUTE = 60 * SECOND;    final static long HOUR   = 60 * MINUTE;    final static long DAY    = 24 * HOUR;     final static Color bgColor = new Color(250, 250, 250);    final static Color defaultColor = Color.blue.darker();     final static int ARRAY_SIZE_INCREMENT = 4000;     private static Stroke dashedStroke;     private TimeStamps times = new TimeStamps();    private ArrayList<Sequence> seqs = new ArrayList<Sequence>();    private JPopupMenu popupMenu;    private JMenu timeRangeMenu;    private JRadioButtonMenuItem[] menuRBs;    private JMenuItem saveAsMI;    private JFileChooser saveFC;     private int viewRange = -1; // Minutes (value <= 0 means full range)    private Unit unit;    private int decimals;    private double decimalsMultiplier;    private Border border = null;    private Rectangle r = new Rectangle(1, 1, 1, 1);    private Font smallFont = null;     // Initial margins, may be recalculated as needed    private int topMargin = 10;    private int bottomMargin = 45;    private int leftMargin = 65;    private int rightMargin = 70;    private final boolean displayLegend;     public Plotter() {        this(Unit.NONE, 0);    }     public Plotter(Unit unit) {        this(unit, 0);    }     public Plotter(Unit unit, int decimals) {        this(unit,decimals,true);    }     // Note: If decimals > 0 then values must be decimally shifted left    // that many places, i.e. multiplied by Math.pow(10.0, decimals).    public Plotter(Unit unit, int decimals, boolean displayLegend) {        this.displayLegend = displayLegend;        setUnit(unit);        setDecimals(decimals);         enableEvents(AWTEvent.MOUSE_EVENT_MASK);         addMouseListener(new MouseAdapter() {            @Override            public void mousePressed(MouseEvent e) {                if (getParent() instanceof PlotterPanel) {                    getParent().requestFocusInWindow();                }            }        });     }     public void setUnit(Unit unit) {        this.unit = unit;    }     public void setDecimals(int decimals) {        this.decimals = decimals;        this.decimalsMultiplier = Math.pow(10.0, decimals);    }     public void createSequence(String key, String name, Color color, boolean isPlotted) {        Sequence seq = getSequence(key);        if (seq == null) {            seq = new Sequence(key);        }        seq.name = name;        seq.color = (color != null) ? color : defaultColor;        seq.isPlotted = isPlotted;         seqs.add(seq);    }     public void setUseDashedTransitions(String key, boolean b) {        Sequence seq = getSequence(key);        if (seq != null) {            seq.transitionStroke = b ? getDashedStroke() : null;        }    }     public void setIsPlotted(String key, boolean isPlotted) {        Sequence seq = getSequence(key);        if (seq != null) {            seq.isPlotted = isPlotted;        }    }     // Note: If decimals > 0 then values must be decimally shifted left    // that many places, i.e. multiplied by Math.pow(10.0, decimals).    public synchronized void addValues(long time, long... values) {        assert (values.length == seqs.size());        times.add(time);        for (int i = 0; i < values.length; i++) {            seqs.get(i).add(values[i]);        }        repaint();    }     private Sequence getSequence(String key) {        for (Sequence seq : seqs) {            if (seq.key.equals(key)) {                return seq;            }        }        return null;    }     /**     * @return the displayed time range in minutes, or -1 for all data     */    public int getViewRange() {        return viewRange;    }     /**     * @param minutes the displayed time range in minutes, or -1 to diaplay all data     */    public void setViewRange(int minutes) {        if (minutes != viewRange) {            int oldValue = viewRange;            viewRange = minutes;            /* Do not i18n this string */            firePropertyChange("viewRange", oldValue, viewRange);            if (popupMenu != null) {                for (int i = 0; i < menuRBs.length; i++) {                    if (rangeValues[i] == viewRange) {                        menuRBs[i].setSelected(true);                        break;                    }                }            }            repaint();        }    }     @Override    public JPopupMenu getComponentPopupMenu() {        if (popupMenu == null) {            popupMenu = new JPopupMenu(Resources.getText("Chart:"));            timeRangeMenu = new JMenu(Resources.getText("Plotter.timeRangeMenu"));            timeRangeMenu.setMnemonic(getMnemonicInt("Plotter.timeRangeMenu"));            popupMenu.add(timeRangeMenu);            menuRBs = new JRadioButtonMenuItem[rangeNames.length];            ButtonGroup rbGroup = new ButtonGroup();            for (int i = 0; i < rangeNames.length; i++) {                menuRBs[i] = new JRadioButtonMenuItem(rangeNames[i]);                rbGroup.add(menuRBs[i]);                menuRBs[i].addActionListener(this);                if (viewRange == rangeValues[i]) {                    menuRBs[i].setSelected(true);                }                timeRangeMenu.add(menuRBs[i]);            }             popupMenu.addSeparator();             saveAsMI = new JMenuItem(getText("Plotter.saveAsMenuItem"));            saveAsMI.setMnemonic(getMnemonicInt("Plotter.saveAsMenuItem"));            saveAsMI.addActionListener(this);            popupMenu.add(saveAsMI);        }        return popupMenu;    }     public void actionPerformed(ActionEvent ev) {        JComponent src = (JComponent)ev.getSource();        if (src == saveAsMI) {            saveAs();        } else {            int index = timeRangeMenu.getPopupMenu().getComponentIndex(src);            setViewRange(rangeValues[index]);        }    }     private void saveAs() {        if (saveFC == null) {            saveFC = new SaveDataFileChooser();        }        int ret = saveFC.showSaveDialog(this);        if (ret == JFileChooser.APPROVE_OPTION) {            saveDataToFile(saveFC.getSelectedFile());        }    }     private void saveDataToFile(File file) {        try {            PrintStream out = new PrintStream(new FileOutputStream(file));             // Print header line            out.print("Time");            for (Sequence seq : seqs) {                out.print(","+seq.name);            }            out.println();             // Print data lines            if (seqs.size() > 0 && seqs.get(0).size > 0) {                for (int i = 0; i < seqs.get(0).size; i++) {                    double excelTime = toExcelTime(times.time(i));                    out.print(String.format(Locale.ENGLISH, "%.6f", excelTime));                    for (Sequence seq : seqs) {                        out.print("," + getFormattedValue(seq.value(i), false));                    }                    out.println();                }            }             out.close();            JOptionPane.showMessageDialog(this,                                          getText("FileChooser.savedFile",                                                  file.getAbsolutePath(),                                                  file.length()));        } catch (IOException ex) {            String msg = ex.getLocalizedMessage();            String path = file.getAbsolutePath();            if (msg.startsWith(path)) {                msg = msg.substring(path.length()).trim();            }            JOptionPane.showMessageDialog(this,                                          getText("FileChooser.saveFailed.message",                                                  path, msg),                                          getText("FileChooser.saveFailed.title"),                                          JOptionPane.ERROR_MESSAGE);        }    }     @Override    public void paintComponent(Graphics g) {        super.paintComponent(g);         Color oldColor = g.getColor();        Font  oldFont  = g.getFont();        Color fg = getForeground();        Color bg = getBackground();        boolean bgIsLight = (bg.getRed() > 200 &&                             bg.getGreen() > 200 &&                             bg.getBlue() > 200);          ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,                                         RenderingHints.VALUE_ANTIALIAS_ON);         if (smallFont == null) {            smallFont = oldFont.deriveFont(9.0F);        }         r.x = leftMargin - 5;        r.y = topMargin  - 8;        r.width  = getWidth()-leftMargin-rightMargin;        r.height = getHeight()-topMargin-bottomMargin+16;         if (border == null) {            // By setting colors here, we avoid recalculating them            // over and over.            border = new BevelBorder(BevelBorder.LOWERED,                                     getBackground().brighter().brighter(),                                     getBackground().brighter(),                                     getBackground().darker().darker(),                                     getBackground().darker());        }         border.paintBorder(this, g, r.x, r.y, r.width, r.height);         // Fill background color        g.setColor(bgColor);        g.fillRect(r.x+2, r.y+2, r.width-4, r.height-4);        g.setColor(oldColor);         long tMin = Long.MAX_VALUE;        long tMax = Long.MIN_VALUE;        long vMin = Long.MAX_VALUE;        long vMax = 1;         int w = getWidth()-rightMargin-leftMargin-10;        int h = getHeight()-topMargin-bottomMargin;         if (times.size > 1) {            tMin = Math.min(tMin, times.time(0));            tMax = Math.max(tMax, times.time(times.size-1));        }        long viewRangeMS;        if (viewRange > 0) {            viewRangeMS = viewRange * MINUTE;        } else {            // Display full time range, but no less than a minute            viewRangeMS = Math.max(tMax - tMin, 1 * MINUTE);        }         // Calculate min/max values        for (Sequence seq : seqs) {            if (seq.size > 0) {                for (int i = 0; i < seq.size; i++) {                    if (seq.size == 1 || times.time(i) >= tMax - viewRangeMS) {                        long val = seq.value(i);                        if (val > Long.MIN_VALUE) {                            vMax = Math.max(vMax, val);                            vMin = Math.min(vMin, val);                        }                    }                }            } else {                vMin = 0L;            }            if (unit == Unit.BYTES || !seq.isPlotted) {                // We'll scale only to the first (main) value set.                // TODO: Use a separate property for this.                break;            }        }         // Normalize scale        vMax = normalizeMax(vMax);        if (vMin > 0) {            if (vMax / vMin > 4) {                vMin = 0;            } else {                vMin = normalizeMin(vMin);            }        }          g.setColor(fg);         // Axes        // Draw vertical axis        int x = leftMargin - 18;        int y = topMargin;        FontMetrics fm = g.getFontMetrics();         g.drawLine(x,   y,   x,   y+h);         int n = 5;        if ((""+vMax).startsWith("2")) {            n = 4;        } else if ((""+vMax).startsWith("3")) {            n = 6;        } else if ((""+vMax).startsWith("4")) {            n = 4;        } else if ((""+vMax).startsWith("6")) {            n = 6;        } else if ((""+vMax).startsWith("7")) {            n = 7;        } else if ((""+vMax).startsWith("8")) {            n = 8;        } else if ((""+vMax).startsWith("9")) {            n = 3;        }         // Ticks        ArrayList<Long> tickValues = new ArrayList<Long>();        tickValues.add(vMin);        for (int i = 0; i < n; i++) {            long v = i * vMax / n;            if (v > vMin) {                tickValues.add(v);            }        }        tickValues.add(vMax);        n = tickValues.size();         String[] tickStrings = new String[n];        for (int i = 0; i < n; i++) {            long v = tickValues.get(i);            tickStrings[i] = getSizeString(v, vMax);        }         // Trim trailing decimal zeroes.        if (decimals > 0) {            boolean trimLast = true;            boolean removedDecimalPoint = false;            do {                for (String str : tickStrings) {                    if (!(str.endsWith("0") || str.endsWith("."))) {                        trimLast = false;                        break;                    }                }                if (trimLast) {                    if (tickStrings[0].endsWith(".")) {                        removedDecimalPoint = true;                    }                    for (int i = 0; i < n; i++) {                        String str = tickStrings[i];                        tickStrings[i] = str.substring(0, str.length()-1);                    }                }            } while (trimLast && !removedDecimalPoint);        } 

Lines 1–500 of 1095.