Added build script and more stuff
This commit is contained in:
parent
6b839349fb
commit
22c1fb6d74
|
@ -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
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue