Drawing API cleanup

This commit is contained in:
Patrick Haßel 2023-02-27 11:20:47 +01:00
parent cae3f0b2cf
commit 7cc298638c
5 changed files with 42 additions and 40 deletions

View File

@ -8,7 +8,7 @@ import lombok.Getter;
@Getter @Getter
public class Environment { public class Environment {
private final Publisher<Drawing> onNewDrawing = new Publisher<>(); private final Publisher<Drawing> onDrawingChange = new Publisher<>();
private final Tools tools = new Tools(); private final Tools tools = new Tools();
@ -19,8 +19,8 @@ public class Environment {
} }
public void newDrawing() { public void newDrawing() {
drawing = new Drawing(1920, 1080); drawing = new Drawing(1920, 1080, onDrawingChange::publish);
onNewDrawing.publish(drawing); onDrawingChange.publish(drawing);
} }
} }

View File

@ -1,5 +1,6 @@
package de.ph87.kindermalen.drawing; package de.ph87.kindermalen.drawing;
import lombok.Getter;
import lombok.ToString; import lombok.ToString;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -10,6 +11,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.function.Consumer;
@Slf4j @Slf4j
@ToString @ToString
@ -19,41 +21,37 @@ public class Drawing {
public final int height; public final int height;
private final Consumer<Drawing> onChange;
public final ZonedDateTime created = ZonedDateTime.now(); public final ZonedDateTime created = ZonedDateTime.now();
@Getter
@ToString.Exclude @ToString.Exclude
private final Layer current; private final Layer layer;
public Drawing(final int width, final int height) { public Drawing(final int width, final int height, final Consumer<Drawing> onChange) {
this.width = width; this.width = width;
this.height = height; this.height = height;
current = new Layer(width, height); this.onChange = onChange;
layer = new Layer(width, height, l -> onChange.accept(this));
log.info("New Drawing: {}", this); log.info("New Drawing: {}", this);
} }
public Graphics2D getGraphics() {
return (Graphics2D) current.getCurrent().getGraphics();
}
public void publish() {
current.publish();
}
public void undo() { public void undo() {
current.undo(); layer.undo();
} }
public void redo() { public void redo() {
current.redo(); layer.redo();
} }
public void newRevision() { public void newRevision() {
current.newRevision(); layer.newRevision();
} }
public void save(final File dir) throws IOException { public void save(final File dir) throws IOException {
final int revision = current.getRevision(); final int revision = layer.getRevision();
final BufferedImage image = current.getCurrent(); final BufferedImage image = layer.getBuffer();
final File subdir = new File(dir, created.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); final File subdir = new File(dir, created.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
final File file = new File(subdir, "%05d".formatted(revision) + ".png"); final File file = new File(subdir, "%05d".formatted(revision) + ".png");
if (subdir.mkdirs()) { if (subdir.mkdirs()) {
@ -69,7 +67,7 @@ public class Drawing {
} }
public Image getImage() { public Image getImage() {
return current.getCurrent(); return layer.getBuffer();
} }
} }

View File

@ -37,7 +37,7 @@ public class DrawingPanel extends MyComponent {
public DrawingPanel(final Environment environment) { public DrawingPanel(final Environment environment) {
this.environment = environment; this.environment = environment;
subscribe(environment.getTools().getOnSelect(), this::onToolSelect); subscribe(environment.getTools().getOnSelect(), this::onToolSelect);
subscribe(environment.getOnNewDrawing(), drawing -> repaint()); subscribe(environment.getOnDrawingChange(), drawing -> repaint());
} }
private void onToolSelect(final Tool tool) { private void onToolSelect(final Tool tool) {

View File

@ -1,12 +1,13 @@
package de.ph87.kindermalen.drawing; package de.ph87.kindermalen.drawing;
import de.ph87.kindermalen.util.Publisher;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Consumer;
import static de.ph87.kindermalen.util.ImageHelper.COPY; import static de.ph87.kindermalen.util.ImageHelper.COPY;
@ -17,25 +18,25 @@ public class Layer {
private final int height; private final int height;
@Getter private final Consumer<Layer> onChange;
private BufferedImage current;
private List<BufferedImage> history = new ArrayList<>(); private List<BufferedImage> history = new ArrayList<>();
@Getter
private BufferedImage buffer;
@Getter @Getter
private int index = 0; private int index = 0;
@Getter @Getter
private int revision = 0; private int revision = 0;
@Getter public Layer(final int width, final int height, final Consumer<Layer> onChange) {
private final Publisher<BufferedImage> onChange = new Publisher<>();
public Layer(final int width, final int height) {
this.width = width; this.width = width;
this.height = height; this.height = height;
this.current = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); this.onChange = onChange;
this.history.add(current); this.buffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
this.history.add(buffer);
} }
public void newRevision() { public void newRevision() {
@ -45,19 +46,19 @@ public class Layer {
history = history.subList(0, keep); history = history.subList(0, keep);
log.info("{} Revisions deleted", old - keep); log.info("{} Revisions deleted", old - keep);
} }
current = COPY(current); buffer = COPY(buffer);
index = history.size(); index = history.size();
revision++; revision++;
history.add(current); history.add(buffer);
log.debug("Revision {} created", index); log.debug("Revision {} created", index);
} }
public void undo() { public void undo() {
if (index > 0) { if (index > 0) {
index--; index--;
current = history.get(index); buffer = history.get(index);
log.info("UNDO: Revision {} loaded", index); log.info("UNDO: Revision {} loaded", index);
publish(); onChange.accept(this);
} else { } else {
log.warn("No UNDO steps left."); log.warn("No UNDO steps left.");
} }
@ -66,9 +67,9 @@ public class Layer {
public void redo() { public void redo() {
if (canRedo()) { if (canRedo()) {
index++; index++;
current = history.get(index); buffer = history.get(index);
log.info("REDO: Revision {} loaded", index); log.info("REDO: Revision {} loaded", index);
publish(); onChange.accept(this);
} else { } else {
log.warn("No REDO steps left."); log.warn("No REDO steps left.");
} }
@ -78,8 +79,10 @@ public class Layer {
return index < history.size() - 1; return index < history.size() - 1;
} }
public void publish() { public void draw(final BufferedImage image, final int x, final int y) {
onChange.publish(current); final Graphics2D g = (Graphics2D) buffer.getGraphics();
g.drawImage(image, x, y, null);
onChange.accept(this);
} }
} }

View File

@ -96,8 +96,9 @@ public class StampTool extends Tool {
} }
private void apply(final Drawing drawing, final Vector point) { private void apply(final Drawing drawing, final Vector point) {
drawing.getGraphics().drawImage(prepared, point.intX() - prepared.getWidth() / 2, point.intY() - prepared.getHeight() / 2, null); final int x = point.intX() - prepared.getWidth() / 2;
drawing.publish(); final int y = point.intY() - prepared.getHeight() / 2;
drawing.getLayer().draw(prepared, x, y);
} }
@Override @Override