Base java event POC
This commit is contained in:
parent
95cb82d419
commit
51885d8c53
43
src/main/java/ovh/gasser/newshapes/App.java
Normal file
43
src/main/java/ovh/gasser/newshapes/App.java
Normal file
@ -0,0 +1,43 @@
|
||||
package ovh.gasser.newshapes;
|
||||
|
||||
import ovh.gasser.newshapes.shapes.SCollection;
|
||||
import ovh.gasser.newshapes.shapes.SRectangle;
|
||||
import ovh.gasser.newshapes.shapes.Shape;
|
||||
import ovh.gasser.newshapes.ui.ShapesView;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class App {
|
||||
|
||||
public static final Dimension WIN_SIZE = new Dimension(800, 600);
|
||||
private Shape model;
|
||||
|
||||
private App() throws HeadlessException {
|
||||
final JFrame frame = new JFrame("Reactive shapes");
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
buildModel();
|
||||
final ShapesView view = new ShapesView(this.model);
|
||||
view.setPreferredSize(WIN_SIZE);
|
||||
frame.getContentPane().add(view, BorderLayout.CENTER);
|
||||
frame.setContentPane(view);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private void buildModel() {
|
||||
model = SCollection.of(
|
||||
SRectangle.create(10, 10, 40, 60, Color.RED),
|
||||
SRectangle.create(70, 10, 40, 60),
|
||||
SCollection.of(
|
||||
SRectangle.create(100, 200, 40, 60, Color.MAGENTA),
|
||||
SRectangle.create(150, 200, 40, 60, Color.MAGENTA)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SwingUtilities.invokeLater(App::new);
|
||||
}
|
||||
|
||||
}
|
39
src/main/java/ovh/gasser/newshapes/HTMLExporter.java
Normal file
39
src/main/java/ovh/gasser/newshapes/HTMLExporter.java
Normal file
@ -0,0 +1,39 @@
|
||||
package ovh.gasser.newshapes;
|
||||
|
||||
import ovh.gasser.newshapes.shapes.SCollection;
|
||||
import ovh.gasser.newshapes.shapes.SRectangle;
|
||||
import ovh.gasser.newshapes.ui.html.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
public class HTMLExporter {
|
||||
|
||||
private final SCollection model;
|
||||
|
||||
private HTMLExporter() throws FileNotFoundException {
|
||||
model = SCollection.of(
|
||||
SRectangle.create(10, 10, 40, 60, Color.RED),
|
||||
SRectangle.create(70, 10, 40, 60),
|
||||
SCollection.of(
|
||||
SRectangle.create(100, 200, 40, 60, Color.MAGENTA),
|
||||
SRectangle.create(150, 200, 40, 60, Color.MAGENTA)
|
||||
)
|
||||
);
|
||||
export();
|
||||
}
|
||||
|
||||
private void export() throws FileNotFoundException {
|
||||
try (final PrintWriter html = new PrintWriter("out.html")) {
|
||||
try (final PrintWriter css = new PrintWriter("style.css")) {
|
||||
HTMLDraftman draftman = new HTMLDraftman(html, css);
|
||||
draftman.generateHTML(this.model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws FileNotFoundException {
|
||||
new HTMLExporter().export();
|
||||
}
|
||||
}
|
24
src/main/java/ovh/gasser/newshapes/Selection.java
Normal file
24
src/main/java/ovh/gasser/newshapes/Selection.java
Normal file
@ -0,0 +1,24 @@
|
||||
package ovh.gasser.newshapes;
|
||||
|
||||
import ovh.gasser.newshapes.attributes.SelectionAttributes;
|
||||
import ovh.gasser.newshapes.shapes.Shape;
|
||||
|
||||
public class Selection {
|
||||
|
||||
private final SelectionAttributes attributes;
|
||||
public final Shape shape;
|
||||
|
||||
public Selection(final Shape shape, boolean selected) {
|
||||
this(shape);
|
||||
attributes.selected = selected;
|
||||
}
|
||||
|
||||
private Selection(final Shape shape) {
|
||||
attributes = (SelectionAttributes) shape.getAttributes(SelectionAttributes.ID);
|
||||
this.shape = shape;
|
||||
}
|
||||
|
||||
public void unselect() {
|
||||
attributes.selected = false;
|
||||
}
|
||||
}
|
10
src/main/java/ovh/gasser/newshapes/ShapeVisitor.java
Normal file
10
src/main/java/ovh/gasser/newshapes/ShapeVisitor.java
Normal file
@ -0,0 +1,10 @@
|
||||
package ovh.gasser.newshapes;
|
||||
|
||||
import ovh.gasser.newshapes.shapes.SCollection;
|
||||
import ovh.gasser.newshapes.shapes.SRectangle;
|
||||
|
||||
public interface ShapeVisitor {
|
||||
void visitRectangle(SRectangle sRectangle);
|
||||
|
||||
void visitCollection(SCollection collection);
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package ovh.gasser.newshapes.attributes;
|
||||
|
||||
public interface Attributes {
|
||||
String getID();
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package ovh.gasser.newshapes.attributes;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class ColorAttributes implements Attributes {
|
||||
public static final String ID = "COLOR_ATTRS";
|
||||
public final boolean filled;
|
||||
public final boolean stroked;
|
||||
public final Color filledColor;
|
||||
public final Color strokedColor;
|
||||
|
||||
public ColorAttributes(boolean filled, boolean stroked, Color filledColor, Color strokedColor) {
|
||||
this.filled = filled;
|
||||
this.stroked = stroked;
|
||||
this.filledColor = filledColor;
|
||||
this.strokedColor = strokedColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ColorAttributes{" +
|
||||
"filled=" + filled +
|
||||
", stroked=" + stroked +
|
||||
", filledColor=" + filledColor +
|
||||
", strokedColor=" + strokedColor +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return ID;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package ovh.gasser.newshapes.attributes;
|
||||
|
||||
public class SelectionAttributes implements Attributes {
|
||||
public static final String ID = "SELECTION_ATTRS";
|
||||
public boolean selected;
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return ID;
|
||||
}
|
||||
}
|
51
src/main/java/ovh/gasser/newshapes/shapes/AbstractShape.java
Normal file
51
src/main/java/ovh/gasser/newshapes/shapes/AbstractShape.java
Normal file
@ -0,0 +1,51 @@
|
||||
package ovh.gasser.newshapes.shapes;
|
||||
|
||||
import ovh.gasser.newshapes.attributes.Attributes;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public abstract class AbstractShape implements Shape {
|
||||
|
||||
private Map<String, Attributes> attributes = new TreeMap<>();
|
||||
private Rectangle bounds;
|
||||
|
||||
AbstractShape() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
AbstractShape(Rectangle bounds) {
|
||||
this.bounds = bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attributes getAttributes(String key) {
|
||||
return attributes.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAttributes(Attributes attrs) {
|
||||
attributes.put(attrs.getID(), attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoc(Point newLoc) {
|
||||
getBounds().setLocation(newLoc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translate(int dx, int dy) {
|
||||
getBounds().translate(dx, dy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getBounds() {
|
||||
return this.bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("x=%d, y=%d, width=%d, height=%d", bounds.x, bounds.y, bounds.width, bounds.height);
|
||||
}
|
||||
}
|
65
src/main/java/ovh/gasser/newshapes/shapes/SCollection.java
Normal file
65
src/main/java/ovh/gasser/newshapes/shapes/SCollection.java
Normal file
@ -0,0 +1,65 @@
|
||||
package ovh.gasser.newshapes.shapes;
|
||||
|
||||
import ovh.gasser.newshapes.App;
|
||||
import ovh.gasser.newshapes.attributes.SelectionAttributes;
|
||||
import ovh.gasser.newshapes.ShapeVisitor;
|
||||
import ovh.gasser.newshapes.util.Streamable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Spliterator;
|
||||
|
||||
public class SCollection extends AbstractShape implements Streamable<Shape> {
|
||||
private final List<Shape> children;
|
||||
|
||||
private SCollection(Shape... shapes) {
|
||||
this.children = List.of(shapes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ShapeVisitor visitor) {
|
||||
visitor.visitCollection(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getBounds() {
|
||||
try {
|
||||
Rectangle bounds = children.get(0).getBounds();
|
||||
for (Shape s : children) bounds = bounds.union(s.getBounds());
|
||||
return bounds;
|
||||
} catch (IndexOutOfBoundsException e){
|
||||
// If the SCollection is empty, set the bounds to fill the window
|
||||
return new Rectangle(App.WIN_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoc(Point newLoc) {
|
||||
final Point loc = getBounds().getLocation();
|
||||
children.forEach(s -> s.translate(newLoc.x - loc.x, newLoc.y - loc.y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Shape> iterator() {
|
||||
return children.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator<Shape> spliterator() {
|
||||
return children.spliterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("SCollection{");
|
||||
children.forEach(obj -> sb.append(obj).append(", "));
|
||||
return sb.append("}").toString();
|
||||
}
|
||||
|
||||
public static SCollection of(Shape ...shapes) {
|
||||
SCollection collection = new SCollection(shapes);
|
||||
collection.addAttributes(new SelectionAttributes());
|
||||
return collection;
|
||||
}
|
||||
}
|
38
src/main/java/ovh/gasser/newshapes/shapes/SRectangle.java
Normal file
38
src/main/java/ovh/gasser/newshapes/shapes/SRectangle.java
Normal file
@ -0,0 +1,38 @@
|
||||
package ovh.gasser.newshapes.shapes;
|
||||
|
||||
import ovh.gasser.newshapes.attributes.ColorAttributes;
|
||||
import ovh.gasser.newshapes.attributes.SelectionAttributes;
|
||||
import ovh.gasser.newshapes.ShapeVisitor;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class SRectangle extends AbstractShape {
|
||||
|
||||
private SRectangle(Rectangle rect) {
|
||||
super(rect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ShapeVisitor visitor) {
|
||||
visitor.visitRectangle(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SRectangle{" +
|
||||
super.toString() +
|
||||
'}';
|
||||
}
|
||||
|
||||
public static SRectangle create(int x, int y, int width, int height) {
|
||||
SRectangle rect = new SRectangle(new Rectangle(x, y, width, height));
|
||||
rect.addAttributes(new SelectionAttributes());
|
||||
return rect;
|
||||
}
|
||||
|
||||
public static SRectangle create(int x, int y, int width, int height, Color color) {
|
||||
final SRectangle rect = create(x, y, width, height);
|
||||
rect.addAttributes(new ColorAttributes(false, true, Color.BLACK, color));
|
||||
return rect;
|
||||
}
|
||||
}
|
15
src/main/java/ovh/gasser/newshapes/shapes/Shape.java
Normal file
15
src/main/java/ovh/gasser/newshapes/shapes/Shape.java
Normal file
@ -0,0 +1,15 @@
|
||||
package ovh.gasser.newshapes.shapes;
|
||||
|
||||
import ovh.gasser.newshapes.ShapeVisitor;
|
||||
import ovh.gasser.newshapes.attributes.Attributes;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public interface Shape {
|
||||
void accept(ShapeVisitor visitor);
|
||||
void setLoc(Point newLoc);
|
||||
void translate(int dx, int dy);
|
||||
Attributes getAttributes(String key);
|
||||
void addAttributes(Attributes attr);
|
||||
Rectangle getBounds();
|
||||
}
|
70
src/main/java/ovh/gasser/newshapes/ui/Controller.java
Normal file
70
src/main/java/ovh/gasser/newshapes/ui/Controller.java
Normal file
@ -0,0 +1,70 @@
|
||||
package ovh.gasser.newshapes.ui;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import ovh.gasser.newshapes.Selection;
|
||||
import ovh.gasser.newshapes.shapes.SCollection;
|
||||
import ovh.gasser.newshapes.shapes.Shape;
|
||||
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Optional;
|
||||
|
||||
public class Controller {
|
||||
private final Logger logger = LoggerFactory.getLogger(ShapesView.class);
|
||||
private final ShapesView view;
|
||||
private final Shape model;
|
||||
private Selection selection;
|
||||
|
||||
Controller(ShapesView view, Shape model) {
|
||||
this.view = view;
|
||||
this.model = model;
|
||||
var adapter = new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent evt) {
|
||||
handleMousePressed(evt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent evt) {
|
||||
handleMouseDragged(evt);
|
||||
}
|
||||
};
|
||||
this.view.addMouseMotionListener(adapter);
|
||||
this.view.addMouseListener(adapter);
|
||||
}
|
||||
|
||||
private void handleMouseDragged(MouseEvent evt) {
|
||||
if (selection != null) selection.shape.setLoc(evt.getPoint());
|
||||
view.repaint();
|
||||
}
|
||||
|
||||
private void handleMousePressed(MouseEvent evt) {
|
||||
var sc = (SCollection) this.model;
|
||||
getTarget(evt, sc)
|
||||
.ifPresentOrElse(
|
||||
s -> {
|
||||
if (selection != null) resetSelection();
|
||||
selection = new Selection(s, true);
|
||||
this.logger.debug("Selecting {}", selection.shape);
|
||||
},
|
||||
() -> {
|
||||
if (selection != null) resetSelection();
|
||||
}
|
||||
);
|
||||
view.repaint();
|
||||
}
|
||||
|
||||
private void resetSelection() {
|
||||
this.logger.debug("Un-selecting {}", selection.shape);
|
||||
selection.unselect();
|
||||
selection = null;
|
||||
}
|
||||
|
||||
private Optional<Shape> getTarget(MouseEvent evt, SCollection sc) {
|
||||
return sc.stream()
|
||||
.filter(s -> s.getBounds().contains(evt.getPoint()))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
}
|
59
src/main/java/ovh/gasser/newshapes/ui/ShapeDraftman.java
Normal file
59
src/main/java/ovh/gasser/newshapes/ui/ShapeDraftman.java
Normal file
@ -0,0 +1,59 @@
|
||||
package ovh.gasser.newshapes.ui;
|
||||
|
||||
import ovh.gasser.newshapes.ShapeVisitor;
|
||||
import ovh.gasser.newshapes.shapes.Shape;
|
||||
import ovh.gasser.newshapes.attributes.ColorAttributes;
|
||||
import ovh.gasser.newshapes.attributes.SelectionAttributes;
|
||||
import ovh.gasser.newshapes.shapes.SCollection;
|
||||
import ovh.gasser.newshapes.shapes.SRectangle;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class ShapeDraftman implements ShapeVisitor {
|
||||
|
||||
private static final ColorAttributes DEFAULT_COLOR_ATTRIBUTES =
|
||||
new ColorAttributes(false, true, Color.BLACK, Color.BLACK);
|
||||
private Graphics2D g2d;
|
||||
|
||||
|
||||
public ShapeDraftman(Graphics graph) {
|
||||
this.g2d = (Graphics2D) graph;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRectangle(SRectangle rect) {
|
||||
Rectangle r = rect.getBounds();
|
||||
ColorAttributes colAttrs = (ColorAttributes) rect.getAttributes(ColorAttributes.ID);
|
||||
if (colAttrs == null){
|
||||
colAttrs = DEFAULT_COLOR_ATTRIBUTES;
|
||||
}
|
||||
if (colAttrs.filled) {
|
||||
this.g2d.setColor(colAttrs.filledColor);
|
||||
this.g2d.fillRect(r.x, r.y, r.width, r.height);
|
||||
}
|
||||
if (colAttrs.stroked) {
|
||||
this.g2d.setColor(colAttrs.strokedColor);
|
||||
this.g2d.drawRect(r.x, r.y, r.width, r.height);
|
||||
}
|
||||
drawHandlerIfSelected(rect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCollection(SCollection collection) {
|
||||
for (Shape s: collection) {
|
||||
s.accept(this);
|
||||
}
|
||||
drawHandlerIfSelected(collection);
|
||||
}
|
||||
|
||||
private void drawHandlerIfSelected(Shape s) {
|
||||
SelectionAttributes selAttrs = (SelectionAttributes) s.getAttributes(SelectionAttributes.ID);
|
||||
if ((selAttrs != null) && (selAttrs.selected)){
|
||||
Rectangle bounds = s.getBounds();
|
||||
this.g2d.setColor(Color.RED);
|
||||
this.g2d.drawRect(bounds.x - 5, bounds.y - 5, 5, 5);
|
||||
this.g2d.drawRect(bounds.x + bounds.width, bounds.y + bounds.height, 5, 5);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
29
src/main/java/ovh/gasser/newshapes/ui/ShapesView.java
Normal file
29
src/main/java/ovh/gasser/newshapes/ui/ShapesView.java
Normal file
@ -0,0 +1,29 @@
|
||||
package ovh.gasser.newshapes.ui;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import ovh.gasser.newshapes.ShapeVisitor;
|
||||
import ovh.gasser.newshapes.shapes.Shape;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class ShapesView extends JPanel {
|
||||
final Logger logger = LoggerFactory.getLogger(ShapesView.class);
|
||||
|
||||
private final Shape model;
|
||||
private final Controller controller;
|
||||
private ShapeVisitor draftman;
|
||||
|
||||
public ShapesView(Shape model) {
|
||||
this.model = model;
|
||||
this.controller = new Controller(this, model);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
this.draftman = new ShapeDraftman(g);
|
||||
model.accept(draftman);
|
||||
}
|
||||
}
|
85
src/main/java/ovh/gasser/newshapes/ui/html/HTMLDraftman.java
Normal file
85
src/main/java/ovh/gasser/newshapes/ui/html/HTMLDraftman.java
Normal file
@ -0,0 +1,85 @@
|
||||
package ovh.gasser.newshapes.ui.html;
|
||||
|
||||
import ovh.gasser.newshapes.ShapeVisitor;
|
||||
import ovh.gasser.newshapes.attributes.ColorAttributes;
|
||||
import ovh.gasser.newshapes.shapes.SCollection;
|
||||
import ovh.gasser.newshapes.shapes.SRectangle;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
public class HTMLDraftman implements ShapeVisitor {
|
||||
|
||||
private static final String HEADER_TEMPLATE = "<!DOCTYPE html>" +
|
||||
"<html lang=\"fr\">" +
|
||||
"<head>" +
|
||||
" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />" +
|
||||
" <link rel=\"stylesheet\" href=\"style.css\" />" +
|
||||
" <title>Reactive shapes HTML</title>" +
|
||||
"</head>" +
|
||||
"<body>";
|
||||
|
||||
private static final String FOOTER_TEMPLATE = "</body>";
|
||||
|
||||
private PrintWriter htmlOutput;
|
||||
private PrintWriter cssOutput;
|
||||
|
||||
public HTMLDraftman(PrintWriter htmlOutput, PrintWriter cssOutput) {
|
||||
this.htmlOutput = htmlOutput;
|
||||
this.cssOutput = cssOutput;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRectangle(SRectangle rect) {
|
||||
htmlOutput.println("<div id=\"rec" + rect.hashCode() + "\"></div>");
|
||||
cssOutput.println("#rec" + rect.hashCode() + "{ ");
|
||||
cssOutput.println("position:absolute;");
|
||||
cssOutput.println("top:" + rect.getBounds().y + "px;");
|
||||
cssOutput.println("left:" + rect.getBounds().x + "px;");
|
||||
cssOutput.println("width:" + rect.getBounds().width + "px;");
|
||||
cssOutput.println("height:" + rect.getBounds().height + "px;");
|
||||
cssOutput.println(this.attributesToCss(rect) + " }");
|
||||
}
|
||||
|
||||
private String attributesToCss(SRectangle rect) {
|
||||
ColorAttributes attrs = (ColorAttributes) rect.getAttributes(ColorAttributes.ID);
|
||||
String strokedColor = "#ffffff";
|
||||
String filledColor = "#ffffff";
|
||||
|
||||
if (attrs != null && attrs.filledColor != null){
|
||||
filledColor = formatCSSColor(attrs.filledColor);
|
||||
}
|
||||
if (attrs != null && attrs.strokedColor != null){
|
||||
strokedColor = formatCSSColor(attrs.strokedColor);
|
||||
}
|
||||
if(attrs != null && attrs.stroked && attrs.filled){
|
||||
return "background: " + filledColor + ";border:1px solid " + strokedColor + ";";
|
||||
}
|
||||
if (attrs != null && attrs.stroked){
|
||||
return "background:#ffffff;border:1px solid "+strokedColor+";";
|
||||
}
|
||||
if (attrs != null && attrs.filled) {
|
||||
return "background: "+filledColor+";";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private String formatCSSColor(Color col) {
|
||||
final int r = col.getRed();
|
||||
final int g = col.getGreen();
|
||||
final int b = col.getBlue();
|
||||
return String.format("#%02x%02x%02x", r, g, b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCollection(SCollection collection) {
|
||||
collection.stream().forEach(shape -> shape.accept(this));
|
||||
}
|
||||
|
||||
public void generateHTML(SCollection model) {
|
||||
htmlOutput.println(HEADER_TEMPLATE);
|
||||
visitCollection(model);
|
||||
htmlOutput.println(FOOTER_TEMPLATE);
|
||||
}
|
||||
}
|
10
src/main/java/ovh/gasser/newshapes/util/Streamable.java
Normal file
10
src/main/java/ovh/gasser/newshapes/util/Streamable.java
Normal file
@ -0,0 +1,10 @@
|
||||
package ovh.gasser.newshapes.util;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
public interface Streamable<T> extends Iterable<T> {
|
||||
default Stream<T> stream() {
|
||||
return StreamSupport.stream(this.spliterator(), false);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user