⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 graphpanel.java

📁 一个用于排队系统仿真的开源软件,有非常形象的图象仿真过程!
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/**
 * Copyright (C) 2006, Laboratorio di Valutazione delle Prestazioni - Politecnico di Milano

 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.

 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
package jmt.gui.exact.panels;

import jmt.gui.wizard.WizardPanel;
import jmt.gui.exact.ExactModel;
import jmt.gui.exact.ExactConstants;
import jmt.gui.exact.utils.WhatIfPlot;
import jmt.gui.exact.utils.ArrayUtils;
import jmt.gui.common.editors.ColorCellEditor;
import jmt.gui.common.editors.ComboBoxCellEditor;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import java.awt.*;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
import java.util.Arrays;

/**
 * <p>Title: Graph Panel</p>
 * <p>Description: This panelis used to display JMVA what-if analysis
 * results in a graph. Number of allowed lines in graph is determined
 * by <code>graph.getColors().length</code>. Modify it to allow more lines.</p>
 *
 * @author Bertoli Marco
 *         Date: 1-giu-2006
 *         Time: 11.01.29
 */
public class GraphPanel extends WizardPanel implements ExactConstants {
    // Data structure
    private ExactModel model;
    // Plot
    private WhatIfPlot graph;
    // Performance index selector
    private JComboBox index;
    // Bounds for graph
    private JSpinner Xmin, Xmax, Ymin, Ymax;
    // Tells if spinner update is forced. This is needed to avoid that updates made by
    // code will be interpreted as updated made by user.
    private boolean forcedUpdate = false;
    // Table used to select performance indices to be plotted
    private LinesTable table;
    // Scrollpane used for table
    private JScrollPane tableScrollPane;
    // Dimension of bounds spinners
    final static Dimension DIM_SPINNER = new Dimension(60,20);
    // Current performance index
    private String currentIndex = "none";
    // Selected performance indices
    private int[] classes;
    private int[] stations;
    // Aggregate special value
    private static final String AGGREGATE = "<html><b><i>Aggregate</i></b></html>";

    /**
     * Builds a new GraphPanel, given an exact model data structure
     * @param model reference to data structure
     */
    public GraphPanel(ExactModel model) {
        this.model = model;
        initGraphics();
    }



    /**
     * Initialize GUI of this panel
     */
    private void initGraphics() {
        setLayout(new BorderLayout(10,10));
        setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
        JPanel mainPanel = new JPanel(new BorderLayout(5,5));
        mainPanel.setBorder(BorderFactory.createEtchedBorder());

        // Adds description label
        JLabel descrLabel = new JLabel(DESCRIPTION_GRAPH);
        add(descrLabel, BorderLayout.NORTH);
        add(mainPanel, BorderLayout.CENTER);

        // Creates left panel with options
        JPanel left = new JPanel(new BorderLayout(3,3));
        // Adds performance index selection
        JPanel indexPanel = new JPanel();
        JLabel pIndex = new JLabel("Performance index: ");
        index = new JComboBox(ExactModel.INDICES_TYPES);
        // Adds aggregate types
        for (int i=0; i<AGGREGATE_TYPES.length; i++)
            index.addItem(AGGREGATE_TYPES[i]);
        pIndex.setLabelFor(index);
        indexPanel.add(pIndex);
        indexPanel.add(index);
        left.add(indexPanel, BorderLayout.NORTH);

        // Adds panel for bounds selection
        JPanel boundsPanel = new JPanel(new GridLayout(2, 4,1,1));
        boundsPanel.add(new JLabel("Xmin: ", JLabel.RIGHT));
        Xmin = new JSpinner(new SpinnerNumberModel(0.0, 0.0, 1e10, 0.01));
        Xmin.setPreferredSize(DIM_SPINNER);
        boundsPanel.add(Xmin);
        boundsPanel.add(new JLabel("Xmax: ", JLabel.RIGHT));
        Xmax = new JSpinner(new SpinnerNumberModel(0.0, 0.0, 1e10, 0.01));
        Xmax.setPreferredSize(DIM_SPINNER);
        boundsPanel.add(Xmax);
        boundsPanel.add(new JLabel("Ymin: ", JLabel.RIGHT));
        Ymin = new JSpinner(new SpinnerNumberModel(0.0, 0.0, 1e10, 0.01));
        Ymin.setPreferredSize(DIM_SPINNER);
        boundsPanel.add(Ymin);
        boundsPanel.add(new JLabel("Ymax: ", JLabel.RIGHT));
        Ymax = new JSpinner(new SpinnerNumberModel(0.0, 0.0, 1e10, 0.01));
        Ymax.setPreferredSize(DIM_SPINNER);
        boundsPanel.add(Ymax);
        left.add(boundsPanel, BorderLayout.SOUTH);

        mainPanel.add(left, BorderLayout.WEST);

        // Puts graph in the right panel
        // Creates label for X-axis
        String xLabel= "";
        if (model.getWhatIfClass() >= 0) {
            graph = new WhatIfPlot(model.getWhatIfValues());
            if (model.getWhatIfType().equals(ExactModel.WHAT_IF_ARRIVAL))
                xLabel = "Arrival rate \u03bbi for "+ model.getClassNames()[model.getWhatIfClass()] + " [job/s]";
            else if (model.getWhatIfType().equals(ExactModel.WHAT_IF_CUSTOMERS))
                xLabel = "Number of customers Ni for " + model.getClassNames()[model.getWhatIfClass()];
            else if (model.getWhatIfType().equals(ExactModel.WHAT_IF_DEMANDS))
                xLabel = "Service demand Di for "+
                        model.getClassNames()[model.getWhatIfClass()]+
                        " at "+ model.getStationNames()[model.getWhatIfStation()]+" [s]";
            else if (model.getWhatIfType().equals(ExactModel.WHAT_IF_MIX))
                xLabel = "Population mix \u03b2i for "+model.getClassNames()[model.getWhatIfClass()];
        }
        else {
            graph = new WhatIfPlot(ArrayUtils.multiply(model.getWhatIfValues(), 100.0));
            if (model.getWhatIfType().equals(ExactModel.WHAT_IF_ARRIVAL))
                xLabel = "% of arrival rates \u03bbi w.r.t. initial values";
            else if (model.getWhatIfType().equals(ExactModel.WHAT_IF_CUSTOMERS))
                xLabel = "% of customers Ni w.r.t. initial values";
            else if (model.getWhatIfType().equals(ExactModel.WHAT_IF_DEMANDS))
                xLabel = "% of Service demands Di at "
                        +model.getStationNames()[model.getWhatIfStation()]+
                        " w.r.t. initial values";
        }
        graph.setXLabel(xLabel);
        mainPanel.add(graph, BorderLayout.CENTER);

        // Adds table and inits data structure for it.
        classes = new int[graph.getColors().length];
        if (model.isMultiClass()) // If model is single-class, select first class by default
            Arrays.fill(classes, -10);
        stations = new int[graph.getColors().length];
        Arrays.fill(stations, -10);
        table = new LinesTable();
        tableScrollPane = new JScrollPane(table);
        tableScrollPane.setPreferredSize(new Dimension(160, tableScrollPane.getPreferredSize().height));
        left.add(tableScrollPane, BorderLayout.CENTER);

        updateSpinners();
        addActions();
        updateIndex();
    }

    /**
     * Updates values in spinners used to select ranges to be shown in graph
     */
    private void updateSpinners() {
        // Check for special value used if graph is empty
        if (graph.getXRange()[0] != Double.MAX_VALUE) {
            Xmin.setValue(new Double(graph.getXRange()[0]));
            Xmax.setValue(new Double(graph.getXRange()[1]));
            Ymin.setValue(new Double(graph.getYRange()[0]));
            Ymax.setValue(new Double(graph.getYRange()[1]));
        }
        else {
            Xmin.setValue(new Double(0.0));
            Xmax.setValue(new Double(0.0));
            Ymin.setValue(new Double(0.0));
            Ymax.setValue(new Double(0.0));
        }
    }

    /**
     * Used when a spinne value is updated
     */
    private void setBounds() {
        double xmin, xmax, ymin, ymax;
        Object val = Xmin.getValue();
        if (val instanceof Number)
            xmin = ((Number)val).doubleValue();
        else
            xmin = graph.getXRange()[0];
        val = Xmax.getValue();
        if (val instanceof Number)
            xmax = ((Number)val).doubleValue();
        else
            xmax = graph.getXRange()[1];
        val = Ymin.getValue();
        if (val instanceof Number)
            ymin = ((Number)val).doubleValue();
        else
            ymin = graph.getYRange()[0];
        val = Ymax.getValue();
        if (val instanceof Number)
            ymax = ((Number)val).doubleValue();
        else
            ymax = graph.getYRange()[1];
        // Sets bounds
        graph.setXRange(xmin, xmax);
        graph.setYRange(ymin, ymax);
        graph.repaint();
    }

    /**
     * This function must be called each time selected performance
     * index changes
     */
    private void updateIndex() {
        String current = (String)index.getSelectedItem();
        if (!current.equals(currentIndex)) {
            currentIndex = current;
            // System Response time
            if (currentIndex.equals(AGGREGATE_TYPES[0])) {
                tableScrollPane.setVisible(false);
                graph.clear(false);
                graph.draw(0, model.getGlobalR());
                graph.fillPlot();
            }
            // System throughput
            else if (currentIndex.equals(AGGREGATE_TYPES[1])) {
                tableScrollPane.setVisible(false);
                graph.clear(false);
                graph.draw(0, model.getGlobalX());
                graph.fillPlot();
            }
            // Number of customers
            else if (currentIndex.equals(AGGREGATE_TYPES[2])) {
                tableScrollPane.setVisible(false);
                graph.clear(false);
                graph.draw(0, model.getGlobalQ());
                graph.fillPlot();
            }
            // otherwise
            else {
                tableScrollPane.setVisible(true);
                // Removes incorrect utilization measures
                if (table.getCellEditor() != null)
                    table.getCellEditor().stopCellEditing();
                if (currentIndex.equals(ExactModel.INDICES_TYPES[3])) {
                    for (int i=0; i<stations.length; i++)
                        if (stations[i] == -1)
                            stations[i] = -2;
                }
                table.repaint();
                paintAllIndices();
            }
            // Updates graph
            graph.setYLabel(current);
            graph.repaint();
        }
    }


    /**
     * Adds action listeners to GUI components
     */
    private void addActions() {
        // Listener used for bounds spinners
        ChangeListener boundsListener = new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                if (!forcedUpdate) {
                    setBounds();
                    updateSpinners();
                }
            }
        };
        Xmin.addChangeListener(boundsListener);
        Xmax.addChangeListener(boundsListener);
        Ymin.addChangeListener(boundsListener);
        Ymax.addChangeListener(boundsListener);
        // Listener for index selection comboBox
        index.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                updateIndex();
            }
        });

        // Adds a listener to the graph to detect zoom events
        graph.addRescaleListener(new WhatIfPlot.RescaleListener() {
            public void Rescaled() {
                forcedUpdate = true;
                updateSpinners();
                forcedUpdate = false;
            }
        });
    }

    /**
     * Paints performance index at specified row
     * @param rowNum row number of index to be painted
     */
    private void paintIndexAtRow(int rowNum) {
        // Clears previous graph
        graph.clear(rowNum);
        int classNum = classes[rowNum];
        int statNum = stations[rowNum];

        if (classNum < -1 || statNum < -1) {
            // Resets view
            autosizeGraph();
            return;
        }

        // Throughput
        if (currentIndex.equals(ExactModel.INDICES_TYPES[0])) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -