diff --git a/recorder/pom.xml b/recorder/pom.xml
index a1241c4..a91d322 100644
--- a/recorder/pom.xml
+++ b/recorder/pom.xml
@@ -32,4 +32,22 @@
+
+
+
+ maven-assembly-plugin
+
+
+
+ com.github.andrewlalis.running_every_day.RecorderApp
+
+
+
+ jar-with-dependencies
+
+
+
+
+
+
\ No newline at end of file
diff --git a/recorder/src/main/java/com/github/andrewlalis/running_every_day/RecorderApp.java b/recorder/src/main/java/com/github/andrewlalis/running_every_day/RecorderApp.java
index 07abea3..cd30783 100644
--- a/recorder/src/main/java/com/github/andrewlalis/running_every_day/RecorderApp.java
+++ b/recorder/src/main/java/com/github/andrewlalis/running_every_day/RecorderApp.java
@@ -24,6 +24,8 @@ public class RecorderApp {
System.out.println("Added App Window close listener");
window.setVisible(true);
System.out.println("Set App Window as visible");
+ window.initComponentData();
+ System.out.println("Initialized component data");
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, "Failed to open database: " + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
diff --git a/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/AggregateStatisticsPanel.java b/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/AggregateStatisticsPanel.java
index 673e101..e76c76c 100644
--- a/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/AggregateStatisticsPanel.java
+++ b/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/AggregateStatisticsPanel.java
@@ -33,8 +33,10 @@ public class AggregateStatisticsPanel extends JPanel {
refreshButton.addActionListener(e -> refreshStats());
controlsPanel.add(refreshButton);
this.add(controlsPanel, BorderLayout.NORTH);
+ }
-// SwingUtilities.invokeLater(this::refreshStats);
+ public void init() {
+ SwingUtilities.invokeLater(this::refreshStats);
}
private void refreshStats() {
diff --git a/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/RecorderAppWindow.java b/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/RecorderAppWindow.java
index dc241d0..dd7428b 100644
--- a/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/RecorderAppWindow.java
+++ b/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/RecorderAppWindow.java
@@ -6,8 +6,14 @@ import javax.swing.*;
import java.awt.*;
public class RecorderAppWindow extends JFrame {
+ private final RunRecordsPanel runRecordsPanel;
+ private final AggregateStatisticsPanel aggregateStatisticsPanel;
+
public RecorderAppWindow(DataSource dataSource) {
super("Run-Recorder");
+ this.runRecordsPanel = new RunRecordsPanel(dataSource);
+ this.aggregateStatisticsPanel = new AggregateStatisticsPanel(dataSource);
+
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
this.setContentPane(buildGui(dataSource));
this.setPreferredSize(new Dimension(1000, 600));
@@ -15,10 +21,15 @@ public class RecorderAppWindow extends JFrame {
this.setLocationRelativeTo(null);
}
+ public void initComponentData() {
+ runRecordsPanel.init();
+ aggregateStatisticsPanel.init();
+ }
+
private Container buildGui(DataSource dataSource) {
JTabbedPane tabbedPane = new JTabbedPane();
- tabbedPane.addTab("Run Records", new RunRecordsPanel(dataSource));
- tabbedPane.addTab("Aggregate Statistics", new AggregateStatisticsPanel(dataSource));
+ tabbedPane.addTab("Run Records", runRecordsPanel);
+ tabbedPane.addTab("Aggregate Statistics", aggregateStatisticsPanel);
tabbedPane.addTab("Charts", new ChartsPanel(dataSource));
return tabbedPane;
}
diff --git a/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/RunRecordsPanel.java b/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/RunRecordsPanel.java
index 0fe786e..93eb24e 100644
--- a/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/RunRecordsPanel.java
+++ b/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/RunRecordsPanel.java
@@ -5,6 +5,8 @@ import com.github.andrewlalis.running_every_day.data.db.DataSource;
import com.github.andrewlalis.running_every_day.data.db.Queries;
import javax.swing.*;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
import java.awt.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
@@ -22,17 +24,28 @@ public class RunRecordsPanel extends JPanel {
private final DataSource dataSource;
private final RunRecordTableModel tableModel;
- private final JTextField currentPageField;
- private final JButton firstPageButton;
- private final JButton previousPageButton;
- private final JButton nextPageButton;
- private final JButton lastPageButton;
+ private final JTextField currentPageField = new JTextField("1", 3);
+ private final JButton firstPageButton = new JButton("First Page");
+ private final JButton previousPageButton = new JButton("Previous Page");
+ private final JButton nextPageButton = new JButton("Next Page");
+ private final JButton lastPageButton = new JButton("Last Page");
public RunRecordsPanel(DataSource dataSource) {
super(new BorderLayout());
this.dataSource = dataSource;
this.tableModel = new RunRecordTableModel(dataSource);
+ tableModel.addTableModelListener(e -> updateButtonStates());
+ this.add(buildTablePanel(), BorderLayout.CENTER);
+ this.add(buildPaginationPanel(), BorderLayout.SOUTH);
+ this.add(buildActionsPanel(), BorderLayout.NORTH);
+ }
+
+ public void init() {
+ SwingUtilities.invokeLater(tableModel::firstPage);
+ }
+
+ private Container buildTablePanel() {
var table = new JTable(tableModel);
table.getTableHeader().setReorderingAllowed(false);
table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
@@ -48,56 +61,10 @@ public class RunRecordsPanel extends JPanel {
for (int i = 0; i < 7; i++) {
table.getColumnModel().getColumn(i).setResizable(false);
}
- var scrollPane = new JScrollPane(table, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
- this.add(scrollPane, BorderLayout.CENTER);
-
- JPanel paginationPanel = new JPanel(new GridLayout(1, 6));
- firstPageButton = new JButton("First Page");
- firstPageButton.addActionListener(e -> {
- tableModel.firstPage();
- updateButtonStates();
- });
- previousPageButton = new JButton("Previous Page");
- previousPageButton.addActionListener(e -> {
- tableModel.previousPage();
- updateButtonStates();
- });
- nextPageButton = new JButton("Next Page");
- nextPageButton.addActionListener(e -> {
- tableModel.nextPage();
- updateButtonStates();
- });
- lastPageButton = new JButton("Last Page");
- lastPageButton.addActionListener(e -> {
- tableModel.lastPage();
- updateButtonStates();
- });
-
- JPanel currentPagePanel = new JPanel();
- currentPagePanel.add(new JLabel("Current Page: "));
- this.currentPageField = new JTextField("1", 3);
- currentPagePanel.add(this.currentPageField);
-
- JPanel pageSizePanel = new JPanel();
- pageSizePanel.add(new JLabel("Page Size: "));
- JComboBox pageSizeSelector = new JComboBox<>(new Integer[]{5, 10, 20, 50, 100, 500});
- pageSizeSelector.setSelectedItem(tableModel.getPagination().size());
- pageSizeSelector.addItemListener(e -> {
- int size = (int) e.getItem();
- tableModel.setPageSize(size);
- updateButtonStates();
- });
- pageSizePanel.add(pageSizeSelector);
-
- paginationPanel.add(firstPageButton);
- paginationPanel.add(previousPageButton);
- paginationPanel.add(currentPagePanel);
- paginationPanel.add(pageSizePanel);
- paginationPanel.add(nextPageButton);
- paginationPanel.add(lastPageButton);
-
- this.add(paginationPanel, BorderLayout.SOUTH);
+ return new JScrollPane(table, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ }
+ private JPanel buildActionsPanel() {
JPanel actionsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JButton addActionButton = new JButton("Add a Record");
addActionButton.addActionListener(e -> {
@@ -111,7 +78,37 @@ public class RunRecordsPanel extends JPanel {
JButton generateRandomDataButton = new JButton("Generate Random Data");
generateRandomDataButton.addActionListener(e -> generateRandomData());
actionsPanel.add(generateRandomDataButton);
- this.add(actionsPanel, BorderLayout.NORTH);
+ return actionsPanel;
+ }
+
+ private JPanel buildPaginationPanel() {
+ JPanel paginationPanel = new JPanel(new GridLayout(1, 6));
+ firstPageButton.addActionListener(e -> tableModel.firstPage());
+ previousPageButton.addActionListener(e -> tableModel.previousPage());
+ nextPageButton.addActionListener(e -> tableModel.nextPage());
+ lastPageButton.addActionListener(e -> tableModel.lastPage());
+
+ JPanel currentPagePanel = new JPanel();
+ currentPagePanel.add(new JLabel("Current Page: "));
+ currentPagePanel.add(this.currentPageField);
+
+ JPanel pageSizePanel = new JPanel();
+ pageSizePanel.add(new JLabel("Page Size: "));
+ JComboBox pageSizeSelector = new JComboBox<>(new Integer[]{5, 10, 20, 50, 100, 500});
+ pageSizeSelector.setSelectedItem(tableModel.getPagination().size());
+ pageSizeSelector.addItemListener(e -> {
+ int size = (int) e.getItem();
+ tableModel.setPageSize(size);
+ });
+ pageSizePanel.add(pageSizeSelector);
+
+ paginationPanel.add(firstPageButton);
+ paginationPanel.add(previousPageButton);
+ paginationPanel.add(currentPagePanel);
+ paginationPanel.add(pageSizePanel);
+ paginationPanel.add(nextPageButton);
+ paginationPanel.add(lastPageButton);
+ return paginationPanel;
}
private void updateButtonStates() {
@@ -151,7 +148,6 @@ public class RunRecordsPanel extends JPanel {
c.commit();
c.setAutoCommit(true);
tableModel.firstPage();
- updateButtonStates();
} catch (SQLException e) {
e.printStackTrace();
}
diff --git a/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/WindowDataSourceCloser.java b/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/WindowDataSourceCloser.java
index 5f80c93..e57020d 100644
--- a/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/WindowDataSourceCloser.java
+++ b/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/WindowDataSourceCloser.java
@@ -20,6 +20,7 @@ public class WindowDataSourceCloser extends WindowAdapter {
public void windowClosing(WindowEvent e) {
try {
dataSource.close();
+ System.out.println("Data source closed");
} catch (SQLException ex) {
ex.printStackTrace();
}
diff --git a/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/chart/DateSeriesChartRenderer.java b/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/chart/DateSeriesChartRenderer.java
index f4da993..5411003 100644
--- a/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/chart/DateSeriesChartRenderer.java
+++ b/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/chart/DateSeriesChartRenderer.java
@@ -53,6 +53,9 @@ public class DateSeriesChartRenderer extends JFreeChartRenderer {
false
);
}
+ if (series.getItemCount() < 2) {
+ throw new IllegalStateException("Not enough data.");
+ }
XYDataset dataset = new TimeSeriesCollection(series);
DateAxis domainAxis = new DateAxis();
diff --git a/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/chart/JFreeChartRenderer.java b/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/chart/JFreeChartRenderer.java
index 3f4c20c..d5c9a9f 100644
--- a/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/chart/JFreeChartRenderer.java
+++ b/recorder/src/main/java/com/github/andrewlalis/running_every_day/view/chart/JFreeChartRenderer.java
@@ -17,14 +17,10 @@ public abstract class JFreeChartRenderer implements ChartRenderer {
protected abstract JFreeChart getChart() throws Exception;
protected void applyCustomStyles(JFreeChart chart) {}
- public void refresh() {
- try {
- lastChart = getChart();
- standardChartTheme.apply(lastChart);
- applyCustomStyles(lastChart);
- } catch (Exception e) {
- e.printStackTrace();
- }
+ public void refresh() throws Exception {
+ lastChart = getChart();
+ standardChartTheme.apply(lastChart);
+ applyCustomStyles(lastChart);
}
@Override
@@ -35,7 +31,7 @@ public abstract class JFreeChartRenderer implements ChartRenderer {
}
lastChart.draw(graphics, area);
} catch (Exception e) {
- graphics.setColor(Color.BLACK);
+ graphics.setColor(Color.RED);
graphics.setBackground(Color.WHITE);
graphics.fill(area);
graphics.drawString("Error: " + e.getMessage(), 20, 40);