Base java event POC
This commit is contained in:
		
							
								
								
									
										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); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user