package de.wwwu.awolf.view.panels; import de.wwwu.awolf.model.Line; import de.wwwu.awolf.presenter.Presenter; import de.wwwu.awolf.view.MainFrame; import de.wwwu.awolf.view.custom.ButtonGroupAtLeastTwo; import de.wwwu.awolf.view.custom.ColorColumnRenderer; import javax.swing.*; import javax.swing.border.TitledBorder; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.filechooser.FileSystemView; import javax.swing.plaf.FontUIResource; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; import javax.swing.table.JTableHeader; import javax.swing.table.TableColumn; import java.awt.*; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; /** * Created by * Armin Wolf * on 02.08.17. */ public class EvaluationPanel extends JPanel { private final MainFrame view; private JTable table; private JTableHeader header; private JButton start; private JButton clearTable; private JButton exportData; private JRadioButton evalTypeOne; //1: Alg - N: Data private JRadioButton evalTypeTwo; //N: Alg - 1: Data private ButtonGroup radiobuttonGroup; private ButtonGroup checkboxGroup; private ButtonGroupAtLeastTwo checkboxAtLeastOne; private JCheckBox lms; //1: Alg - N: Data private JCheckBox rm; //N: Alg - 1: Data private JCheckBox ts; //1: Alg - N: Data private JPanel comp; private JPanel algorithmPanel; private JPanel leftSidePanel; private JPanel datasetCount; private JComboBox datasetCountChoice; private JComboBox datasetType; private JLabel datasetCountLabel; private JSplitPane splitPane; private DefaultTableModel model; private int currentRowOfTypes; private JPanel buttonPanel; private PlotPanel plotPanel; private String[] selections = {"Approximationsgüte", "Least Median of Squares", "Repeated-Median", "Theil-Sen"}; /** * Konstruktor * * @param view View */ public EvaluationPanel(MainFrame view) { super(); this.view = view; this.setLayout(new BorderLayout()); this.currentRowOfTypes = 0; init(); addListener(); addComponents(); } /** * Initialisiere die Komponenten */ private void init() { datasetCountLabel = new JLabel("Größe des Datensatzes"); Integer[] choice = {50, 100, 200, 500, 1000, 1500}; datasetCountChoice = new JComboBox(choice); String[] datatypes = {"Punktwolke", "Gerade", "Kreis und Gerade", "Import von CSV-Datei"}; datasetType = new JComboBox<>(datatypes); start = new JButton("Start"); clearTable = new JButton("Löschen"); exportData = new JButton("Datenexport"); clearTable.setEnabled(false); exportData.setEnabled(false); evalTypeOne = new JRadioButton("Algorithmus evaluieren"); evalTypeTwo = new JRadioButton("Algorithmen vergleichen"); lms = new JCheckBox("Least Median of Squares"); rm = new JCheckBox("Repeated Median"); ts = new JCheckBox("Theil-Sen"); radiobuttonGroup = new ButtonGroup(); checkboxGroup = new ButtonGroup(); checkboxAtLeastOne = new ButtonGroupAtLeastTwo(); buttonPanel = new JPanel(new FlowLayout()); leftSidePanel = new JPanel(new BorderLayout()); comp = new JPanel(new GridLayout(0, 1)); plotPanel = new PlotPanel(); model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { //all cells false return false; } }; table = new JTable(model); UIManager.put("TableHeader.font", new Font("SansSerif", Font.BOLD, 14)); UIManager.put("TableHeader.foreground", Color.WHITE); header = table.getTableHeader(); header.setBackground(Color.GRAY); splitPane = new JSplitPane(); algorithmPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); datasetCount = new JPanel(new FlowLayout(FlowLayout.LEFT)); } /** * Hinzufügen der Komponenten zum ContentPane */ private void addComponents() { evalTypeOne.setSelected(true); lms.setSelected(true); checkboxGroup.add(lms); checkboxGroup.add(rm); checkboxGroup.add(ts); radiobuttonGroup.add(evalTypeOne); radiobuttonGroup.add(evalTypeTwo); buttonPanel.add(start); buttonPanel.add(clearTable); buttonPanel.add(exportData); algorithmPanel.add(lms); algorithmPanel.add(rm); algorithmPanel.add(ts); datasetCount.add(datasetCountLabel); datasetCount.add(datasetCountChoice); datasetCount.add(datasetType); comp.add(evalTypeOne); comp.add(evalTypeTwo); comp.add(algorithmPanel); comp.add(datasetCount); comp.setBorder(new TitledBorder("Konfiguration")); //Tabelle model.setColumnIdentifiers(selections); table.setDragEnabled(true); JScrollPane scrollPane = new JScrollPane(table); scrollPane.setWheelScrollingEnabled(true); scrollPane.setBorder(new TitledBorder("Ergebnisse")); //Plot plotPanel.createPlot(new LinkedList<>()); plotPanel.setBorder(new TitledBorder("Plot")); leftSidePanel.add(comp, BorderLayout.NORTH); leftSidePanel.add(scrollPane, BorderLayout.CENTER); //Splitpane splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT); splitPane.setResizeWeight(.5d); splitPane.setContinuousLayout(true); splitPane.setLeftComponent(leftSidePanel); splitPane.setRightComponent(plotPanel); this.add(splitPane, BorderLayout.CENTER); this.add(buttonPanel, BorderLayout.SOUTH); TableColumn tm = table.getColumnModel().getColumn(0); tm.setCellRenderer(new ColorColumnRenderer(Color.lightGray, Color.blue)); for (int i = 1; i < 4; i++) { DefaultTableCellRenderer rightRenderer = new DefaultTableCellRenderer(); rightRenderer.setHorizontalAlignment(SwingConstants.RIGHT); rightRenderer.setFont(new FontUIResource("Courier", Font.PLAIN, 12)); table.getColumnModel().getColumn(i).setCellRenderer(rightRenderer); } } /** * Hinzufügen der Listener */ private void addListener() { start.addActionListener(e -> { int type; int alg; int n; if (radiobuttonGroup.isSelected(evalTypeOne.getModel())) { type = 0; } else { type = 1; } alg = checkSelection(); n = (Integer) datasetCountChoice.getSelectedItem(); String datatyp = (String) datasetType.getSelectedItem(); if ("Import von CSV-Datei".equals(datatyp)) { SwingUtilities.invokeLater(() -> { File file = null; JFileChooser chooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); chooser.setPreferredSize(new Dimension(800, 700)); chooser.setFileFilter(new FileNameExtensionFilter("Comma-Separated Value, (*.csv)", "csv", "text")); chooser.setMultiSelectionEnabled(false); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { //Logging.logInfo ("Datei "+chooser.getSelectedFile()+ " ausgewählt."); file = chooser.getSelectedFile(); final File input = file; Thread t = new Thread(() -> ((Presenter) view.getPresenter()).startEvaluation(type, alg, input)); t.start(); } }); } else { ((Presenter) view.getPresenter()).startEvaluation(type, n, alg, datatyp); } clearTable.setEnabled(true); exportData.setEnabled(true); }); evalTypeOne.addActionListener(e -> { checkboxAtLeastOne.remove(lms); checkboxAtLeastOne.remove(rm); checkboxAtLeastOne.remove(ts); lms.setSelected(true); checkboxGroup.add(lms); checkboxGroup.add(rm); checkboxGroup.add(ts); }); evalTypeTwo.addActionListener(e -> { checkboxGroup.remove(lms); checkboxGroup.remove(rm); checkboxGroup.remove(ts); checkboxAtLeastOne.addAll(lms, rm, ts); lms.setSelected(true); rm.setSelected(true); }); clearTable.addActionListener(e -> { SwingUtilities.invokeLater(() -> { int n = model.getDataVector().size(); for (int i = 0; i < n; i++) { model.removeRow(0); currentRowOfTypes--; } this.revalidate(); clearTable.setEnabled(false); exportData.setEnabled(false); }); }); exportData.addActionListener(e -> { SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> { File file = null; JFileChooser chooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); chooser.setPreferredSize(new Dimension(800, 700)); chooser.setFileFilter(new FileNameExtensionFilter("Comma-Separated Value, (*.csv)", "csv", "text")); chooser.setMultiSelectionEnabled(false); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { file = chooser.getSelectedFile(); String filename = file.getAbsolutePath().contains(".csv") ? file.getAbsolutePath() : file.getAbsolutePath().concat(".csv"); final File input = new File(filename); Thread t = new Thread(() -> ((Presenter) view.getPresenter()).startDatasetExportEvaluation(input)); t.start(); } }); }); }); } /** * Fügt der Tabelle eine Spalte hinzu * * @param data Daten der Spalte * @param col Spalte * @param isLabel true, falls es sich um die Approximations Überschriften handelt */ public void addColumn(Object[] data, int col, boolean isLabel) { if (isLabel) { addBlankRows(data.length); } for (int i = 0; i < data.length; i++) { int row = currentRowOfTypes - data.length + i; model.setValueAt(data[i], row, col); } this.repaint(); this.revalidate(); } /** * Fügt der Tabelle eine Zeile hinzu * * @param data Daten der Zeile */ public void addRow(Object[] data) { addBlankRows(1); for (int i = 0; i < 4; i++) { model.setValueAt(data[i], currentRowOfTypes, i); } currentRowOfTypes++; this.repaint(); this.revalidate(); } /** * Visualisierung der Ausgleichsgeraden * * @param alg Steigung und y-Achsenabschnitt der Geraden, bestimmt durch die Schätzer */ public void drawLines(List alg) { Paint[] color = {Color.ORANGE, Color.RED, Color.MAGENTA}; String[] name = {"LMS", "RM", "TS"}; for (Double[] o : alg) { int i = o[0].intValue(); Double m = o[1]; Double b = o[2]; plotPanel.addLineToPlot(m, b, color[i], name[i]); } } /** * Visualisierung der Ausgleichsgerade * * @param results Steigung und y-Achsenabschnitt der Gerade, bestimmt durch die Schätzer * @param alg identifizierung des Alg. */ public void drawLines(Object[] results, int alg) { String[] castedResults = Arrays.copyOf(results, results.length, String[].class); Paint[] color = {Color.ORANGE, Color.RED, Color.MAGENTA}; String[] name = {"LMS", "RM", "TS"}; String[] nName = {"Brute-force LMS", "Brute-force RM", "Brute-force TS"}; double m = Double.parseDouble(castedResults[0]); double b = Double.parseDouble(castedResults[1]); plotPanel.addLineToPlot(m, b, color[alg], name[alg]); double nM = Double.parseDouble(castedResults[2]); double nB = Double.parseDouble(castedResults[3]); plotPanel.addLineToPlot(nM, nB, Color.BLACK, nName[alg]); } /** * Visualisierung der dualen Geraden (Eingabemenge) * * @param points Liste der Geraden */ public void setDualPoints(List points) { plotPanel = new PlotPanel(); plotPanel.setBorder(new TitledBorder("Plot")); splitPane.setRightComponent(plotPanel); plotPanel.createPlot(points); plotPanel.repaint(); plotPanel.revalidate(); } /** * Hilfsmethode * * @param n Anzahl der leeren Zeilen */ private void addBlankRows(int n) { for (int i = 0; i < n; i++) { String[] tmp = {"", "", "", "",}; model.addRow(tmp); } } /** * Hilfsmethode * * @param val Anzahl der Zeilen die noch hinzugefügt werden */ public void setCurrentRow(int val) { this.currentRowOfTypes += val; } /** * @return Kodierung welche Algorithmen ausgewählt wurden */ private int checkSelection() { if (lms.isSelected() && rm.isSelected() && ts.isSelected()) { return 6; } else if (!lms.isSelected() && rm.isSelected() && ts.isSelected()) { return 5; } else if (lms.isSelected() && !rm.isSelected() && ts.isSelected()) { return 4; } else if (lms.isSelected() && rm.isSelected() && !ts.isSelected()) { return 3; } else if (!lms.isSelected() && !rm.isSelected() && ts.isSelected()) { return 2; } else if (!lms.isSelected() && rm.isSelected() && !ts.isSelected()) { return 1; } else if (lms.isSelected() && !rm.isSelected() && !ts.isSelected()) { return 0; } else { throw new IllegalStateException("Mindestens ein Algortihmus muss selektiert werden"); } } }