package de.wwwu.awolf.view; import de.wwwu.awolf.model.Line; import de.wwwu.awolf.presenter.AbstractPresenter; import de.wwwu.awolf.presenter.Presenter; import de.wwwu.awolf.presenter.util.Logging; import de.wwwu.awolf.view.listener.*; import de.wwwu.awolf.view.panels.DualityPanel; import de.wwwu.awolf.view.panels.EvaluationPanel; import de.wwwu.awolf.view.panels.InfoPanel; import de.wwwu.awolf.view.panels.PlotPanel; import de.wwwu.awolf.view.panels.tabs.LMSPanel; import de.wwwu.awolf.view.panels.tabs.RMPanel; import de.wwwu.awolf.view.panels.tabs.TSPanel; import de.wwwu.awolf.view.panels.tabs.TabPanel; import javax.imageio.ImageIO; import javax.swing.*; import java.awt.*; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. * * @Author: Armin Wolf * @Email: a_wolf28@uni-muenster.de * @Date: 28.05.2017. */ public class MainFrame extends JFrame { private AbstractPresenter presenter; private Boolean lmsIsComplete = false; private Boolean rmIsComplete = false; private Boolean tsIsComplete = false; private JButton arrangementButton; private JButton importButton; private JButton generateButton; private JButton exportButton; private InfoPanel output; private MenuBar menu; private JToolBar toolBar; private TabPanel lmsPanel; private TabPanel rmPanel; private TabPanel tsPanel; private DualityPanel arrangement; private JDialog arrangementDialog; private PlotPanel plotLMS; private PlotPanel plotRM; private PlotPanel plotTS; private JDialog progressDialog; private JDialog evaluationDialog; private Container progressContent; private JProgressBar progressBar; private JSplitPane splitpane; private JScrollPane scrollPane; private JTabbedPane tabbedPane; private EvaluationPanel evaluationPanel; /** * Konstruktor */ public MainFrame() { super(); initializeComponents(); setDimensions(); setLayouts(); setTitles(); addComponents(); setCloseOperations(); setIcons(); disableFunctionality(); this.setVisible(true); } /******************************************************************************************************************* * visualisierungs methoden ******************************************************************************************************************/ /** * Erzeugt den Dialog für die duale Darstellung */ public void createDualityDialog() { arrangement = new DualityPanel(); arrangementDialog = new JDialog(); arrangementDialog.setTitle("Dualraum - Dialog"); arrangementDialog.setMinimumSize(new Dimension(1024, 768)); arrangementDialog.setPreferredSize(new Dimension(800, 800)); arrangementDialog.setLocationRelativeTo(this); arrangementDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); arrangementButton.addActionListener(new DualityVisualizerListener((Presenter) getPresenter())); arrangement.clear(); arrangement.setPrameters(getPresenter().getModel().getLines(), getPresenter().getModel().getNodes(), getPresenter().getModel().getxMinimum(), getPresenter().getModel().getxMaximum(), getPresenter().getModel().getyMinimum(), getPresenter().getModel().getyMaximum()); arrangement.createArrangement(); SwingUtilities.invokeLater(() -> { arrangementDialog.add(arrangement); arrangementDialog.setLocationRelativeTo(this); arrangementDialog.revalidate(); arrangementDialog.repaint(); arrangementDialog.setVisible(true); }); } /** * Visualisiert das Ergebnis des LMS-Schätzers * * @param m Steigung * @param b y-Achsenabschnitt */ public void visualizeLMS(double m, double b) { plotLMS = new PlotPanel(); lmsPanel.setPlotPanel(plotLMS); createPlot(m, b, plotLMS, lmsPanel, "LMS"); } /** * Visualisiert das Ergebnis des LMS-Schätzers * * @param line Line */ public void visualizeLMS(final Line line) { plotLMS = new PlotPanel(); lmsPanel.setPlotPanel(plotLMS); createPlot(line.getM(), line.getB(), plotLMS, lmsPanel, "LMS"); } /** * Visualisiert das Ergebnis des RM-Schätzers * * @param m Steigung * @param b y-Achsenabschnitt */ public void visualizeRM(double m, double b) { plotRM = new PlotPanel(); rmPanel.setPlotPanel(plotRM); createPlot(m, b, plotRM, rmPanel, "RM"); } /** * Visualisiert das Ergebnis des RM-Schätzers * * @param line Line */ public void visualizeRM(final Line line) { plotRM = new PlotPanel(); rmPanel.setPlotPanel(plotRM); createPlot(line.getM(), line.getB(), plotRM, rmPanel, "RM"); } /** * Visualisiert das Ergebnis des TS-Schätzers * * @param m Steigung * @param b y-Achsenabschnitt */ public void visualizeTS(double m, double b) { plotTS = new PlotPanel(); tsPanel.setPlotPanel(plotTS); createPlot(m, b, plotTS, tsPanel, "TS"); } /** * Visualisiert das Ergebnis des TS-Schätzers * * @param line Line */ public void visualizeTS(final Line line) { plotTS = new PlotPanel(); tsPanel.setPlotPanel(plotTS); createPlot(line.getM(), line.getB(), plotTS, tsPanel, "TS"); } /** * Erzeugt den Plot zu einer Eingabe von Punkten und der Lösung eines Schätzers (m,b) * * @param m Steigung * @param b y-Achsenabschnitt * @param plot Plot * @param panel Panel auf dem der Plot plaziert wird * @param name Bezeichnung der Gerade */ public void createPlot(double m, double b, PlotPanel plot, JPanel panel, String name) { SwingUtilities.invokeLater(() -> { plot.clear(); plot.createPlot(getPresenter().getModel().getLines()); plot.addLineToPlot(m, b, name); panel.revalidate(); }); } /** * Visualisierung des Import-Prozesses * * @param progress akteulle Prozentzahl (0-100) */ public void showImportProgress(Integer progress) { progressBar.setValue(progress); progressBar.setStringPainted(true); progressDialog.setVisible(true); } /** * Zeigt den Evaluations-Dialog an (ggf. wird dieser erzeugt) */ public void showEvauluationDialog() { if (evaluationDialog == null) { SwingUtilities.invokeLater(() -> { evaluationDialog = new JDialog(); evaluationDialog.setTitle("evaluation"); evaluationDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); evaluationDialog.setSize(new Dimension(1500, 800)); evaluationDialog.setLocationRelativeTo(null); evaluationPanel = new EvaluationPanel(this); evaluationDialog.setLocationRelativeTo(this); evaluationDialog.add(evaluationPanel); evaluationDialog.setVisible(true); }); } else { SwingUtilities.invokeLater(() -> { evaluationDialog.setLocationRelativeTo(this); evaluationDialog.setVisible(true); }); } } /** * Fügt der Evaluations-Tabelle eine Spalte mit Daten hinzu * * @param res Daten der Spalte * @param col Spalte * @param isApprCol true, falls es sich um die Überschirften der Approximationsgüten handelt */ public void appendEvalResult(Object[] res, int col, boolean isApprCol) { SwingUtilities.invokeLater(() -> { Object[] tmp = Arrays.copyOfRange(res, 2, res.length); if (isApprCol) { evaluationPanel.setCurrentRow(tmp.length); evaluationPanel.addColumn(tmp, col, true); } else { evaluationPanel.addColumn(tmp, col + 1, false); } evaluationPanel.repaint(); evaluationPanel.revalidate(); }); } /** * Fügt der Evaluations-Tabelle eine Zeile mit Daten hinzu * * @param res Daten der Spalte */ public void appendEvalResult(Object[] res) { SwingUtilities.invokeLater(() -> { Object[] tmp = Arrays.copyOfRange(res, 1, res.length); evaluationPanel.addRow(tmp); evaluationPanel.repaint(); evaluationPanel.revalidate(); }); } /** * Visualisiert die Ausgleichsgerade zu gegebenen Algorithmen * * @param res Steigungen und y-Achsenabschnitte * @param alg Kodierung der Alg. */ public void drawLineResult(Object[] res, int alg) { SwingUtilities.invokeLater(() -> { Object[] result = Arrays.copyOfRange(res, 2, res.length); evaluationPanel.drawLines(result, alg); evaluationPanel.repaint(); evaluationPanel.revalidate(); }); } /** * Visualisiert die Ausgleichsgerade zu einem gegebenen Algorithmus * * @param res Steigungen und y-Achsenabschnitte */ public void drawLineResults(Object[] res) { SwingUtilities.invokeLater(() -> { Object[] result = Arrays.copyOfRange(res, 1, res.length); List algs = new ArrayList<>(); for (int i = 0; i < (result.length + 1) / 3; i++) { String name = (String) result[(3 * i)]; String m = (String) result[(3 * i) + 1]; String b = (String) result[(3 * i) + 2]; Double[] tmp = {Double.parseDouble(name), Double.parseDouble(m), Double.parseDouble(b)}; algs.add(tmp); } evaluationPanel.drawLines(algs); evaluationPanel.repaint(); evaluationPanel.revalidate(); }); } /** * Evaluations-Datensätze werden Visualisiert * * @param lines Liste der Geraden */ public void addEvalDataset(List lines) { SwingUtilities.invokeLater(() -> { evaluationPanel.setDualPoints(lines); evaluationPanel.repaint(); evaluationPanel.revalidate(); }); } /******************************************************************************************************************* * init GUI ******************************************************************************************************************/ /** * Setzt den Titel der Komponenten */ private void setTitles() { this.setTitle("Algorithmen zur Berechnung von Ausgleichgeraden"); importButton.setText("Import"); exportButton.setText("Export"); generateButton.setText("Generiere"); arrangementButton.setText("Dualraum"); } /** * Fügt die einzelnen Seiten dem TabbedPane hinzu */ private void setupTabbedPane() { tabbedPane.add("Least Median of Squares", lmsPanel); tabbedPane.add("Repeated Median", rmPanel); tabbedPane.add("Theil-Sen", tsPanel); } /** * Komponenten werden in Container gesetzt */ private void addComponents() { toolBar.add(arrangementButton); toolBar.add(importButton); toolBar.add(exportButton); toolBar.add(generateButton); toolBar.setFloatable(false); setJMenuBar(menu.getMenuBar()); add(toolBar); //northPanel.add(toolBar); setupSplitPane(); setupTabbedPane(); progressContent.add(progressBar, BorderLayout.CENTER); progressBar.setBorder(BorderFactory.createTitledBorder("Import...")); progressDialog.setLocationRelativeTo(null); ((JPanel) progressDialog.getContentPane()).setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY)); this.add(toolBar, BorderLayout.NORTH); this.add(splitpane, BorderLayout.CENTER); } /** * Konfiguration des SplitPane */ private void setupSplitPane() { splitpane.setOrientation(JSplitPane.HORIZONTAL_SPLIT); splitpane.setResizeWeight(.5d); splitpane.setContinuousLayout(true); splitpane.setLeftComponent(output); splitpane.setRightComponent(tabbedPane); } /** * Fenster Funktionalität wird gesetzt */ private void setCloseOperations() { this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); progressDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); } /** * Größen der Komponenten werden gesetzt */ private void setDimensions() { this.setSize(new Dimension(1500, 800)); this.setResizable(true); GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); this.setMaximizedBounds(env.getMaximumWindowBounds()); lmsPanel.setMinimumSize(new Dimension(400, 500)); rmPanel.setMinimumSize(new Dimension(400, 500)); tsPanel.setMinimumSize(new Dimension(400, 500)); output.setMinimumSize(new Dimension(400, 500)); progressDialog.setSize(300, 45); progressDialog.setResizable(false); progressDialog.setUndecorated(true); } /** * Setzen der Layouts */ private void setLayouts() { this.setLayout(new BorderLayout()); toolBar.setLayout(new FlowLayout(FlowLayout.LEFT)); } /** * Initialisierung der Komponenten */ private void initializeComponents() { //panels toolBar = new JToolBar(); lmsPanel = new LMSPanel(); rmPanel = new RMPanel(); tsPanel = new TSPanel(); menu = new MenuBar(this); //Dialogs progressDialog = new JDialog(); progressDialog.setLocationRelativeTo(null); progressContent = progressDialog.getContentPane(); progressBar = new JProgressBar(); //Panes tabbedPane = new JTabbedPane(); output = new InfoPanel(); splitpane = new JSplitPane(); //Buttons arrangementButton = new JButton(); importButton = new JButton(); generateButton = new JButton(); exportButton = new JButton(); pack(); } /** * Icons werden passend gesetzt */ private void setIcons() { try { ClassLoader classLoader = getClass().getClassLoader(); Image imgImport = ImageIO.read(classLoader.getResource("import.png")).getScaledInstance(16, 16, Image.SCALE_SMOOTH); Image imgPlot = ImageIO.read(classLoader.getResource("plot.png")).getScaledInstance(16, 16, Image.SCALE_SMOOTH); Image imgStart = ImageIO.read(classLoader.getResource("start.png")).getScaledInstance(32, 32, Image.SCALE_SMOOTH); Image imgGenerate = ImageIO.read(classLoader.getResource("generate.png")).getScaledInstance(16, 16, Image.SCALE_SMOOTH); Image imgExport = ImageIO.read(classLoader.getResource("export.png")).getScaledInstance(16, 16, Image.SCALE_SMOOTH); Image imgFrame = ImageIO.read(classLoader.getResource("frame.png")).getScaledInstance(32, 23, Image.SCALE_SMOOTH); importButton.setIcon(new ImageIcon(imgImport)); exportButton.setIcon(new ImageIcon(imgExport)); generateButton.setIcon(new ImageIcon(imgGenerate)); arrangementButton.setIcon(new ImageIcon(imgPlot)); lmsPanel.getStartButton().setIcon(new ImageIcon(imgStart)); rmPanel.getStartButton().setIcon(new ImageIcon(imgStart)); tsPanel.getStartButton().setIcon(new ImageIcon(imgStart)); this.setIconImage(imgFrame); } catch (IOException e) { Logging.logError(e.getMessage(), e); } } /** * Funktionalitäten werden hinzugefügt */ public void setActionListeners() { //action listener für MenuItems menu.addActionListeners(); //action listener für diese Klasse arrangementButton.addActionListener(new DualityVisualizerListener((Presenter) getPresenter())); lmsPanel.getStartButton().addActionListener(new StartAlgorithmListener(((Presenter) getPresenter()), lmsPanel)); rmPanel.getStartButton().addActionListener(new StartAlgorithmListener(((Presenter) getPresenter()), rmPanel)); tsPanel.getStartButton().addActionListener(new StartAlgorithmListener(((Presenter) getPresenter()), tsPanel)); importButton.addActionListener(new ImportDataListener((Presenter) this.getPresenter(), this)); exportButton.addActionListener(new ExportDataListener((Presenter) this.getPresenter(), this)); generateButton.addActionListener(new GenerateDataListener((Presenter) this.getPresenter())); } /** * Funktionalitäten werden aktiviert. */ public void enableFunctionality() { this.getLmsPanel().getStartButton().setEnabled(true); this.getRmPanel().getStartButton().setEnabled(true); this.getTsPanel().getStartButton().setEnabled(true); this.getArrangementButton().setEnabled(true); this.getExportButton().setEnabled(true); } /** * Funktionalitäten werden deaktiviert. */ public void disableFunctionality() { this.getLmsPanel().getStartButton().setEnabled(false); this.getRmPanel().getStartButton().setEnabled(false); this.getTsPanel().getStartButton().setEnabled(false); this.getArrangementButton().setEnabled(false); this.getExportButton().setEnabled(false); } /******************************************************************************************************************* * log Methode ******************************************************************************************************************/ /** * @param s Text der ausgegeben wird */ public void log(String s) { SwingUtilities.invokeLater(() -> output.appendParagraph(s)); } /** * @param s Fehlertext der ausgegeben wird */ public void logError(String s) { SwingUtilities.invokeLater(() -> output.appendParagraphRed(s)); } /** * @param s Text der in grüner Farbe ausgegeben wird */ public void logSuccess(String s) { SwingUtilities.invokeLater(() -> output.appendParagraphGreen(s)); } /** * @param s Text der als Überschrift ausgegeben wird */ public void logHeading(String s) { SwingUtilities.invokeLater(() -> output.appendParagraphWithHeading(s)); } /** * Ausgabe einer Tabelle * * @param heading Überschrift * @param rows Zeilen mit Text */ public void createTable(List heading, List> rows) { SwingUtilities.invokeLater(() -> output.logTable(heading, rows)); } /******************************************************************************************************************* * Getter und Setter Methoden ******************************************************************************************************************/ /** * @return liefert den Button, zum visualisieren des dualen Raums zurück */ public JButton getArrangementButton() { return arrangementButton; } /** * @return liefert das Panel zum visualisieren des LMS-Schätzers */ public TabPanel getLmsPanel() { return lmsPanel; } /** * @return liefert das Panel zum visualisieren des RM-Schätzers */ public TabPanel getRmPanel() { return rmPanel; } /** * @return liefert die Instanz des Presenters zurück */ public AbstractPresenter getPresenter() { return presenter; } /** * @param presenter Presenter Instanz */ public void setPresenter(AbstractPresenter presenter) { this.presenter = presenter; } /** * @return liefert den Dialog zum visualisieren des Import-Fortschrits */ public JDialog getProgressDialog() { return progressDialog; } /** * @return liefert das Panel zum visualisieren des TS-Schätzers */ public TabPanel getTsPanel() { return tsPanel; } /** * @return liefert den Button, exportieren zurück */ public JButton getExportButton() { return exportButton; } }