package org.geogebra.desktop.gui.view.probcalculator; 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 java.awt.event.FocusEvent; import java.awt.event.FocusListener; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JEditorPane; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.StyleSheet; import org.geogebra.common.gui.SetLabels; import org.geogebra.common.gui.view.probcalculator.StatisticsCalculator; import org.geogebra.common.util.TextObject; import org.geogebra.desktop.gui.inputfield.MyTextFieldD; import org.geogebra.desktop.gui.util.LayoutUtil; import org.geogebra.desktop.gui.util.ListSeparatorRenderer; import org.geogebra.desktop.main.AppD; /** * @author G. Sturr * */ public class StatisticsCalculatorD extends StatisticsCalculator implements ActionListener, FocusListener, SetLabels { // ========================================= // support classes // ========================================= // ========================================= // GUI components // ========================================= // labels private JLabel[] lblSampleStat1, lblSampleStat2; private JLabel lblResult, lblHypParameter, lblTailType, lblNull, lblConfLevel, lblSigma, lblSampleHeader1, lblSampleHeader2; // buttons and combo boxes private JRadioButton btnLeft, btnRight, btnTwo; private JButton btnCalculate; private JComboBox cbProcedure; private JCheckBox ckPooled; // panels private JPanel panelBasicProcedures, panelControl, panelSample1, panelSample2, panelTestAndCI; private ChiSquarePanelD panelChiSquare; private JEditorPane resultPane; private JScrollPane scroller; private JPanel wrappedPanel; /****************************************************************** * * Construct StatisticsCalculator * * @param app */ public StatisticsCalculatorD(AppD app) { super(app); createGUI(); } // ========================================= // GUI // ========================================= private void createGUI() { this.wrappedPanel = new JPanel(); createGUIElements(); createControlPanel(); setInputPanelLayout(); panelChiSquare = new ChiSquarePanelD(loc, this); // prepare result panel resultPane.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createEtchedBorder(), BorderFactory.createEmptyBorder(10, 10, 10, 10))); JPanel resultPanel = new JPanel(new BorderLayout()); resultPanel.add(lblResult, BorderLayout.NORTH); resultPanel.add(resultPane, BorderLayout.CENTER); // procedure panel (procedure input fields + result panel) JPanel procedurePanel = new JPanel(); procedurePanel .setLayout(new BoxLayout(procedurePanel, BoxLayout.Y_AXIS)); procedurePanel.add(panelBasicProcedures); procedurePanel.add(panelChiSquare.getWrappedPanel()); procedurePanel.add(Box.createVerticalStrut(20)); procedurePanel.add(resultPanel); procedurePanel.setAlignmentY(Component.TOP_ALIGNMENT); // wrapper for procedure panel JPanel procedureWrapper = new JPanel(new BorderLayout()); procedureWrapper.add(procedurePanel, BorderLayout.NORTH); procedureWrapper .setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20)); scroller = new JScrollPane(procedureWrapper); scroller.getVerticalScrollBar().setUnitIncrement(30); // main content panel JPanel main = new JPanel(new BorderLayout()); main.add(scroller, BorderLayout.CENTER); main.add(panelControl, BorderLayout.NORTH); wrappedPanel.setLayout(new BorderLayout()); wrappedPanel.add(main, BorderLayout.CENTER); setLabels(); updateGUI(); } private void createControlPanel() { panelControl = new JPanel(new BorderLayout()); panelControl.add(LayoutUtil.flowPanel(cbProcedure), loc.borderWest()); // panelControl.add(LayoutUtil.flowPanel(btnCalculate), // BorderLayout.CENTER); panelControl.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); } private void setInputPanelLayout() { // ---- prepare panels if (panelBasicProcedures == null) { panelBasicProcedures = new JPanel(); panelBasicProcedures.setLayout(new GridBagLayout()); panelBasicProcedures.setAlignmentY(Component.TOP_ALIGNMENT); } if (panelSample1 == null) { panelSample1 = new JPanel(); panelSample1 .setLayout(new BoxLayout(panelSample1, BoxLayout.Y_AXIS)); panelSample1.setAlignmentY(Component.TOP_ALIGNMENT); } if (panelSample2 == null) { panelSample2 = new JPanel(); panelSample2 .setLayout(new BoxLayout(panelSample2, BoxLayout.Y_AXIS)); panelSample2.setAlignmentY(Component.TOP_ALIGNMENT); } if (panelTestAndCI == null) { panelTestAndCI = new JPanel(); panelTestAndCI .setLayout(new BoxLayout(panelTestAndCI, BoxLayout.Y_AXIS)); panelTestAndCI.setAlignmentY(Component.TOP_ALIGNMENT); } panelBasicProcedures.removeAll(); panelSample1.removeAll(); panelSample2.removeAll(); panelTestAndCI.removeAll(); // ---- add components panelSample1.add(LayoutUtil.flowPanelRight(4, 2, 0, lblSampleHeader1)); for (int i = 0; i < lblSampleStat1.length; i++) { panelSample1.add(LayoutUtil.flowPanelRight(4, 2, 0, lblSampleStat1[i], (MyTextFieldD) fldSampleStat1[i])); } panelSample2.add(LayoutUtil.flowPanelRight(4, 2, 0, new JLabel(" "), lblSampleHeader2)); for (int i = 0; i < lblSampleStat2.length; i++) { panelSample2.add(LayoutUtil.flowPanelRight(4, 2, 0, lblSampleStat2[i], (MyTextFieldD) fldSampleStat2[i])); } switch (selectedProcedure) { default: // do nothing break; case ZMEAN_TEST: case ZMEAN2_TEST: case TMEAN_TEST: case TMEAN2_TEST: case ZPROP_TEST: case ZPROP2_TEST: if (app.getLocalization().isRightToLeftReadingOrder()) { // eg 1.1 = mu panelTestAndCI.add(LayoutUtil.flowPanel(4, 2, 0, lblNull, Box.createHorizontalStrut(5), (MyTextFieldD) fldNullHyp, lblHypParameter)); } else { // eg mu = 1.1 panelTestAndCI.add(LayoutUtil.flowPanel(4, 2, 0, lblNull, Box.createHorizontalStrut(5), lblHypParameter, (MyTextFieldD) fldNullHyp)); } panelTestAndCI.add(LayoutUtil.flowPanel(4, 2, 0, lblTailType, btnLeft, btnRight, btnTwo)); panelTestAndCI.add(LayoutUtil.flowPanel(4, 2, 0, ckPooled)); break; case ZMEAN_CI: case ZMEAN2_CI: case TMEAN_CI: case TMEAN2_CI: case ZPROP_CI: case ZPROP2_CI: panelTestAndCI.add( LayoutUtil.flowPanel(4, 2, 0, lblConfLevel, (MyTextFieldD) fldConfLevel)); panelTestAndCI.add(LayoutUtil.flowPanel(4, 2, 0, ckPooled)); break; } GridBagConstraints c = new GridBagConstraints(); c.gridx = 0; c.gridy = 1; c.anchor = GridBagConstraints.NORTHWEST; c.insets = new Insets(10, 0, 0, 0); panelBasicProcedures.add(panelSample1, c); c.gridx = 1; c.weightx = 1; c.insets = new Insets(10, 30, 0, 0); panelBasicProcedures.add(panelSample2, c); c.gridx = 0; c.gridy = 0; c.weightx = 0; c.weighty = 1; c.gridwidth = 2; c.insets = new Insets(10, 0, 0, 0); c.anchor = GridBagConstraints.FIRST_LINE_START; panelBasicProcedures.add(panelTestAndCI, c); } private void createGUIElements() { // text pane to hold result HTML output resultPane = new JEditorPane(); HTMLEditorKit kit = new HTMLEditorKit(); resultPane.setEditorKit(kit); setStyleSheets(kit); resultPane.setEditable(false); s1 = new double[3]; s2 = new double[3]; lblResult = new JLabel(); lblSampleHeader1 = new JLabel(); lblSampleHeader2 = new JLabel(); bodyText = new StringBuilder(); ckPooled = new JCheckBox(); ckPooled.setSelected(false); ckPooled.addActionListener(this); cbProcedure = new JComboBox(); cbProcedure.setRenderer(new ListSeparatorRenderer()); cbProcedure.addActionListener(this); btnCalculate = new JButton(); btnCalculate.addActionListener(this); btnLeft = new JRadioButton(tail_left); btnRight = new JRadioButton(tail_right); btnTwo = new JRadioButton(tail_two); ButtonGroup group = new ButtonGroup(); group.add(btnLeft); group.add(btnRight); group.add(btnTwo); btnLeft.addActionListener(this); btnRight.addActionListener(this); btnTwo.addActionListener(this); btnTwo.setSelected(true); lblNull = new JLabel(); lblHypParameter = new JLabel(); lblTailType = new JLabel(); fldNullHyp = new MyTextFieldD((AppD) app); fldNullHyp.setColumns(fieldWidth); addActionListener(fldNullHyp); ((MyTextFieldD) fldNullHyp).addFocusListener(this); lblConfLevel = new JLabel(); fldConfLevel = new MyTextFieldD((AppD) app); fldConfLevel.setColumns(fieldWidth); addActionListener(fldConfLevel); ((MyTextFieldD) fldNullHyp).addFocusListener(this); lblSigma = new JLabel(); fldSigma = new MyTextFieldD((AppD) app); fldSigma.setColumns(fieldWidth); addActionListener(fldSigma); ((MyTextFieldD) fldNullHyp).addFocusListener(this); lblSampleStat1 = new JLabel[3]; for (int i = 0; i < lblSampleStat1.length; i++) { lblSampleStat1[i] = new JLabel(); } fldSampleStat1 = new TextObject[3]; for (int i = 0; i < fldSampleStat1.length; i++) { fldSampleStat1[i] = new MyTextFieldD((AppD) app); fldSampleStat1[i].setColumns(fieldWidth); addActionListener(fldSampleStat1[i]); ((MyTextFieldD) fldSampleStat1[i]).addFocusListener(this); } lblSampleStat2 = new JLabel[3]; for (int i = 0; i < lblSampleStat2.length; i++) { lblSampleStat2[i] = new JLabel(); } fldSampleStat2 = new MyTextFieldD[3]; for (int i = 0; i < fldSampleStat2.length; i++) { fldSampleStat2[i] = new MyTextFieldD((AppD) app); fldSampleStat2[i].setColumns(fieldWidth); addActionListener(fldSampleStat2[i]); ((MyTextFieldD) fldSampleStat2[i]).addFocusListener(this); } } @Override public void setLabels() { lblResult.setText(loc.getMenu("Result")); lblNull.setText(loc.getMenu("NullHypothesis")); lblTailType.setText(loc.getMenu("AlternativeHypothesis")); lblConfLevel.setText(loc.getMenu("ConfidenceLevel")); lblSigma.setText(loc.getMenu("StandardDeviation.short")); btnCalculate.setText(loc.getMenu("Calculate")); switch (selectedProcedure) { case ZMEAN2_TEST: case TMEAN2_TEST: case ZMEAN2_CI: case TMEAN2_CI: case ZPROP2_TEST: case ZPROP2_CI: lblSampleHeader1.setText(loc.getMenu("Sample1")); break; default: lblSampleHeader1.setText(loc.getMenu("Sample")); } lblSampleHeader2.setText(loc.getMenu("Sample2")); ckPooled.setText(loc.getMenu("Pooled")); setHypParameterLabel(); setLabelStrings(); setProcedureComboLabels(); setSampleFieldLabels(); panelChiSquare.setLabels(); // reset the text in the result panel updateResult(); } private void setHypParameterLabel() { switch (selectedProcedure) { case ZMEAN_TEST: case TMEAN_TEST: lblHypParameter .setText(loc.getMenu("HypothesizedMean.short") + " = "); break; case ZMEAN2_TEST: case TMEAN2_TEST: lblHypParameter .setText(loc.getMenu("DifferenceOfMeans.short") + " = "); break; case ZPROP_TEST: lblHypParameter.setText( loc.getMenu("HypothesizedProportion.short") + " = "); break; case ZPROP2_TEST: lblHypParameter.setText( loc.getMenu("DifferenceOfProportions.short") + " = "); break; default: lblHypParameter.setText(loc.getMenu("")); } } private void setProcedureComboLabels() { combolabelsPreprocess(); cbProcedure.removeAllItems(); cbProcedure.addItem(mapProcedureToName.get(Procedure.ZMEAN_TEST)); cbProcedure.addItem(mapProcedureToName.get(Procedure.TMEAN_TEST)); cbProcedure.addItem(mapProcedureToName.get(Procedure.ZMEAN2_TEST)); cbProcedure.addItem(mapProcedureToName.get(Procedure.TMEAN2_TEST)); cbProcedure.addItem(mapProcedureToName.get(Procedure.ZPROP_TEST)); cbProcedure.addItem(mapProcedureToName.get(Procedure.ZPROP2_TEST)); cbProcedure.addItem(ListSeparatorRenderer.SEPARATOR); cbProcedure.addItem(mapProcedureToName.get(Procedure.ZMEAN_CI)); cbProcedure.addItem(mapProcedureToName.get(Procedure.TMEAN_CI)); cbProcedure.addItem(mapProcedureToName.get(Procedure.ZMEAN2_CI)); cbProcedure.addItem(mapProcedureToName.get(Procedure.TMEAN2_CI)); cbProcedure.addItem(mapProcedureToName.get(Procedure.ZPROP_CI)); cbProcedure.addItem(mapProcedureToName.get(Procedure.ZPROP2_CI)); cbProcedure.addItem(ListSeparatorRenderer.SEPARATOR); cbProcedure.addItem(mapProcedureToName.get(Procedure.GOF_TEST)); cbProcedure.addItem(mapProcedureToName.get(Procedure.CHISQ_TEST)); cbProcedure.setMaximumRowCount(cbProcedure.getItemCount()); // TODO for testing only, remove later // cbProcedure.setSelectedItem(mapProcedureToName // .get(Procedure.CHISQ_TEST)); } private void setSampleFieldLabels() { for (int i = 0; i < 3; i++) { lblSampleStat1[i].setText(""); lblSampleStat2[i].setText(""); } switch (selectedProcedure) { default: // do nothing break; case ZMEAN_TEST: case ZMEAN_CI: lblSampleStat1[0].setText(strMean); lblSampleStat1[1].setText(strSigma); lblSampleStat1[2].setText(strN); break; case TMEAN_TEST: case TMEAN_CI: lblSampleStat1[0].setText(strMean); lblSampleStat1[1].setText(strSD); lblSampleStat1[2].setText(strN); break; case ZMEAN2_TEST: case ZMEAN2_CI: lblSampleStat1[0].setText(strMean); lblSampleStat1[1].setText(strSigma); lblSampleStat1[2].setText(strN); lblSampleStat2[0].setText(strMean); lblSampleStat2[1].setText(strSigma); lblSampleStat2[2].setText(strN); break; case TMEAN2_TEST: case TMEAN2_CI: lblSampleStat1[0].setText(strMean); lblSampleStat1[1].setText(strSD); lblSampleStat1[2].setText(strN); lblSampleStat2[0].setText(strMean); lblSampleStat2[1].setText(strSD); lblSampleStat2[2].setText(strN); break; case ZPROP_TEST: case ZPROP_CI: lblSampleStat1[0].setText(strSuccesses); lblSampleStat1[1].setText(strN); break; case ZPROP2_TEST: case ZPROP2_CI: lblSampleStat1[0].setText(strSuccesses); lblSampleStat1[1].setText(strN); lblSampleStat2[0].setText(strSuccesses); lblSampleStat2[1].setText(strN); break; } } private void updateGUI() { setHypParameterLabel(); setSampleFieldLabels(); setSampleFieldText(); for (int i = 0; i < 3; i++) { lblSampleStat1[i] .setVisible(isNotEmpty(lblSampleStat1[i].getText())); fldSampleStat1[i] .setVisible(isNotEmpty(lblSampleStat1[i].getText())); lblSampleStat2[i] .setVisible(isNotEmpty(lblSampleStat2[i].getText())); fldSampleStat2[i] .setVisible(isNotEmpty(lblSampleStat2[i].getText())); } lblSampleHeader2.setVisible((isNotEmpty(lblSampleStat2[0].getText()))); ckPooled.setVisible(selectedProcedure == Procedure.TMEAN2_TEST || selectedProcedure == Procedure.TMEAN2_CI); setPanelLayout(); wrappedPanel.revalidate(); } private static boolean isNotEmpty(String s) { return s != null && !"".equals(s); } private void setPanelLayout() { panelBasicProcedures.setVisible(false); panelChiSquare.getWrappedPanel().setVisible(false); switch (selectedProcedure) { case CHISQ_TEST: case GOF_TEST: panelChiSquare.getWrappedPanel().setVisible(true); panelChiSquare.updateGUI(); break; default: setInputPanelLayout(); panelBasicProcedures.setVisible(true); } } @Override public void actionPerformed(ActionEvent e) { doActionPerformed(e); } public void doActionPerformed(ActionEvent e) { Object source = e.getSource(); if (source instanceof JTextField) { doTextFieldActionPerformed((JTextField) source); } if (source == cbProcedure && cbProcedure.getSelectedIndex() >= 0) { selectedProcedure = mapNameToProcedure .get(cbProcedure.getSelectedItem()); updateGUI(); updateResult(); // setLabels(); // reset the scrollpane to the top javax.swing.SwingUtilities.invokeLater(new Runnable() { @Override public void run() { scroller.getVerticalScrollBar().setValue(0); } }); } if (source == btnLeft || source == btnRight || source == btnTwo) { updateResult(); } if (source == ckPooled) { sc.pooled = ckPooled.isSelected(); updateResult(); } if (source == btnCalculate) { updateResult(); } } public void doTextFieldActionPerformed(JTextField source) { if (source.getText().equals(ListSeparatorRenderer.SEPARATOR)) { return; } updateResult(); } @Override public void focusGained(FocusEvent e) { if (e.getSource() instanceof MyTextFieldD) { ((MyTextFieldD) e.getSource()).selectAll(); } } @Override public void focusLost(FocusEvent e) { if (e.getSource() instanceof MyTextFieldD) { doTextFieldActionPerformed((MyTextFieldD) e.getSource()); } } public void updateFonts(Font font) { setStyleSheetFontSize((HTMLEditorKit) resultPane.getEditorKit(), font); wrappedPanel.setFont(font); updateResultText(bodyText.toString()); } private static void setStyleSheetFontSize(HTMLEditorKit kit, Font font) { StyleSheet styleSheet = kit.getStyleSheet(); String size = "" + font.getSize(); styleSheet.addRule("body {font-size : " + size + "pt }"); } private static void setStyleSheets(HTMLEditorKit kit) { // add some styles to the html StyleSheet styleSheet = kit.getStyleSheet(); styleSheet.addRule( "body {color:#00008B; font : 9pt verdana; margin: 4px; }"); String padding = "padding-top:2px; padding-bottom:2px;padding-left:5px;padding-right:5px;"; styleSheet.addRule( "td {text-align: center; border-top-width: 1px; border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-style:solid; border-color:#00008B;" + padding + "}"); } @Override protected void updateResultText(String str) { String htmlString = "<html><body>\n" + str + "</body>\n"; resultPane.setText(htmlString); } /** * @return the wrapped panel */ public JPanel getWrappedPanel() { return wrappedPanel; } @Override protected void resetCaret() { resultPane.setCaretPosition(0); } @Override protected boolean btnRightIsSelected() { return btnRight.isSelected(); } @Override protected boolean btnLeftIsSelected() { return btnLeft.isSelected(); } @Override public void addActionListener(TextObject obj) { ((MyTextFieldD) obj).addActionListener(this); } @Override public void removeActionListener(TextObject obj) { ((MyTextFieldD) obj).removeActionListener(this); } }