CompositeChartPanel
package com.gossamer.voyant.client.ui.chart;
import com.gossamer.cobra.calculator.core.event.CalculationEvent;
import com.gossamer.cobra.calculator.core.event.PeriodEvent;
import com.gossamer.voyant.client.AppStyle;
import com.gossamer.voyant.client.dispatch.ClientCalculationListener;
import com.gossamer.voyant.client.dispatch.EventDispatcher;
import com.gossamer.voyant.client.dispatch.ClientPeriodListener;
import com.gossamer.voyant.client.ui.StageTimelinePanel;
import com.gossamer.voyant.client.ui.VoyantEventQueue;
import com.gossamer.voyant.client.ui.chartview.ChartConfig;
import com.gossamer.voyant.model.Plan;
import javax.swing.*;
import java.awt.*;
/**
* Contains a chart, a stages bar, and possibly an ages bar.<br>
*/
public class CompositeChartPanel
extends JPanel implements ChartConfig.ChartConfigListener {
public static final CompositeChartPanel upperCCP = new CompositeChartPanel(false);
public static final CompositeChartPanel lowerCCP = new CompositeChartPanel(true);
static {
new VoyantChartMouseListener(upperCCP.voyantChartPanel, lowerCCP.voyantChartPanel);
}
private VoyantChartPanel voyantChartPanel;
private ChartStageEditorPanel chartStageEditorPanel;
private VoyantChart voyantChart;
private VoyantCategoryPlot voyantCategoryPlot;
private boolean lowerPane;
private CCPListener ccpListener = new CCPListener();
private ChartConfig chartConfig;
private StageTimelinePanel stageTimelinePanel;
private ChartDomainLabel chartDomainLabel;
public static void reset() {
EventDispatcher.registerListener(upperCCP.ccpListener);
EventDispatcher.registerListener(lowerCCP.ccpListener);
EventDispatcher.registerListener(upperCCP.voyantCategoryPlot.getChartRefreshListener());
EventDispatcher.registerListener(lowerCCP.voyantCategoryPlot.getChartRefreshListener());
EventDispatcher.registerListener(upperCCP.voyantChartPanel);
EventDispatcher.registerListener(lowerCCP.voyantChartPanel);
EventDispatcher.registerListener(upperCCP.chartDomainLabel.getListener());
// There is no chartDomainLabel for the lowerpane
}
public CompositeChartPanel(boolean lowerPane) {
this.lowerPane = lowerPane;
chartConfig = lowerPane ? ChartConfig.LOWER_CHART_CONFIG : ChartConfig.UPPER_CHART_CONFIG;
// -------------------------------------------
setLayout(new BorderLayout());
chartConfig.registerLast(this);
createVoyantChart();
voyantChartPanel = new VoyantChartPanel(voyantChart, chartConfig, lowerPane);
if (!lowerPane) {
chartStageEditorPanel = new ChartStageEditorPanel();
JPanel chartContainer = new JPanel(new ChartLayout()) {
@Override
// to ensure componentZOrder is respected
public boolean isOptimizedDrawingEnabled() {
return false;
}
};
chartContainer.setOpaque(false);
chartContainer.setComponentZOrder(chartStageEditorPanel, 0);
chartContainer.setComponentZOrder(voyantChartPanel, 1);
add(BorderLayout.CENTER, chartContainer);
}
else {
add(BorderLayout.CENTER, voyantChartPanel);
}
add(lowerPane ? BorderLayout.NORTH : BorderLayout.SOUTH, createChartLabelPanel());
setOpaque(false);
}
public static VoyantChartPanel getVoyantChartPanel(boolean lowerPane) {
return lowerPane ? lowerCCP.voyantChartPanel : upperCCP.voyantChartPanel;
}
public void showChartStageEditorPanel() {
VoyantChartMouseListener.removeHoverAndInfoPanels();
chartStageEditorPanel.activate();
revalidate();
repaint();
}
public void hideChartStageEditorPanel() {
chartStageEditorPanel.deactivate();
revalidate();
repaint();
}
public void reveal() {
setVisible(true);
}
public void veil() {
setVisible(false);
if (this == upperCCP) {
hideChartStageEditorPanel();
}
}
public void chartConfigChange(ChartConfig newChartConfig) {
autoAdjustRangeAxis();
}
/**
* Redraws the chart.
*/
public void refreshChart() {
VoyantChart.refreshAll();
stageTimelinePanel.update();
if (chartDomainLabel != null) {
chartDomainLabel.repaint();
}
}
/**
* Used to maintain chart-scale consistency between calculations even when views are changed
* or dataseries are hidden
* @return the greatest value in the Y-axis scale of the chart
*/
public double getUpperBound() {
return voyantChart.getUpperBound();
}
/**
* "Blink" the setting for auto-adjusting the range axis to cause it to re-adjust and then remain fixed again.<br>
* Also refreshes chart
*/
public void autoAdjustRangeAxis() {
// Don't do this if the lower pane is showing percentages
if (ChartConfig.isShowingPercentLowerPane() && lowerPane) {
return;
}
voyantChart.autoResizeRangeAxis();
}
/**
* Set the range axis on the plot to the height parameter<br>
* Also refreshes chart
*/
public void setChartHeight(final double height) {
voyantChart.setChartHeight(height);
}
/**
* Tells the chart to turn on or off automatic range axis scaling.<br>
* Will not refresh the chart
* @param auto on or off
*/
private void setAutoAdjustRangeAxis(boolean auto) {
voyantChart.setAutoAdjustRangeAxis(auto);
}
private VoyantChart createVoyantChart() {
voyantCategoryPlot = new VoyantCategoryPlot(chartConfig, lowerPane);
voyantChart = new VoyantChart(voyantCategoryPlot, chartConfig);
voyantChart.setBorderVisible(false);
voyantChart.setBackgroundPaint(AppStyle.getInstance().chartRangeBackgroundColor);
return voyantChart;
}
private JPanel createChartLabelPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBackground(AppStyle.getInstance().chartDomainBackgroundColor);
stageTimelinePanel = new StageTimelinePanel(voyantChartPanel, lowerPane, chartConfig);
panel.add(BorderLayout.NORTH, stageTimelinePanel);
if (!lowerPane) {
chartDomainLabel = new ChartDomainLabel(voyantChartPanel);
panel.add(BorderLayout.SOUTH, chartDomainLabel);
}
return panel;
}
public static void refreshCharts() {
upperCCP.refreshChart();
lowerCCP.refreshChart();
}
protected class CCPListener
implements ClientCalculationListener, ClientPeriodListener {
public void calculationStarted(CalculationEvent e, Plan plan) {
// Do this NOW
try {
setAutoAdjustRangeAxis(true);
} catch (Exception e1) {}
}
public void calculationCompleted(CalculationEvent e, Plan plan) {
// Do this NOW
try {
setAutoAdjustRangeAxis(false);
} catch (Exception e1) {}
// Then do this later
VoyantEventQueue.invokeLater(new Runnable() {
public void run() {
refreshChart();
repaint();
}
});
}
public void periodStarted(PeriodEvent event, Plan plan) {
// no op
}
public void periodCompleted(PeriodEvent event, Plan plan) {
VoyantEventQueue.invokeLater(new Runnable() {
public void run() {
autoAdjustRangeAxis();
}
});
}
}
private class ChartLayout implements LayoutManager2 {
public void layoutContainer(Container parent) {
Dimension size = parent.getSize();
voyantChartPanel.setBounds(0, 0, size.width, size.height);
voyantChartPanel.setSize(size);
int leftSide = (int) VoyantCategoryPlot.getRangeAxisWidth();
chartStageEditorPanel.setBounds(leftSide, 0, size.width, size.height);
}
public float getLayoutAlignmentX(Container target) {
return 0;
}
public float getLayoutAlignmentY(Container target) {
return 0;
}
public Dimension maximumLayoutSize(Container target) {
return voyantChartPanel.getMaximumSize();
}
public Dimension preferredLayoutSize(Container parent) {
return voyantChartPanel.getPreferredSize();
}
public Dimension minimumLayoutSize(Container parent) {
return voyantChartPanel.getMinimumSize();
}
// --------------------------------------------
public void addLayoutComponent(Component comp, Object constraints) {}
public void invalidateLayout(Container target) {}
public void addLayoutComponent(String name, Component comp) {}
public void removeLayoutComponent(Component comp) {}
}
}