saving JSON plus PNG preview
This commit is contained in:
parent
ad7562e3d2
commit
0eb53de222
@ -1,5 +1,6 @@
|
||||
package de.ph87.electro;
|
||||
|
||||
import de.ph87.electro.circuit.CircuitIOService;
|
||||
import de.ph87.electro.circuit.CircuitPanel;
|
||||
import de.ph87.electro.sidebar.Sidebar;
|
||||
|
||||
@ -17,7 +18,7 @@ public class Window extends JFrame {
|
||||
setExtendedState(MAXIMIZED_BOTH);
|
||||
|
||||
final CircuitPanel circuitPanel = new CircuitPanel();
|
||||
final Sidebar sidebar = new Sidebar(circuitPanel::newCircuit, circuitPanel::save);
|
||||
final Sidebar sidebar = new Sidebar(circuitPanel::newCircuit, () -> CircuitIOService.save(circuitPanel.getCircuit()));
|
||||
final JSplitPane splitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, sidebar, circuitPanel);
|
||||
|
||||
sidebar.setRepaintCallback(circuitPanel::repaint);
|
||||
|
||||
@ -9,11 +9,9 @@ import de.ph87.electro.circuit.wire.Wire;
|
||||
import de.ph87.electro.circuit.wire.WireDto;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
@ -21,9 +19,6 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static de.ph87.electro.circuit.CircuitIOService.write;
|
||||
|
||||
@Slf4j
|
||||
public class Circuit {
|
||||
|
||||
@Getter
|
||||
@ -34,13 +29,19 @@ public class Circuit {
|
||||
|
||||
private final List<Wire> wires = new ArrayList<>();
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
private boolean dirty = false;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
private File file = null;
|
||||
|
||||
public Circuit() {
|
||||
this.created = ZonedDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
|
||||
}
|
||||
|
||||
public Circuit(final CircuitDto dto) {
|
||||
public Circuit(final File file, final CircuitDto dto) {
|
||||
created = dto.getCreated();
|
||||
for (PartDto partDto : dto.getParts()) {
|
||||
final Part part = Part.of(this, partDto);
|
||||
@ -96,22 +97,6 @@ public class Circuit {
|
||||
parts.forEach(Part::render);
|
||||
}
|
||||
|
||||
public void save() {
|
||||
if (!dirty) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final File file = new File("./data/%s.json".formatted(created));
|
||||
if (file.getParentFile().mkdirs()) {
|
||||
log.info("Directory created: {}", file.getParent());
|
||||
}
|
||||
write(this, new FileOutputStream(file));
|
||||
dirty = false;
|
||||
} catch (IOException e) {
|
||||
log.error(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyFree(final Position position) {
|
||||
if (parts.stream().anyMatch(part -> part.getPosition().equals(position))) {
|
||||
throw new RuntimeException();
|
||||
@ -146,4 +131,11 @@ public class Circuit {
|
||||
return wires.stream().filter(wire -> wire.intersects(position)).findFirst();
|
||||
}
|
||||
|
||||
public File getPreviewFile() {
|
||||
if (file == null) {
|
||||
return null;
|
||||
}
|
||||
return new File(file.getAbsolutePath().replaceAll("\\.json$", ".png"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,21 +1,55 @@
|
||||
package de.ph87.electro.circuit;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
|
||||
import static de.ph87.electro.circuit.CircuitPainter.paintCircuit;
|
||||
|
||||
@Slf4j
|
||||
public class CircuitIOService {
|
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules();
|
||||
|
||||
public static void write(final Circuit circuit, final OutputStream stream) throws IOException {
|
||||
public static void save(final Circuit circuit) {
|
||||
if (!circuit.isDirty()) {
|
||||
return;
|
||||
}
|
||||
if (circuit.getFile() == null) {
|
||||
circuit.setFile(new File("./data/%s.json".formatted(circuit.getCreated())));
|
||||
}
|
||||
try {
|
||||
if (circuit.getFile().getParentFile().mkdirs()) {
|
||||
log.info("Directory created: {}", circuit.getFile().getParent());
|
||||
}
|
||||
CircuitIOService.serialize(circuit, new FileOutputStream(circuit.getFile()));
|
||||
circuit.setDirty(false);
|
||||
} catch (IOException e) {
|
||||
log.error(e.toString());
|
||||
}
|
||||
|
||||
final BufferedImage img = paintCircuit(circuit, 1920, 1080);
|
||||
try {
|
||||
ImageIO.write(img, "PNG", circuit.getPreviewFile());
|
||||
} catch (IOException e) {
|
||||
log.error(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static Circuit load(final File file) throws IOException {
|
||||
return load(null, new FileInputStream(file));
|
||||
}
|
||||
|
||||
public static Circuit load(final File file, final InputStream stream) throws IOException {
|
||||
final CircuitDto dto = objectMapper.readValue(stream, CircuitDto.class);
|
||||
return new Circuit(file, dto);
|
||||
}
|
||||
|
||||
public static void serialize(final Circuit circuit, final OutputStream stream) throws IOException {
|
||||
objectMapper.writeValue(stream, new CircuitDto(circuit));
|
||||
}
|
||||
|
||||
public static Circuit read(final InputStream stream) throws IOException {
|
||||
return new Circuit(objectMapper.readValue(stream, CircuitDto.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
86
src/main/java/de/ph87/electro/circuit/CircuitPainter.java
Normal file
86
src/main/java/de/ph87/electro/circuit/CircuitPainter.java
Normal file
@ -0,0 +1,86 @@
|
||||
package de.ph87.electro.circuit;
|
||||
|
||||
import de.ph87.electro.circuit.part.Part;
|
||||
import de.ph87.electro.circuit.part.junction.Junction;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import static de.ph87.electro.CONFIG.*;
|
||||
|
||||
public class CircuitPainter {
|
||||
|
||||
public static BufferedImage paintCircuit(final Circuit circuit, final int w, final int h) {
|
||||
final BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
|
||||
final Graphics2D g = img.createGraphics();
|
||||
paintCircuit(circuit, g, w, h);
|
||||
return img;
|
||||
}
|
||||
|
||||
public static void paintCircuit(final Circuit circuit, final Graphics2D g, final int w, final int h) {
|
||||
drawBack(g, w, h);
|
||||
drawParts(circuit, g);
|
||||
drawRaster(g, w, h);
|
||||
drawWires(circuit, g);
|
||||
drawVoltages(circuit, g);
|
||||
}
|
||||
|
||||
private static void drawBack(final Graphics2D g, final int w, final int h) {
|
||||
g.setColor(Color.white);
|
||||
g.fillRect(0, 0, w, h);
|
||||
}
|
||||
|
||||
private static void drawParts(final Circuit circuit, final Graphics2D g) {
|
||||
circuit.streamParts().forEach(part -> part.paint(g));
|
||||
}
|
||||
|
||||
private static void drawRaster(final Graphics2D g, final int w, final int h) {
|
||||
g.setStroke(RASTER_STROKE);
|
||||
g.setColor(RASTER_COLOR);
|
||||
for (int x = 0; x < w; x += RASTER) {
|
||||
g.drawLine(x, 0, x, h);
|
||||
}
|
||||
for (int y = 0; y < h; y += RASTER) {
|
||||
g.drawLine(0, y, w, y);
|
||||
}
|
||||
}
|
||||
|
||||
private static void drawWires(final Circuit circuit, final Graphics2D g) {
|
||||
circuit.streamWires().forEach(wire -> wire.draw(g));
|
||||
}
|
||||
|
||||
private static void drawVoltages(final Circuit circuit, final Graphics2D g) {
|
||||
if (!SHOW_JUNCTION_VOLTAGES && !SHOW_JUNCTION_NAMES) {
|
||||
return;
|
||||
}
|
||||
|
||||
g.setColor(Color.BLACK);
|
||||
g.setFont(LABEL_FONT);
|
||||
final int third = g.getFont().getSize() / 3;
|
||||
|
||||
for (Part part : circuit.getParts()) {
|
||||
for (final Junction junction : part.getJunctions()) {
|
||||
if (SHOW_JUNCTION_NAMES) {
|
||||
int offsetY = third;
|
||||
if (SHOW_JUNCTION_VOLTAGES) {
|
||||
offsetY -= third;
|
||||
}
|
||||
final String string = junction.getName();
|
||||
final Rectangle2D bounds = g.getFontMetrics().getStringBounds(string, g);
|
||||
g.drawString(string, junction.getPosition().absolute.x - (int) (bounds.getWidth() / 2), junction.getPosition().absolute.y + offsetY);
|
||||
}
|
||||
if (SHOW_JUNCTION_VOLTAGES) {
|
||||
int offsetY = third;
|
||||
if (SHOW_JUNCTION_NAMES) {
|
||||
offsetY += 2 * third;
|
||||
}
|
||||
final String string = "%.1fV".formatted(junction.getVoltage());
|
||||
final Rectangle2D bounds = g.getFontMetrics().getStringBounds(string, g);
|
||||
g.drawString(string, junction.getPosition().absolute.x - (int) (bounds.getWidth() / 2), junction.getPosition().absolute.y + offsetY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,7 +1,5 @@
|
||||
package de.ph87.electro.circuit;
|
||||
|
||||
import de.ph87.electro.circuit.part.Part;
|
||||
import de.ph87.electro.circuit.part.junction.Junction;
|
||||
import de.ph87.electro.circuit.part.parts.Battery;
|
||||
import de.ph87.electro.circuit.part.parts.Light;
|
||||
import lombok.Getter;
|
||||
@ -9,9 +7,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
import static de.ph87.electro.CONFIG.*;
|
||||
import static de.ph87.electro.circuit.CircuitPainter.paintCircuit;
|
||||
import static de.ph87.electro.circuit.part.Position.RST;
|
||||
|
||||
@Slf4j
|
||||
@ -34,81 +31,14 @@ public class CircuitPanel extends JPanel {
|
||||
@Override
|
||||
public void paint(final Graphics _g) {
|
||||
final Graphics2D g = (Graphics2D) _g;
|
||||
final int w = getWidth();
|
||||
final int h = getHeight();
|
||||
drawBack(g, w, h);
|
||||
drawParts(g);
|
||||
drawRaster(g, w, h);
|
||||
drawWires(g);
|
||||
drawVoltages(g);
|
||||
paintCircuit(circuit, g, getWidth(), getHeight());
|
||||
mouseAdapter.drawHover(g);
|
||||
mouseAdapter.drawDrag(g);
|
||||
}
|
||||
|
||||
private void drawBack(final Graphics2D g, final int w, final int h) {
|
||||
g.setColor(Color.white);
|
||||
g.fillRect(0, 0, w, h);
|
||||
}
|
||||
|
||||
private void drawParts(final Graphics2D g) {
|
||||
circuit.streamParts().forEach(part -> part.paint(g));
|
||||
}
|
||||
|
||||
private void drawRaster(final Graphics2D g, final int w, final int h) {
|
||||
g.setStroke(RASTER_STROKE);
|
||||
g.setColor(RASTER_COLOR);
|
||||
for (int x = 0; x < w; x += RASTER) {
|
||||
g.drawLine(x, 0, x, h);
|
||||
}
|
||||
for (int y = 0; y < h; y += RASTER) {
|
||||
g.drawLine(0, y, w, y);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawWires(final Graphics2D g) {
|
||||
circuit.streamWires().forEach(wire -> wire.draw(g));
|
||||
}
|
||||
|
||||
private void drawVoltages(final Graphics2D g) {
|
||||
if (!SHOW_JUNCTION_VOLTAGES && !SHOW_JUNCTION_NAMES) {
|
||||
return;
|
||||
}
|
||||
|
||||
g.setColor(Color.BLACK);
|
||||
g.setFont(LABEL_FONT);
|
||||
final int third = g.getFont().getSize() / 3;
|
||||
|
||||
for (Part part : circuit.getParts()) {
|
||||
for (final Junction junction : part.getJunctions()) {
|
||||
if (SHOW_JUNCTION_NAMES) {
|
||||
int offsetY = third;
|
||||
if (SHOW_JUNCTION_VOLTAGES) {
|
||||
offsetY -= third;
|
||||
}
|
||||
final String string = junction.getName();
|
||||
final Rectangle2D bounds = g.getFontMetrics().getStringBounds(string, g);
|
||||
g.drawString(string, junction.getPosition().absolute.x - (int) (bounds.getWidth() / 2), junction.getPosition().absolute.y + offsetY);
|
||||
}
|
||||
if (SHOW_JUNCTION_VOLTAGES) {
|
||||
int offsetY = third;
|
||||
if (SHOW_JUNCTION_NAMES) {
|
||||
offsetY += 2 * third;
|
||||
}
|
||||
final String string = "%.1fV".formatted(junction.getVoltage());
|
||||
final Rectangle2D bounds = g.getFontMetrics().getStringBounds(string, g);
|
||||
g.drawString(string, junction.getPosition().absolute.x - (int) (bounds.getWidth() / 2), junction.getPosition().absolute.y + offsetY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void newCircuit() {
|
||||
circuit = new Circuit();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void save() {
|
||||
circuit.save();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package de.ph87.electro.circuit.io;
|
||||
|
||||
import de.ph87.electro.circuit.Circuit;
|
||||
import de.ph87.electro.circuit.CircuitIOService;
|
||||
import de.ph87.electro.circuit.part.Part;
|
||||
import de.ph87.electro.circuit.part.junction.Junction;
|
||||
import de.ph87.electro.circuit.part.parts.Battery;
|
||||
@ -12,8 +13,7 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static de.ph87.electro.circuit.CircuitIOService.read;
|
||||
import static de.ph87.electro.circuit.CircuitIOService.write;
|
||||
import static de.ph87.electro.circuit.CircuitIOService.serialize;
|
||||
import static de.ph87.electro.circuit.part.Position.RST;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@ -31,12 +31,12 @@ class CircuitIOServiceTest {
|
||||
|
||||
private void check(final Circuit original) throws IOException {
|
||||
final ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
write(original, output);
|
||||
serialize(original, output);
|
||||
|
||||
System.out.println(output.toString(StandardCharsets.UTF_8));
|
||||
|
||||
final ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
|
||||
final Circuit reloaded = read(input);
|
||||
final Circuit reloaded = CircuitIOService.load(null, input);
|
||||
|
||||
assertEquals(original.getCreated(), reloaded.getCreated());
|
||||
assertEquals(original.getPartCount(), reloaded.getPartCount());
|
||||
|
||||
Loading…
Reference in New Issue
Block a user