package org.geogebra.desktop.gui.view.data;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.ListCellRenderer;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
import org.geogebra.common.gui.view.data.DataAnalysisModel;
import org.geogebra.common.gui.view.data.StatisticsModel;
import org.geogebra.common.gui.view.data.StatisticsModel.IStatisticsModelListener;
import org.geogebra.desktop.main.AppD;
/**
*
* Extended JPanel that displays: (1) summary statistics for the current data
* set (2) interactive panels for performing statistical inference with the
* current data set
*
* @author G. Sturr
*
*/
public class StatisticsPanel extends JPanel implements StatPanelInterface,
ActionListener, IStatisticsModelListener {
private static final long serialVersionUID = 1L;
private StatisticsModel model;
// inference mode selection
private JComboBox cbInferenceMode;
// panels
private BasicStatTable statTable;
private OneVarInferencePanelD oneVarInferencePanel;
private TwoVarInferencePanel twoVarInferencePanel;
private ANOVATable anovaTable;
private MultiVarStatPanel minMVStatPanel;
private JPanel selectionPanel;
private JPanel inferencePanel;
// ggb fields
private DataAnalysisViewD statDialog;
private AppD app;
private DataAnalysisModel daModel;
/*************************************
* Constructor
*
* @param app
* @param statDialog
*/
public StatisticsPanel(AppD app, DataAnalysisViewD statDialog) {
this.app = app;
this.statDialog = statDialog;
this.daModel = statDialog.getModel();
model = new StatisticsModel(app, daModel, this);
// create the sub-panels
createSelectionPanel();
createStatTable();
if (statTable != null) {
statTable.setBorder(BorderFactory.createEmptyBorder());
inferencePanel = new JPanel(new BorderLayout());
inferencePanel.add(statTable, BorderLayout.CENTER);
// add sub-panels to layout
setLayout(new BorderLayout());
add(selectionPanel, BorderLayout.NORTH);
add(inferencePanel, BorderLayout.CENTER);
setLabels();
}
}
/**
* Creates a table to display summary statistics for the current data set(s)
*/
private void createStatTable() {
// create a statTable according to dialog type
if (daModel.getMode() == DataAnalysisModel.MODE_ONEVAR) {
statTable = new BasicStatTable(app, statDialog);
} else if (daModel.getMode() == DataAnalysisModel.MODE_REGRESSION) {
statTable = new BasicStatTable(app, statDialog);
} else if (daModel.getMode() == DataAnalysisModel.MODE_MULTIVAR) {
statTable = new MultiVarStatPanel(app, statDialog);
}
}
/**
* Reconfigures the panel layout according to the current selected inference
* mode
*/
private void setInferencePanel() {
if (inferencePanel == null) {
return;
}
inferencePanel.removeAll();
switch (model.getSelectedMode()) {
case StatisticsModel.INFER_ZTEST:
case StatisticsModel.INFER_TTEST:
case StatisticsModel.INFER_ZINT:
case StatisticsModel.INFER_TINT:
inferencePanel.add(getOneVarInferencePanel(), BorderLayout.NORTH);
break;
case StatisticsModel.INFER_TTEST_2MEANS:
case StatisticsModel.INFER_TINT_2MEANS:
inferencePanel.add(getTwoVarInferencePanel(true),
BorderLayout.NORTH);
break;
case StatisticsModel.INFER_TTEST_PAIRED:
case StatisticsModel.INFER_TINT_PAIRED:
inferencePanel.add(getTwoVarInferencePanel(false),
BorderLayout.NORTH);
break;
case StatisticsModel.INFER_ANOVA:
GridBagConstraints tab = new GridBagConstraints();
tab.gridx = 0;
tab.gridy = GridBagConstraints.RELATIVE;
tab.weightx = 1;
tab.insets = new Insets(4, 20, 0, 20);
tab.fill = GridBagConstraints.HORIZONTAL;
tab.anchor = GridBagConstraints.NORTHWEST;
JPanel p = new JPanel(new GridBagLayout());
p.add(getAnovaTable(), tab);
p.add(getMinMVStatPanel(), tab);
inferencePanel.add(p, BorderLayout.CENTER);
break;
default:
inferencePanel.add(statTable, BorderLayout.CENTER);
}
revalidate();
repaint();
this.setMinimumSize(this.getPreferredSize());
statDialog.updateStatDataPanelVisibility();
}
private void createSelectionPanel() {
createInferenceTypeComboBox();
selectionPanel = new JPanel(new BorderLayout());
selectionPanel.add(cbInferenceMode, app.getLocalization().borderWest());
}
private ANOVATable getAnovaTable() {
if (anovaTable == null) {
anovaTable = new ANOVATable(app, statDialog);
}
return anovaTable;
}
private OneVarInferencePanelD getOneVarInferencePanel() {
if (oneVarInferencePanel == null) {
oneVarInferencePanel = new OneVarInferencePanelD(app, statDialog);
}
return oneVarInferencePanel;
}
private TwoVarInferencePanel getTwoVarInferencePanel() {
if (twoVarInferencePanel == null) {
twoVarInferencePanel = new TwoVarInferencePanel(app, statDialog);
}
return twoVarInferencePanel;
}
private TwoVarInferencePanel getTwoVarInferencePanel(boolean enablePooled) {
TwoVarInferencePanel p = getTwoVarInferencePanel();
p.setEnablePooled(enablePooled);
return p;
}
private MultiVarStatPanel getMinMVStatPanel() {
if (minMVStatPanel == null) {
minMVStatPanel = new MultiVarStatPanel(app, statDialog);
}
minMVStatPanel.setMinimalTable(true);
return minMVStatPanel;
}
/**
* Creates the JComboBox that selects inference mode
*/
private void createInferenceTypeComboBox() {
if (cbInferenceMode == null) {
cbInferenceMode = new JComboBox();
cbInferenceMode.setFocusable(false);
cbInferenceMode.setRenderer(new MyRenderer());
} else {
cbInferenceMode.removeActionListener(this);
cbInferenceMode.removeAllItems();
}
model.fillInferenceModes();
cbInferenceMode.addActionListener(this);
cbInferenceMode.setMaximumRowCount(cbInferenceMode.getItemCount());
cbInferenceMode.addActionListener(this);
}
@Override
public void updateFonts(Font font) {
if (statTable != null) {
statTable.updateFonts(font);
}
}
@Override
public void setLabels() {
statTable.setLabels();
}
@Override
public void updatePanel() {
// System.out.println("============= update stat panel");
if (statTable == null) {
return;
}
statTable.updatePanel();
model.update();
revalidate();
repaint();
this.setMinimumSize(this.getPreferredSize());
// statDialog.updateStatDataPanelVisibility();
}
@Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == cbInferenceMode
&& cbInferenceMode.getSelectedItem() != null) {
model.selectInferenceMode(
cbInferenceMode.getSelectedItem().toString());
setInferencePanel();
updatePanel();
}
}
// ============================================================
// ComboBox Renderer with SEPARATOR
// ============================================================
private static class MyRenderer extends JLabel implements ListCellRenderer {
private static final long serialVersionUID = 1L;
public static final String SEPARATOR = "SEPARATOR";
JSeparator separator;
public MyRenderer() {
setOpaque(true);
setBorder(new EmptyBorder(1, 1, 1, 1));
separator = new JSeparator(SwingConstants.HORIZONTAL);
}
@Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
String str = (value == null) ? "" : value.toString();
if (SEPARATOR.equals(str)) {
return separator;
}
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
setFont(list.getFont());
setText(str);
return this;
}
}
@Override
public void addInferenceMode(String item) {
cbInferenceMode.addItem(item);
}
@Override
public void selectInferenceMode(String item) {
cbInferenceMode.setSelectedItem(item);
}
@Override
public String getSeparator() {
return MyRenderer.SEPARATOR;
}
@Override
public void updateOneVarInference(int mode) {
getOneVarInferencePanel().setSelectedPlot(mode);
getOneVarInferencePanel().updatePanel();
}
@Override
public void updateTwoVarInference(int mode) {
getTwoVarInferencePanel().setSelectedInference(mode);
getTwoVarInferencePanel().updatePanel();
}
@Override
public void updateAnovaTable() {
getAnovaTable().updatePanel();
getMinMVStatPanel().updatePanel();
}
}