All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cdc.perfs.ui.swing.ControlledChartPanel Maven / Gradle / Ivy

There is a newer version: 0.52.0
Show newest version
package cdc.perfs.ui.swing;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.Timer;

import cdc.perfs.core.Environment;
import cdc.perfs.core.EnvironmentKind;
import cdc.perfs.ui.PerfsChartHelper;
import cdc.perfs.ui.RefreshRate;
import cdc.perfs.ui.Rendering;
import cdc.ui.swing.GridBagConstraintsBuilder;
import cdc.util.lang.Checks;

/**
 * Panel dedicated to graphical display of measures and its controls.
 *
 * @author Damien Carbonne
 *
 */
public final class ControlledChartPanel extends JPanel {
    private static final long serialVersionUID = 1L;
    private static final double ZOOM_FACTOR = 1.1;
    final JButton wMoveToBegin = new JButton("|<");
    final JButton wLess = new JButton("<");
    final JButton wMore = new JButton(">");
    final JButton wMoveToEnd = new JButton(">|");
    private final JCheckBox wFocusLocked;
    final JSlider wScale = new JSlider();
    private final JScrollPane wScrollPane = new JScrollPane();
    final ChartPanel wChart;

    private enum TimeChangeMode {
        DEC,
        INC,
        NONE
    }

    TimeChangeMode timeChangeMode = TimeChangeMode.NONE;
    long timeChangeInit;

    private final transient ActionListener timeChangeHandler;

    final Timer timer;

    private final transient PerfsChartHelper.ChangeListener changeHandler = source -> refresh();

    public ControlledChartPanel(ContextsTableModel contextsModel,
                                SourcesTableModel sourcesModel) {
        super();

        final GridBagLayout gbl = new GridBagLayout();
        gbl.columnWeights = new double[] { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 };
        gbl.rowWeights = new double[] { 1.0, 0.0 };
        setLayout(gbl);

        // ScrollPane
        add(wScrollPane,
            GridBagConstraintsBuilder.builder()
                                     .fill(GridBagConstraints.BOTH)
                                     .gridwidth(6)
                                     .insets(0, 0, 5, 0)
                                     .gridx(0)
                                     .gridy(0)
                                     .build());

        // Chart
        wChart = new ChartPanel(this, contextsModel, sourcesModel);
        wScrollPane.setViewportView(wChart);
        wChart.addChangeListener(this.changeHandler);

        timeChangeHandler = e -> {
            final long nanos = System.nanoTime() - timeChangeInit;
            switch (timeChangeMode) {
            case DEC:
                wChart.decrementFocus(nanos);
                break;
            case INC:
                wChart.incrementFocus(nanos);
                break;
            default:
                break;
            }
        };
        this.timer = new Timer(10, this.timeChangeHandler);
        this.timer.setInitialDelay(0);

        // Move to begin
        wMoveToBegin.setEnabled(wChart.isFocusLocked());
        wMoveToBegin.addActionListener(event -> wChart.setFocusNanos(0.0));
        add(wMoveToBegin,
            GridBagConstraintsBuilder.builder()
                                     .insets(0, 5, 0, 5)
                                     .gridx(0)
                                     .gridy(1)
                                     .build());

        // Less
        wLess.setEnabled(wChart.isFocusLocked());
        wLess.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                less();
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                stop();
            }
        });

        add(wLess,
            GridBagConstraintsBuilder.builder()
                                     .insets(0, 0, 0, 5)
                                     .gridx(1)
                                     .gridy(1)
                                     .build());

        // Time lock
        wFocusLocked = new JCheckBox("lock");
        if (getEnvironment().getKind() == EnvironmentKind.SNAPSHOT) {
            wFocusLocked.setEnabled(false);
            wFocusLocked.setSelected(true);
            wChart.setFocusLocked(true);
            wMoveToBegin.setEnabled(wChart.isFocusLocked());
            wLess.setEnabled(wChart.isFocusLocked());
            wMore.setEnabled(wChart.isFocusLocked());
            wMoveToEnd.setEnabled(wChart.isFocusLocked());
        } else {
            wFocusLocked.addActionListener(event -> setFocusLocked(wFocusLocked.isSelected()));
        }
        add(wFocusLocked,
            GridBagConstraintsBuilder.builder()
                                     .anchor(GridBagConstraints.LINE_END)
                                     .insets(0, 0, 0, 5)
                                     .gridx(2)
                                     .gridy(1)
                                     .build());

        // Scale
        wScale.setMajorTickSpacing(PerfsChartHelper.SCALE_MAX / 5);
        wScale.setMinorTickSpacing(PerfsChartHelper.SCALE_MAX / 10);
        wScale.setPaintTicks(true);
        wScale.setMinimum(0);
        wScale.setMaximum(PerfsChartHelper.SCALE_MAX);
        wScale.setValue(PerfsChartHelper.SCALE_MAX / 2);
        final Dimension d = wScale.getPreferredSize();
        wScale.setPreferredSize(new Dimension(100, d.height));
        wScale.setMinimumSize(wScale.getPreferredSize());
        wScale.addChangeListener(event -> {
            final JSlider w = (JSlider) event.getSource();
            final double scale = PerfsChartHelper.sliderToScale(w.getValue());
            wChart.setScale(scale);
        });
        add(wScale,
            GridBagConstraintsBuilder.builder()
                                     .insets(0, 0, 0, 5)
                                     .gridx(3)
                                     .gridy(1)
                                     .build());

        // More
        wMore.setEnabled(wChart.isFocusLocked());
        wMore.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                more();
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                stop();
            }
        });
        add(wMore,
            GridBagConstraintsBuilder.builder()
                                     .gridx(4)
                                     .gridy(1)
                                     .build());

        // Move to end
        wMoveToEnd.setEnabled(wChart.isFocusLocked());
        wMoveToEnd.addActionListener(event -> wChart.setFocusNanos(wChart.getEnvironment().getElapsedNanos()));
        add(wMoveToEnd,
            GridBagConstraintsBuilder.builder()
                                     .insets(0, 0, 0, 5)
                                     .gridx(5)
                                     .gridy(1)
                                     .build());

        setScale(PerfsChartHelper.sliderToScale(wScale.getValue()));
        refresh();
    }

    public Environment getEnvironment() {
        return wChart.getEnvironment();
    }

    public void setRefreshRate(RefreshRate rate) {
        Checks.isNotNull(rate, "rate");
        wChart.setRefreshRate(rate);
    }

    public RefreshRate getRefreshRate() {
        return wChart.getRefreshRate();
    }

    public void setRendering(Rendering rendering) {
        Checks.isNotNull(rendering, "rendering");
        wChart.setRendering(rendering);
    }

    public Rendering getRendering() {
        return wChart.getRendering();
    }

    public void setDisplayStatsEnabled(boolean enabled) {
        wChart.setDisplayStatsEnabled(enabled);
    }

    public boolean getDisplayStatsEnabled() {
        return wChart.getDisplayStatsEnabled();
    }

    public void setDrawBordersEnabled(boolean enabled) {
        wChart.setDrawBordersEnabled(enabled);
    }

    public boolean getDrawBordersEnabled() {
        return wChart.getDrawBordersEnabled();
    }

    public void setScale(double scale) {
        wChart.setScale(scale);
    }

    public double getScale() {
        return wChart.getScale();
    }

    public void zoomIn() {
        setScale(getScale() / ZOOM_FACTOR);
    }

    public void zoomOut() {
        setScale(getScale() * ZOOM_FACTOR);
    }

    public void setFocusNanos(double time) {
        wChart.setFocusNanos(time);
    }

    public void setFocusLocked(boolean locked) {
        if (wFocusLocked.isSelected() != locked) {
            wFocusLocked.setSelected(locked);
        }
        wChart.setFocusLocked(locked);
        wMoveToBegin.setEnabled(locked);
        wLess.setEnabled(locked);
        wMore.setEnabled(locked);
        wMoveToEnd.setEnabled(locked);
    }

    public double getFocusNanos() {
        return wChart.getFocusNanos();
    }

    void refresh() {
        wScale.setValue((int) PerfsChartHelper.scaleToSlider(wChart.getScale()));
    }

    void more() {
        if (timeChangeMode != TimeChangeMode.INC) {
            timeChangeMode = TimeChangeMode.INC;
            timeChangeInit = System.nanoTime();
            if (!timer.isRunning()) {
                timer.start();
            }
        }
    }

    void less() {
        if (timeChangeMode != TimeChangeMode.DEC) {
            timeChangeMode = TimeChangeMode.DEC;
            timeChangeInit = System.nanoTime();
            if (!timer.isRunning()) {
                timer.start();
            }
        }
    }

    void stop() {
        if (timeChangeMode != TimeChangeMode.NONE) {
            timeChangeMode = TimeChangeMode.NONE;
            timer.stop();
        }
    }

    TimeChangeMode getTimeChangeMode() {
        return timeChangeMode;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy