Added build script and more stuff

This commit is contained in:
Andrew Lalis 2023-04-22 09:43:14 +02:00
parent 6b839349fb
commit 22c1fb6d74
8 changed files with 100 additions and 27 deletions

5
recorder/build.sh Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
mvn clean compile assembly:single
cp target/recorder-*-jar-with-dependencies.jar recorder.jar
chmod +x recorder.jar

View File

@ -81,6 +81,11 @@ public class RunRecordTableModel extends AbstractTableModel {
} }
} }
public long getRecordIdAtRow(int row) {
if (row < 0 || row >= records.size()) return -1;
return records.get(row).id();
}
@Override @Override
public int getRowCount() { public int getRowCount() {
return records.size(); return records.size();

View File

@ -5,8 +5,6 @@ import com.github.andrewlalis.running_every_day.data.db.DataSource;
import com.github.andrewlalis.running_every_day.data.db.Queries; import com.github.andrewlalis.running_every_day.data.db.Queries;
import javax.swing.*; import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import java.awt.*; import java.awt.*;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
@ -24,6 +22,10 @@ public class RunRecordsPanel extends JPanel {
private final DataSource dataSource; private final DataSource dataSource;
private final RunRecordTableModel tableModel; private final RunRecordTableModel tableModel;
private final JTable table;
private final JButton deleteRecordButton = new JButton("Delete Record");
private final JTextField currentPageField = new JTextField("1", 3); private final JTextField currentPageField = new JTextField("1", 3);
private final JButton firstPageButton = new JButton("First Page"); private final JButton firstPageButton = new JButton("First Page");
private final JButton previousPageButton = new JButton("Previous Page"); private final JButton previousPageButton = new JButton("Previous Page");
@ -34,6 +36,7 @@ public class RunRecordsPanel extends JPanel {
super(new BorderLayout()); super(new BorderLayout());
this.dataSource = dataSource; this.dataSource = dataSource;
this.tableModel = new RunRecordTableModel(dataSource); this.tableModel = new RunRecordTableModel(dataSource);
this.table = new JTable(tableModel);
tableModel.addTableModelListener(e -> updateButtonStates()); tableModel.addTableModelListener(e -> updateButtonStates());
this.add(buildTablePanel(), BorderLayout.CENTER); this.add(buildTablePanel(), BorderLayout.CENTER);
@ -46,7 +49,6 @@ public class RunRecordsPanel extends JPanel {
} }
private Container buildTablePanel() { private Container buildTablePanel() {
var table = new JTable(tableModel);
table.getTableHeader().setReorderingAllowed(false); table.getTableHeader().setReorderingAllowed(false);
table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
table.getColumnModel().getColumn(0).setMaxWidth(50); table.getColumnModel().getColumn(0).setMaxWidth(50);
@ -61,6 +63,9 @@ public class RunRecordsPanel extends JPanel {
for (int i = 0; i < 7; i++) { for (int i = 0; i < 7; i++) {
table.getColumnModel().getColumn(i).setResizable(false); table.getColumnModel().getColumn(i).setResizable(false);
} }
table.getSelectionModel().addListSelectionListener(e -> {
deleteRecordButton.setEnabled(!e.getValueIsAdjusting() && tableModel.getRecordIdAtRow(table.getSelectedRow()) != -1);
});
return new JScrollPane(table, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); return new JScrollPane(table, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
} }
@ -78,6 +83,32 @@ public class RunRecordsPanel extends JPanel {
JButton generateRandomDataButton = new JButton("Generate Random Data"); JButton generateRandomDataButton = new JButton("Generate Random Data");
generateRandomDataButton.addActionListener(e -> generateRandomData()); generateRandomDataButton.addActionListener(e -> generateRandomData());
actionsPanel.add(generateRandomDataButton); actionsPanel.add(generateRandomDataButton);
deleteRecordButton.addActionListener(e -> {
long id = tableModel.getRecordIdAtRow(table.getSelectedRow());
if (id != -1) {
int result = JOptionPane.showConfirmDialog(
this,
"Are you sure you want to delete this record? This is permanent.",
"Confirm Deletion",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE
);
if (result == JOptionPane.OK_OPTION) {
try {
dataSource.runRecords().delete(id);
} catch (SQLException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(
this,
"An SQL Exception occurred: " + ex.getMessage(),
"Error",
JOptionPane.ERROR_MESSAGE
);
}
}
}
});
actionsPanel.add(deleteRecordButton);
return actionsPanel; return actionsPanel;
} }

View File

@ -4,5 +4,5 @@ import java.awt.*;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
public interface ChartRenderer { public interface ChartRenderer {
void render(Graphics2D graphics, Rectangle2D area); void render(Graphics2D graphics, Rectangle2D area, float textScale);
} }

View File

@ -23,7 +23,7 @@ public class ChartRenderingPanel extends JPanel implements Consumer<ChartRendere
if (renderer != null) { if (renderer != null) {
Graphics2D g2 = (Graphics2D) g; Graphics2D g2 = (Graphics2D) g;
Rectangle2D area = new Rectangle2D.Float(0, 0, this.getWidth(), this.getHeight()); Rectangle2D area = new Rectangle2D.Float(0, 0, this.getWidth(), this.getHeight());
renderer.render(g2, area); renderer.render(g2, area, 1);
} else { } else {
g.drawString("No chart to render", 50, 50); g.drawString("No chart to render", 50, 50);
} }

View File

@ -73,7 +73,7 @@ public class DateSeriesChartRenderer extends JFreeChartRenderer {
} }
@Override @Override
protected void applyCustomStyles(JFreeChart chart) { protected void applyCustomStyles(JFreeChart chart, float textScale) {
applyStandardXYLineColor(chart, linePaint); applyStandardXYLineColor(chart, linePaint, textScale);
} }
} }

View File

@ -18,6 +18,7 @@ public class ExportChartImageDialog extends JDialog {
private final SpinnerNumberModel widthSpinnerModel = new SpinnerNumberModel(1920, 10, 10000, 1); private final SpinnerNumberModel widthSpinnerModel = new SpinnerNumberModel(1920, 10, 10000, 1);
private final SpinnerNumberModel heightSpinnerModel = new SpinnerNumberModel(1080, 10, 10000, 1); private final SpinnerNumberModel heightSpinnerModel = new SpinnerNumberModel(1080, 10, 10000, 1);
private final SpinnerNumberModel textScaleSpinnerModel = new SpinnerNumberModel(1.0, 0.01, 25.0, 0.01);
private final JTextField filePathField = new JTextField(); private final JTextField filePathField = new JTextField();
private Path currentFilePath = Path.of(".").toAbsolutePath().resolve("chart.png"); private Path currentFilePath = Path.of(".").toAbsolutePath().resolve("chart.png");
@ -39,8 +40,10 @@ public class ExportChartImageDialog extends JDialog {
c.gridy = 1; c.gridy = 1;
formPanel.add(new JLabel("Height (px)"), c); formPanel.add(new JLabel("Height (px)"), c);
c.gridy = 2; c.gridy = 2;
formPanel.add(new JLabel("File"), c); formPanel.add(new JLabel("Text Scale"), c);
c.gridy = 3; c.gridy = 3;
formPanel.add(new JLabel("File"), c);
c.gridy = 4;
JButton selectFileButton = new JButton("Select File"); JButton selectFileButton = new JButton("Select File");
selectFileButton.addActionListener(e -> browseForFilePath()); selectFileButton.addActionListener(e -> browseForFilePath());
formPanel.add(selectFileButton, c); formPanel.add(selectFileButton, c);
@ -57,8 +60,12 @@ public class ExportChartImageDialog extends JDialog {
JSpinner heightSpinner = new JSpinner(heightSpinnerModel); JSpinner heightSpinner = new JSpinner(heightSpinnerModel);
heightSpinner.setLocale(Locale.US); heightSpinner.setLocale(Locale.US);
formPanel.add(heightSpinner, c); formPanel.add(heightSpinner, c);
c.gridy = 2; c.gridy = 2;
JSpinner textScaleSpinner = new JSpinner(textScaleSpinnerModel);
textScaleSpinner.setLocale(Locale.US);
formPanel.add(textScaleSpinner, c);
c.gridy = 3;
filePathField.setEditable(false); filePathField.setEditable(false);
filePathField.setText(currentFilePath.toAbsolutePath().toString()); filePathField.setText(currentFilePath.toAbsolutePath().toString());
filePathField.addMouseListener(new MouseAdapter() { filePathField.addMouseListener(new MouseAdapter() {
@ -110,8 +117,9 @@ public class ExportChartImageDialog extends JDialog {
} }
int width = (int) widthSpinnerModel.getValue(); int width = (int) widthSpinnerModel.getValue();
int height = (int) heightSpinnerModel.getValue(); int height = (int) heightSpinnerModel.getValue();
double textScale = (Double) textScaleSpinnerModel.getValue();
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
chartRenderer.render(img.createGraphics(), new Rectangle2D.Float(0, 0, width, height)); chartRenderer.render(img.createGraphics(), new Rectangle2D.Float(0, 0, width, height), (float) textScale);
try { try {
ImageIO.write(img, "png", currentFilePath.toFile()); ImageIO.write(img, "png", currentFilePath.toFile());
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(

View File

@ -4,6 +4,7 @@ import com.github.andrewlalis.running_every_day.Resources;
import org.jfree.chart.ChartTheme; import org.jfree.chart.ChartTheme;
import org.jfree.chart.JFreeChart; import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme; import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import java.awt.*; import java.awt.*;
@ -12,23 +13,27 @@ import java.io.IOException;
public abstract class JFreeChartRenderer implements ChartRenderer { public abstract class JFreeChartRenderer implements ChartRenderer {
private JFreeChart lastChart = null; private JFreeChart lastChart = null;
public static final ChartTheme standardChartTheme = getChartTheme();
private final StandardChartTheme standardChartTheme = getChartTheme();
private static final float SMALL_FONT_BASE_SIZE = 10;
private static final float REGULAR_FONT_BASE_SIZE = 12;
private static final float LARGE_FONT_BASE_SIZE = 18;
private static final float EXTRA_LARGE_FONT_BASE_SIZE = 30;
protected abstract JFreeChart getChart() throws Exception; protected abstract JFreeChart getChart() throws Exception;
protected void applyCustomStyles(JFreeChart chart) {} protected void applyCustomStyles(JFreeChart chart, float textScale) {}
public void refresh() throws Exception {
lastChart = getChart();
standardChartTheme.apply(lastChart);
applyCustomStyles(lastChart);
}
@Override @Override
public void render(Graphics2D graphics, Rectangle2D area) { public void render(Graphics2D graphics, Rectangle2D area, float textScale) {
if (textScale < 0) textScale = 1;
try { try {
if (lastChart == null) { if (lastChart == null) {
refresh(); lastChart = getChart();
} }
setThemeTextScale(textScale);
standardChartTheme.apply(lastChart);
applyCustomStyles(lastChart, textScale);
lastChart.draw(graphics, area); lastChart.draw(graphics, area);
} catch (Exception e) { } catch (Exception e) {
graphics.setColor(Color.RED); graphics.setColor(Color.RED);
@ -39,7 +44,7 @@ public abstract class JFreeChartRenderer implements ChartRenderer {
} }
} }
private static ChartTheme getChartTheme() { private static StandardChartTheme getChartTheme() {
StandardChartTheme theme = new StandardChartTheme("Standard Theme"); StandardChartTheme theme = new StandardChartTheme("Standard Theme");
Font baseFont = Font.getFont("sans-serif"); Font baseFont = Font.getFont("sans-serif");
Font lightFont = Font.getFont("sans-serif"); Font lightFont = Font.getFont("sans-serif");
@ -49,10 +54,10 @@ public abstract class JFreeChartRenderer implements ChartRenderer {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
theme.setSmallFont(baseFont.deriveFont(10f)); theme.setSmallFont(baseFont);
theme.setRegularFont(baseFont.deriveFont(12f)); theme.setRegularFont(baseFont);
theme.setLargeFont(lightFont.deriveFont(18f)); theme.setLargeFont(lightFont);
theme.setExtraLargeFont(lightFont.deriveFont(30f)); theme.setExtraLargeFont(lightFont);
theme.setChartBackgroundPaint(Color.WHITE); theme.setChartBackgroundPaint(Color.WHITE);
theme.setPlotBackgroundPaint(Color.WHITE); theme.setPlotBackgroundPaint(Color.WHITE);
@ -62,10 +67,29 @@ public abstract class JFreeChartRenderer implements ChartRenderer {
return theme; return theme;
} }
protected static void applyStandardXYLineColor(JFreeChart chart, Paint paint) { private void setThemeTextScale(float scale) {
standardChartTheme.setSmallFont(standardChartTheme.getSmallFont().deriveFont(scale * SMALL_FONT_BASE_SIZE));
standardChartTheme.setRegularFont(standardChartTheme.getRegularFont().deriveFont(scale * REGULAR_FONT_BASE_SIZE));
standardChartTheme.setLargeFont(standardChartTheme.getLargeFont().deriveFont(scale * LARGE_FONT_BASE_SIZE));
standardChartTheme.setExtraLargeFont(standardChartTheme.getExtraLargeFont().deriveFont(scale * EXTRA_LARGE_FONT_BASE_SIZE));
}
protected static void applyStandardXYLineColor(JFreeChart chart, Paint paint, float textScale) {
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) chart.getXYPlot().getRenderer(); XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) chart.getXYPlot().getRenderer();
renderer.setSeriesPaint(0, paint); renderer.setSeriesPaint(0, paint);
renderer.setSeriesShapesVisible(0, false); renderer.setSeriesShapesVisible(0, false);
renderer.setSeriesStroke(0, new BasicStroke(3)); renderer.setSeriesStroke(0, new BasicStroke(3 * textScale));
XYPlot plot = chart.getXYPlot();
BasicStroke stroke = new BasicStroke(
textScale,
BasicStroke.CAP_SQUARE,
BasicStroke.JOIN_MITER,
1,
new float[]{2 * textScale, 2 * textScale},
0
);
plot.setDomainGridlineStroke(stroke);
plot.setRangeGridlineStroke(stroke);
} }
} }