diff --git a/src/main/java/ovh/gasser/newshapes/App.java b/src/main/java/ovh/gasser/newshapes/App.java
index 4424097..e9d872b 100644
--- a/src/main/java/ovh/gasser/newshapes/App.java
+++ b/src/main/java/ovh/gasser/newshapes/App.java
@@ -15,7 +15,6 @@ import ovh.gasser.newshapes.ui.listeners.SelectionListener;
import javax.swing.*;
import java.awt.*;
import java.io.FileNotFoundException;
-import java.util.Optional;
public class App {
private final static Logger logger = LoggerFactory.getLogger(App.class);
@@ -82,6 +81,7 @@ public class App {
JMenuItem addRectItem = new JMenuItem("Add SRectangle");
JMenuItem addCircleItem = new JMenuItem("Add SCircle");
JMenuItem htmlExportItem = new JMenuItem("Export to HTML");
+ JMenuItem svgExportItem = new JMenuItem("Export to SVG");
JMenuItem exitItem = new JMenuItem("Exit");
addRectItem.addActionListener(new MenuAddListener("SRectangle", model, sview));
addCircleItem.addActionListener(new MenuAddListener("SCircle", model, sview));
@@ -92,11 +92,19 @@ public class App {
logger.error("Could not export as html: {}", e.getMessage());
}
});
+ svgExportItem.addActionListener(evt -> {
+ try {
+ new SVGExporter(model).export();
+ } catch (FileNotFoundException e) {
+ logger.error("Could not export as html: {}", e.getMessage());
+ }
+ });
exitItem.addActionListener(evt -> System.exit(0));
menuFile.add(addRectItem);
menuFile.add(addCircleItem);
menuFile.addSeparator();
menuFile.add(htmlExportItem);
+ menuFile.add(svgExportItem);
menuFile.add(exitItem);
return menuFile;
}
diff --git a/src/main/java/ovh/gasser/newshapes/HTMLExporter.java b/src/main/java/ovh/gasser/newshapes/HTMLExporter.java
index c24f3d2..6d53dfb 100644
--- a/src/main/java/ovh/gasser/newshapes/HTMLExporter.java
+++ b/src/main/java/ovh/gasser/newshapes/HTMLExporter.java
@@ -2,7 +2,7 @@ package ovh.gasser.newshapes;
import ovh.gasser.newshapes.shapes.SCollection;
import ovh.gasser.newshapes.shapes.SRectangle;
-import ovh.gasser.newshapes.ui.html.*;
+import ovh.gasser.newshapes.ui.visitors.*;
import java.awt.*;
import java.io.FileNotFoundException;
@@ -12,7 +12,7 @@ public class HTMLExporter {
private final SCollection model;
- private HTMLExporter() throws FileNotFoundException {
+ private HTMLExporter() {
this(SCollection.of(
SRectangle.create(10, 10, 40, 60, Color.RED),
SRectangle.create(70, 10, 40, 60),
diff --git a/src/main/java/ovh/gasser/newshapes/SVGExporter.java b/src/main/java/ovh/gasser/newshapes/SVGExporter.java
new file mode 100644
index 0000000..1b2ce58
--- /dev/null
+++ b/src/main/java/ovh/gasser/newshapes/SVGExporter.java
@@ -0,0 +1,36 @@
+package ovh.gasser.newshapes;
+
+import ovh.gasser.newshapes.attributes.ColorAttributes;
+import ovh.gasser.newshapes.shapes.SCircle;
+import ovh.gasser.newshapes.shapes.SCollection;
+import ovh.gasser.newshapes.ui.visitors.SVGDraftman;
+
+import java.awt.*;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+
+public class SVGExporter {
+
+ private final SCollection model;
+
+ public SVGExporter() {
+ SCircle circle = SCircle.create(200, 100, 50);
+ circle.addAttributes(new ColorAttributes(true, true, Color.LIGHT_GRAY, Color.BLACK));
+ this.model = SCollection.of(circle);
+ }
+
+ public SVGExporter(SCollection model) {
+ this.model = model;
+ }
+
+ public void export() throws FileNotFoundException {
+ try (final PrintWriter svg = new PrintWriter("out.svg")) {
+ SVGDraftman draftman = new SVGDraftman(svg);
+ draftman.generateSVG(this.model);
+ }
+ }
+
+ public static void main(String[] args) throws FileNotFoundException {
+ new SVGExporter().export();
+ }
+}
diff --git a/src/main/java/ovh/gasser/newshapes/ui/html/HTMLDraftman.java b/src/main/java/ovh/gasser/newshapes/ui/visitors/HTMLDraftman.java
similarity index 98%
rename from src/main/java/ovh/gasser/newshapes/ui/html/HTMLDraftman.java
rename to src/main/java/ovh/gasser/newshapes/ui/visitors/HTMLDraftman.java
index 062a47f..637da66 100644
--- a/src/main/java/ovh/gasser/newshapes/ui/html/HTMLDraftman.java
+++ b/src/main/java/ovh/gasser/newshapes/ui/visitors/HTMLDraftman.java
@@ -1,4 +1,4 @@
-package ovh.gasser.newshapes.ui.html;
+package ovh.gasser.newshapes.ui.visitors;
import ovh.gasser.newshapes.ShapeVisitor;
import ovh.gasser.newshapes.attributes.ColorAttributes;
diff --git a/src/main/java/ovh/gasser/newshapes/ui/visitors/SVGDraftman.java b/src/main/java/ovh/gasser/newshapes/ui/visitors/SVGDraftman.java
new file mode 100644
index 0000000..202ce81
--- /dev/null
+++ b/src/main/java/ovh/gasser/newshapes/ui/visitors/SVGDraftman.java
@@ -0,0 +1,82 @@
+package ovh.gasser.newshapes.ui.visitors;
+
+import ovh.gasser.newshapes.App;
+import ovh.gasser.newshapes.ShapeVisitor;
+import ovh.gasser.newshapes.attributes.ColorAttributes;
+import ovh.gasser.newshapes.shapes.SCircle;
+import ovh.gasser.newshapes.shapes.SCollection;
+import ovh.gasser.newshapes.shapes.SRectangle;
+
+import java.awt.*;
+import java.io.PrintWriter;
+
+public class SVGDraftman implements ShapeVisitor {
+ private static final String SVG_PRELUDE = """
+
+ ";
+
+ private final PrintWriter output;
+
+ public SVGDraftman(PrintWriter output) {
+ this.output = output;
+ }
+
+ @Override
+ public void visitRectangle(SRectangle sRectangle) {
+ int x = sRectangle.getBounds().x;
+ int y = sRectangle.getBounds().y;
+ int w = sRectangle.getBounds().width;
+ int h = sRectangle.getBounds().height;
+ ColorAttributes attrs = (ColorAttributes) sRectangle.getAttributes(ColorAttributes.ID);
+ this.output.println(String.format("""
+ """,
+ w, h, x, y, buildColorParameters(attrs)));
+ }
+
+ @Override
+ public void visitCollection(SCollection collection) {
+ collection.stream().forEach(shape -> shape.accept(this));
+ }
+
+ @Override
+ public void visitCircle(SCircle sCircle) {
+ int r = sCircle.getRadius();
+ int x = sCircle.getBounds().x + r;
+ int y = sCircle.getBounds().y + r;
+ var attrs = (ColorAttributes) sCircle.getAttributes(ColorAttributes.ID);
+ this.output.println(String.format("""
+ """,
+ x, y, r, buildColorParameters(attrs)));
+ }
+
+ public void generateSVG(SCollection model) {
+ output.println(String.format(SVG_PRELUDE, App.WIN_SIZE.width, App.WIN_SIZE.height));
+ visitCollection(model);
+ output.println(SVG_POSTLUDE);
+ }
+
+ private String colorToHex(Color c) {
+ int r = c.getRed();
+ int g = c.getGreen();
+ int b = c.getBlue();
+ return String.format("#%02x%02x%02x", r, g, b);
+ }
+
+ private StringBuilder buildColorParameters(ColorAttributes attrs){
+ var params = new StringBuilder();
+ if (attrs.stroked) {
+ params.append(String.format("stroke=\"%s\" stroke-width=\"1\"", colorToHex(attrs.strokedColor)));
+ params.append(" ");
+ }
+ if (attrs.filled) {
+ params.append(String.format("fill=\"%s\"", colorToHex(attrs.filledColor)));
+ params.append(" ");
+ } else {
+ params.append(String.format("fill=\"%s\"", "none"));
+ params.append(" ");
+ }
+ return params;
+ }
+}