diff --git a/src/main/java/Graph1/serializer/App.java b/src/main/java/Graph1/serializer/App.java new file mode 100644 index 0000000000000000000000000000000000000000..de2390b06553373d5143bbfc42625e5688007f4b --- /dev/null +++ b/src/main/java/Graph1/serializer/App.java @@ -0,0 +1,31 @@ +package Graph1.serializer; + +import javafx.application.Application; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.stage.Stage; + +public class App extends Application { + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(Stage primaryStage) { + Group root = new Group(); + DrawerWithSave container = new DrawerWithSave(800, 600); + root.getChildren().add(container); + primaryStage.setScene(new Scene(root)); + primaryStage.show(); + Button save = new Button("save"); + root.getChildren().add(save); + save.setLayoutX(0); + save.setLayoutY(0); + root.setOnKeyPressed(event->container.context.keyPressed(event)); + //save.setOnKeyPressed(event->container.context.keyPressed(event)); + save.setOnAction(event -> container.write()); + + } +} \ No newline at end of file diff --git a/src/main/java/Graph1/serializer/DrawerWithSave.java b/src/main/java/Graph1/serializer/DrawerWithSave.java new file mode 100644 index 0000000000000000000000000000000000000000..3f5fc3412f7ed021da0ffce96aae90827e0cd1a6 --- /dev/null +++ b/src/main/java/Graph1/serializer/DrawerWithSave.java @@ -0,0 +1,52 @@ +package Graph1.serializer; + +import javafx.scene.canvas.Canvas; +import javafx.scene.control.Alert; +import javafx.stage.FileChooser; + + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + + +public class DrawerWithSave extends Graph1.state.Drawer { + + public DrawerWithSave(int width, int height) { + super(width, height); + } + + void write(){ + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Save"); + File file = fileChooser.showSaveDialog(getScene().getWindow()); + if (file == null) return; + try { + ShapeWriter.write(file, super.shapes); + } + catch (IOException e) { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Error Dialog"); + alert.setHeaderText(null); + alert.setContentText("Ooops, there was an error!"); + alert.showAndWait(); + } + } + public void load() { + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Load"); + File file = fileChooser.showOpenDialog(getScene().getWindow()); + if (file == null) return; + try { + super.shapes = ShapeReader.read(file); + repaint(); + } catch (IOException e) { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Error Dialog"); + alert.setHeaderText(null); + alert.setContentText("Ooops, there was an error!"); + alert.showAndWait(); + } + } +} diff --git a/src/main/java/Graph1/serializer/ShapeReader.java b/src/main/java/Graph1/serializer/ShapeReader.java new file mode 100644 index 0000000000000000000000000000000000000000..27320d4121b0b4a570c6fda01e81677995d10e8b --- /dev/null +++ b/src/main/java/Graph1/serializer/ShapeReader.java @@ -0,0 +1,20 @@ +package Graph1.serializer; + +import Graph1.shape.Shape; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.List; +import java.util.stream.Collector; + +public class ShapeReader { + public static List<Shape> read(File file) throws IOException { + BufferedReader bufferedReader = new BufferedReader(new FileReader(file)); + /*for(String line : bufferedReader.lines().toList()) { + System.out.println(line); + }*/ + return null; + } +} diff --git a/src/main/java/Graph1/serializer/ShapeWriter.java b/src/main/java/Graph1/serializer/ShapeWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..3203d2f63ee95d638d450084d4246cb208a7f0aa --- /dev/null +++ b/src/main/java/Graph1/serializer/ShapeWriter.java @@ -0,0 +1,15 @@ +package Graph1.serializer; + +import Graph1.shape.Shape; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.List; + +public class ShapeWriter { + public static void write (File file, List<Shape> shapes) throws IOException { + PrintWriter printWriter = new PrintWriter(file); + printWriter.println("Coucou"); + } +} diff --git a/src/main/java/Graph1/shape/Abstractshape.java b/src/main/java/Graph1/shape/Abstractshape.java new file mode 100644 index 0000000000000000000000000000000000000000..e458aa1de3d634e2c369993149d2316a806402bc --- /dev/null +++ b/src/main/java/Graph1/shape/Abstractshape.java @@ -0,0 +1,40 @@ +package Graph1.shape; +import javafx.geometry.Point2D; +import javafx.scene.canvas.GraphicsContext; +import java.util.List; + + +public abstract class Abstractshape implements Shape { + private List<Point2D> points; + + public Abstractshape(List<Point2D> points) { + this.points = points; + } + public void addPoints(Point2D... points){ + for (Point2D point: points) + this.points.add(point); + } + @Override + public int pointsCount() { + return points.size(); + } + + @Override + public Point2D point(int index) { + return index < points.size() ? points.get(index) : null; + } + + @Override + public void draw(GraphicsContext context) { + if (pointsCount()>0){ + context.beginPath(); + context.moveTo(point(0).getX(), point(0).getY()); + for (int i = 1; i<pointsCount(); i++){ + context.lineTo(point(i).getX(),point(i).getY()); + } + context.closePath(); + context.stroke(); + } + + } +} \ No newline at end of file diff --git a/src/main/java/Graph1/shape/App.java b/src/main/java/Graph1/shape/App.java new file mode 100644 index 0000000000000000000000000000000000000000..107341ccdc2079008f5cdba8a6083121db31b58c --- /dev/null +++ b/src/main/java/Graph1/shape/App.java @@ -0,0 +1,35 @@ +package Graph1.shape; + +import javafx.application.Application; +import javafx.geometry.Point2D; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; +import javafx.scene.paint.Paint; +import javafx.stage.Stage; + + + +public class App extends Application { + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(Stage primaryStage) { + Group root = new Group(); + Canvas canvas = new Canvas(130, 110); + GraphicsContext graphicsContext = canvas.getGraphicsContext2D(); + ShapeContainer shapeContainer = new ShapeContainer(); + graphicsContext.setFill(Color.AQUAMARINE); + graphicsContext.fillOval(10,10,10,10); + shapeContainer.addShape(new Rectangle(Color.BLUE,new Point2D(10,10), new Point2D(40,40))); + shapeContainer.draw(graphicsContext); + root.getChildren().add(canvas); + primaryStage.setScene(new Scene(root)); + primaryStage.show(); + } +} \ No newline at end of file diff --git a/src/main/java/Graph1/shape/BorderDecorator.java b/src/main/java/Graph1/shape/BorderDecorator.java new file mode 100644 index 0000000000000000000000000000000000000000..04a32c276418de0cc35db5c94063956abda8928e --- /dev/null +++ b/src/main/java/Graph1/shape/BorderDecorator.java @@ -0,0 +1,24 @@ +package Graph1.shape; + +import javafx.geometry.Point2D; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; + + +public class BorderDecorator extends Decorator { + + private double radius; + + public BorderDecorator(Shape decoratedShape ,double radius) { + super(decoratedShape); + this.radius = radius; + } + protected void drawDecoration(GraphicsContext context) { + context.setStroke(Color.BLACK); + context.setLineWidth(2); + for (int i=0; i<pointsCount(); i++){ + Point2D point = point(i); + context.strokeOval(point.getX() - radius, point.getY()- radius,radius*2,radius*2); + } + } +} diff --git a/src/main/java/Graph1/shape/CenterDecorator.java b/src/main/java/Graph1/shape/CenterDecorator.java new file mode 100644 index 0000000000000000000000000000000000000000..a6d1c0b7f4e749a50a686c1eafd78e27d53381e8 --- /dev/null +++ b/src/main/java/Graph1/shape/CenterDecorator.java @@ -0,0 +1,27 @@ +package Graph1.shape; + +import javafx.geometry.Point2D; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; + +public class CenterDecorator extends Decorator{ + private double radius; + public CenterDecorator(Shape decoratedShape, double radius) { + super(decoratedShape); + this.radius = radius; + } + protected void drawDecoration(GraphicsContext context) { + double centerX = 0; + double centerY = 0; + for (int i =0; i<pointsCount(); i++){ + Point2D point = point(i); + centerX += point.getX(); + centerY += point.getY(); + } + centerX /= pointsCount(); + centerY /= pointsCount(); + context.setStroke(Color.RED); + context.setLineWidth(2); + context.strokeOval(centerX-radius, centerY-radius, radius*2,radius*2); + } +} \ No newline at end of file diff --git a/src/main/java/Graph1/shape/Circle.java b/src/main/java/Graph1/shape/Circle.java new file mode 100644 index 0000000000000000000000000000000000000000..e73276310325c80d5f5d2151176873ffb215ddc9 --- /dev/null +++ b/src/main/java/Graph1/shape/Circle.java @@ -0,0 +1,25 @@ +package Graph1.shape; + +import javafx.geometry.Point2D; +import javafx.scene.canvas.GraphicsContext; + +public class Circle implements Shape { + + public Circle(double x, double y, double sqrt) { + } + + @Override + public int pointsCount() { + return 0; + } + + @Override + public Point2D point(int index) { + return null; + } + + @Override + public void draw(GraphicsContext context) { + + } +} diff --git a/src/main/java/Graph1/shape/Decorator.java b/src/main/java/Graph1/shape/Decorator.java new file mode 100644 index 0000000000000000000000000000000000000000..a806739421574fb76c6738209b5b5c432c791b3e --- /dev/null +++ b/src/main/java/Graph1/shape/Decorator.java @@ -0,0 +1,28 @@ +package Graph1.shape; +import javafx.geometry.Point2D; +import javafx.scene.canvas.GraphicsContext; + +public abstract class Decorator implements Shape { + protected Shape decoratedshape; + public Decorator(Shape decoratedShape) { + this.decoratedshape = decoratedShape; + } + @Override + public int pointsCount() { + return decoratedshape.pointsCount(); + } + + @Override + public Point2D point(int index) { + return decoratedshape.point(index); + } + + @Override + public void draw(GraphicsContext context) { + decoratedshape.draw(context); + drawDecoration(context); + } + protected void drawDecoration(GraphicsContext context) { + + } +} \ No newline at end of file diff --git a/src/main/java/Graph1/shape/Polygon.java b/src/main/java/Graph1/shape/Polygon.java new file mode 100644 index 0000000000000000000000000000000000000000..7b45e5bd30847f0d1729b5cf831f75e7a0832b48 --- /dev/null +++ b/src/main/java/Graph1/shape/Polygon.java @@ -0,0 +1,34 @@ +package Graph1.shape; +import javafx.geometry.Point2D; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; + +import java.util.List; + +public class Polygon extends Abstractshape { + + private Color color; + + public Polygon(Color color, Point2D... points) { + super(List.of(points)); + this.color = color; + } + + @Override + public int pointsCount() { + return super.pointsCount(); + } + + @Override + public Point2D point(int index) { + return super.point(index); + } + + @Override + public void draw(GraphicsContext context) { + context.setFill(color); + super.draw(context); + context.fill(); + + } +} \ No newline at end of file diff --git a/src/main/java/Graph1/shape/Rectangle.java b/src/main/java/Graph1/shape/Rectangle.java new file mode 100644 index 0000000000000000000000000000000000000000..958d31d230efe65c2262dc3901760a860c119564 --- /dev/null +++ b/src/main/java/Graph1/shape/Rectangle.java @@ -0,0 +1,32 @@ +package Graph1.shape; + +import javafx.geometry.Point2D; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; +import java.util.List; + +public class Rectangle extends Abstractshape{ + private Color color; + Rectangle(Color color, Point2D point0, Point2D point1){ + super(List.of(point0, new Point2D(point1.getX(),point0.getY()), + point1,new Point2D(point0.getX(),point1.getY()))); + this.color = color; + } + + @Override + public int pointsCount() { + return super.pointsCount(); + } + + @Override + public Point2D point(int index) { + return super.point(index); + } + + @Override + public void draw(GraphicsContext context) { + context.setFill(color); + super.draw(context); + context.fill(); + } +} \ No newline at end of file diff --git a/src/main/java/Graph1/shape/Shape.java b/src/main/java/Graph1/shape/Shape.java new file mode 100644 index 0000000000000000000000000000000000000000..ca81871943b7c430bb64172fb83d75cf2f572fc6 --- /dev/null +++ b/src/main/java/Graph1/shape/Shape.java @@ -0,0 +1,10 @@ +package Graph1.shape; + +import javafx.geometry.Point2D; +import javafx.scene.canvas.GraphicsContext; + +public interface Shape { + int pointsCount(); + Point2D point(int index); + void draw(GraphicsContext context); +} diff --git a/src/main/java/Graph1/shape/ShapeContainer.java b/src/main/java/Graph1/shape/ShapeContainer.java new file mode 100644 index 0000000000000000000000000000000000000000..09ad98af5d5ea8a672d100c5e3949a0e6271f332 --- /dev/null +++ b/src/main/java/Graph1/shape/ShapeContainer.java @@ -0,0 +1,20 @@ +package Graph1.shape; + +import javafx.scene.canvas.GraphicsContext; + +import java.util.ArrayList; +import java.util.List; + +public class ShapeContainer{ + + private List<Shape> shapes = new ArrayList<>(); + + public void addShape(Shape shape){ + shapes.add(shape); + } + + public void draw(GraphicsContext context){ + for(Shape shape : shapes) + shape.draw(context); + } +} \ No newline at end of file diff --git a/src/main/java/Graph1/state/App.java b/src/main/java/Graph1/state/App.java new file mode 100644 index 0000000000000000000000000000000000000000..597da8a30f41cd0019bfbaeaaaa044e1f3e5152f --- /dev/null +++ b/src/main/java/Graph1/state/App.java @@ -0,0 +1,22 @@ +package Graph1.state; + +import javafx.application.Application; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.stage.Stage; + +public class App extends Application { + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(Stage primaryStage) { + Group root = new Group(); + Drawer container = new Drawer(800, 600); + root.getChildren().add(container); + primaryStage.setScene(new Scene(root)); + primaryStage.show(); + } +} \ No newline at end of file diff --git a/src/main/java/Graph1/state/Drawer.java b/src/main/java/Graph1/state/Drawer.java new file mode 100644 index 0000000000000000000000000000000000000000..61faf4e508374d25e8be6e1270f4b1118cb43d0e --- /dev/null +++ b/src/main/java/Graph1/state/Drawer.java @@ -0,0 +1,28 @@ +package Graph1.state; + +import javafx.scene.canvas.Canvas; +import Graph1.shape.Circle; +import Graph1.shape.Shape; + +import java.util.ArrayList; +import java.util.List; + + +public class Drawer extends Canvas { + protected List<Shape> shapes = new ArrayList<>(); + public DrawerContext context = new DrawerContext(this); + + public Drawer(int width, int height) { + super(width,height); + setFocusTraversable(true); + setOnMousePressed(event->context.mousePressed(event)); + setOnMouseReleased(event->context.mouseReleased(event)); + setOnMouseMoved(event->context.mouseMoved(event)); + setOnMouseDragged(event->context.mouseMoved(event)); + //setOnKeyPressed(event -> context.keyPressed(event)); + } + + public void repaint(){ + this.getGraphicsContext2D().clearRect(0,0,this.getWidth(),this.getHeight()); + } +} diff --git a/src/main/java/Graph1/state/DrawerContext.java b/src/main/java/Graph1/state/DrawerContext.java new file mode 100644 index 0000000000000000000000000000000000000000..c90a1b8fac22555b136a75ba331440dbbead79aa --- /dev/null +++ b/src/main/java/Graph1/state/DrawerContext.java @@ -0,0 +1,33 @@ +package Graph1.state; + + +import javafx.scene.input.KeyEvent; +import javafx.scene.input.MouseEvent; + +public class DrawerContext { + + Drawer drawer; + DrawerState currentState; + + public DrawerContext(Drawer drawer) { + this.drawer = drawer; + } + + void mousePressed(MouseEvent event){ + currentState.mousePressed(this,event.getX(),event.getY()); + + } + + void mouseReleased(MouseEvent event){ + currentState.mouseReleased(this,event.getX(),event.getY()); + } + + void mouseMoved(MouseEvent event){} + + public void keyPressed(KeyEvent event) { + switch (event.getText()) { + case "c": + currentState = new StateCircle0(); + } + } +} diff --git a/src/main/java/Graph1/state/DrawerState.java b/src/main/java/Graph1/state/DrawerState.java new file mode 100644 index 0000000000000000000000000000000000000000..1d0a302047aa9fa0dc318f1ab72a1349a1e2dda5 --- /dev/null +++ b/src/main/java/Graph1/state/DrawerState.java @@ -0,0 +1,6 @@ +package Graph1.state; + +public interface DrawerState { + void mousePressed(DrawerContext context, double x, double y); + void mouseReleased(DrawerContext context, double x, double y); +} diff --git a/src/main/java/Graph1/state/StateCircle0.java b/src/main/java/Graph1/state/StateCircle0.java new file mode 100644 index 0000000000000000000000000000000000000000..a9a2b91b6674c08cd74c42c4f423c6dcacefc624 --- /dev/null +++ b/src/main/java/Graph1/state/StateCircle0.java @@ -0,0 +1,13 @@ +package Graph1.state; + +public class StateCircle0 implements DrawerState { + @Override + public void mousePressed(DrawerContext context, double x, double y) { + + } + + @Override + public void mouseReleased(DrawerContext context, double x, double y) { + + } +} diff --git a/src/main/java/TP5/serializer/App.java b/src/main/java/TP5/serializer/App.java new file mode 100644 index 0000000000000000000000000000000000000000..d9f667be0266d06bcd6a0022adef0cc5124ea3ad --- /dev/null +++ b/src/main/java/TP5/serializer/App.java @@ -0,0 +1,31 @@ +package TP5.serializer; + +import javafx.application.Application; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.stage.Stage; + +public class App extends Application { + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(Stage primaryStage) { + Group root = new Group(); + DrawerWithSave container = new DrawerWithSave(800, 600); + root.getChildren().add(container); + primaryStage.setScene(new Scene(root)); + primaryStage.show(); + Button save = new Button("save"); + root.getChildren().add(save); + save.setLayoutX(0); + save.setLayoutY(0); + root.setOnKeyPressed(event->container.context.keyPressed(event)); + //save.setOnKeyPressed(event->container.context.keyPressed(event)); + save.setOnAction(event -> container.write()); + + } +} \ No newline at end of file diff --git a/src/main/java/TP5/serializer/DrawerWithSave.java b/src/main/java/TP5/serializer/DrawerWithSave.java new file mode 100644 index 0000000000000000000000000000000000000000..d0e3d7cb0ea331d883eba458c0312796cd235873 --- /dev/null +++ b/src/main/java/TP5/serializer/DrawerWithSave.java @@ -0,0 +1,48 @@ +package TP5.serializer; + +import javafx.scene.control.Alert; +import javafx.stage.FileChooser; + +import java.io.File; +import java.io.IOException; + + +public class DrawerWithSave extends TP5.state.Drawer { + + public DrawerWithSave(int width, int height) { + super(width, height); + } + + void write(){ + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Save"); + File file = fileChooser.showSaveDialog(getScene().getWindow()); + if (file == null) return; + try { + ShapeWriter.write(file, super.shapes); + } + catch (IOException e) { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Error Dialog"); + alert.setHeaderText(null); + alert.setContentText("Ooops, there was an error!"); + alert.showAndWait(); + } + } + public void load() { + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Load"); + File file = fileChooser.showOpenDialog(getScene().getWindow()); + if (file == null) return; + try { + super.shapes = ShapeReader.read(file); + repaint(); + } catch (IOException e) { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Error Dialog"); + alert.setHeaderText(null); + alert.setContentText("Ooops, there was an error!"); + alert.showAndWait(); + } + } +} diff --git a/src/main/java/TP5/serializer/ShapeReader.java b/src/main/java/TP5/serializer/ShapeReader.java new file mode 100644 index 0000000000000000000000000000000000000000..740f15ad6c76cfa708e71ac89dab81b45c90581d --- /dev/null +++ b/src/main/java/TP5/serializer/ShapeReader.java @@ -0,0 +1,19 @@ +package TP5.serializer; + +import TP5.shape.Shape; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.List; + +public class ShapeReader { + public static List<Shape> read(File file) throws IOException { + BufferedReader bufferedReader = new BufferedReader(new FileReader(file)); + /*for(String line : bufferedReader.lines().toList()) { + System.out.println(line); + }*/ + return null; + } +} diff --git a/src/main/java/TP5/serializer/ShapeWriter.java b/src/main/java/TP5/serializer/ShapeWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..fb9f9fef6f48a0e9abde07e34ee50d73c7102f2e --- /dev/null +++ b/src/main/java/TP5/serializer/ShapeWriter.java @@ -0,0 +1,15 @@ +package TP5.serializer; + +import TP5.shape.Shape; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.List; + +public class ShapeWriter { + public static void write (File file, List<Shape> shapes) throws IOException { + PrintWriter printWriter = new PrintWriter(file); + printWriter.println("Coucou"); + } +} diff --git a/src/main/java/TP5/shape/App.java b/src/main/java/TP5/shape/App.java new file mode 100644 index 0000000000000000000000000000000000000000..5df6b0a49950741028a5949ab1594a777e241486 --- /dev/null +++ b/src/main/java/TP5/shape/App.java @@ -0,0 +1,27 @@ +package TP5.shape; + +import javafx.application.Application; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.stage.Stage; + + +public class App extends Application { + + @Override + public void start(Stage primaryStage) { + Drawer drawer = new Drawer(600, 400); + + Group root = new Group(); + root.getChildren().add(drawer.getCanvas()); + + Scene scene = new Scene(root, 600, 400); + + primaryStage.setTitle("JavaFX Drawer"); + primaryStage.setScene(scene); + primaryStage.show(); + } + public static void main(String[] args) { + launch(args); + } +} \ No newline at end of file diff --git a/src/main/java/TP5/shape/Circle.java b/src/main/java/TP5/shape/Circle.java new file mode 100644 index 0000000000000000000000000000000000000000..0cef5337718a032fb4e6bc7920886abf309c7e97 --- /dev/null +++ b/src/main/java/TP5/shape/Circle.java @@ -0,0 +1,78 @@ +package TP5.shape; + +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; + +public class Circle implements Shape { + + private double radius, x, y; + private boolean isFinished; + + public Circle(double x, double y, double radius) { + this.x = x; + this.y = y; + this.radius = radius; + this.isFinished = true; + } + + + @Override + public void paint(GraphicsContext graphicsContext) { + graphicsContext.setStroke(Color.BLACK); + graphicsContext.setLineWidth(2); + if (isFinished) { + graphicsContext.setFill(Color.GREEN.deriveColor(0,1,1,0.5)); + graphicsContext.fillOval(x - radius, y - radius, 2 * radius, 2 * radius); + } + graphicsContext.strokeOval(x - radius, y - radius, 2 * radius, 2 * radius); + } + + @Override + public boolean contains(double x, double y) { + double dx = x - this.x; + double dy = y - this.y; + return Math.sqrt(dx * dx + dy * dy) <= radius; + } + + @Override + public void translate(double dx, double dy) { + this.x += dx; + this.y += dy; + } + + @Override + public boolean isFinished() { + return isFinished; + } + + public void setX(double x) { + this.x = x; + } + + public void setY(double y) { + this.y = y; + } + + public void setFinished(boolean finished) { + isFinished = finished; + } + + public void updateRadius(double newX, double newY) { + this.radius = Math.sqrt(Math.pow(newX - this.x, 2) + Math.pow(newY - this.y, 2)); + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public void setDimensions(double x, double y, double width, double height){ + this.x = x; + this.y = y; + this.radius = width/2; + } + +} diff --git a/src/main/java/TP5/shape/Drawer.java b/src/main/java/TP5/shape/Drawer.java new file mode 100644 index 0000000000000000000000000000000000000000..914e859a9b5c73c8076c5fb74f024b630b3e3d29 --- /dev/null +++ b/src/main/java/TP5/shape/Drawer.java @@ -0,0 +1,120 @@ +package TP5.shape; + + +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.input.KeyCode; +import javafx.scene.input.MouseButton; +import TP5.state.DrawerContext; +import TP5.state.StateMoveShape; + +import java.util.ArrayList; +import java.util.List; + +public class Drawer { + private List<Shape> shapes; +// private double width; +// private double height; + private Canvas canvas; + private GraphicsContext gc; + + private String currentShapeType = "rectangle"; + private Shape tempShape = null; + private boolean isFinished = false; + public DrawerContext context; + + + public Drawer(double width, double height) { +// this.width = width; +// this.height = height; + shapes = new ArrayList<>(); + canvas = new Canvas(width,height); + gc = canvas.getGraphicsContext2D(); + setupMouseHandlers(); + setupKeyHandlers(); + } + + public void add(Shape shape) { + shapes.add(shape); + } + public void repaint(){ + gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); + for(Shape shape : shapes){ + shape.paint(gc); + } + if (tempShape != null){ + tempShape.paint(gc); + } + } + + private void setupMouseHandlers(){ + canvas.setOnMousePressed(event -> { + if(event.getButton() == MouseButton.PRIMARY){ + double x = event.getX(); + double y = event.getY(); + // tempShape = new Rectangle(x, y, 0, 0); + System.out.println(currentShapeType); + if (currentShapeType.equals("rectangle")) { + tempShape = new Rectangle(x, y, 0, 0); + }else if (currentShapeType.equals("circle")) { + tempShape = new Circle(x, y, 0); + } + } + }); + + canvas.setOnMouseDragged(event ->{ + if (tempShape != null) { + double x = event.getX(); + double y = event.getY(); + if (tempShape instanceof Rectangle){ + ((Rectangle) tempShape).updateSize(x,y); + }else if (tempShape instanceof Circle){ + ((Circle) tempShape).updateRadius(x,y); + } + repaint(); + } + }); + + canvas.setOnMouseReleased(event -> { + if(event.getButton() == MouseButton.PRIMARY && tempShape != null){ + shapes.add(tempShape); + if (tempShape instanceof Rectangle){ + ((Rectangle) tempShape).setFinished(true); + }else if (tempShape instanceof Circle){ + + ((Circle) tempShape).setFinished(true); + } + repaint(); + tempShape = null; + } + }); + } + private void setupKeyHandlers(){ + canvas.setFocusTraversable(true); + canvas.setOnKeyPressed(event -> { + if (event.getCode() == KeyCode.R){ + currentShapeType = "rectangle"; + System.out.println("Current shape type is: " + currentShapeType); + }else if (event.getCode() == KeyCode.C){ + currentShapeType = "circle"; + System.out.println("Current shape type is: " + currentShapeType); + } else if (event.getCode() == KeyCode.M) { + currentShapeType = null ; + } + }); + } + + /* public Shape shapeContaining(double x, double y){ + for(Shape shape : shapes){ + if (shape.contains(x, y)){ + return shape; + } + } + return null; + }*/ + + + public Canvas getCanvas() { + return canvas; + } +} diff --git a/src/main/java/TP5/shape/Rectangle.java b/src/main/java/TP5/shape/Rectangle.java new file mode 100644 index 0000000000000000000000000000000000000000..a702075705a0294d9c0e60b82bbb4dac6263e0d5 --- /dev/null +++ b/src/main/java/TP5/shape/Rectangle.java @@ -0,0 +1,88 @@ +package TP5.shape; + +import javafx.geometry.Point2D; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; + +public class Rectangle implements Shape{ + + private double x,y,width, height; + private boolean isFinished; + public Color fillColor; + + public Rectangle(double x, double y, double width, double height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + this.isFinished = true; + } + + @Override + public void paint(GraphicsContext graphicsContext) { + graphicsContext.setStroke(Color.BLACK); + graphicsContext.setLineWidth(2); + if(isFinished){ + graphicsContext.setFill(Color.RED.deriveColor(0,1,1,0.5)); + graphicsContext.fillRect(x, y, width, height); + } + graphicsContext.strokeRect(x, y, width, height); + + } + + @Override + public boolean contains(double x, double y) { + return x>= this.x && x<= this.x + this.width + && y>= this.y && y<= this.y + this.height; + } + + @Override + public void translate(double dx, double dy) { + x += dx; + y += dy; + } + + @Override + public boolean isFinished() { + return isFinished; + } + + + public void updateSize(double newX, double newY) { + this.width = Math.abs(newX - this.x); + this.height = Math.abs(newY - this.y); + if (newX < this.x && newY < this.y) { + this.x = newX; + this.y = newY; + } + } + + public Color getFillColor() { + return fillColor; + } + + public void setFinished(boolean finished) { + isFinished = finished; + } + + public void setFillColor(Color fillColor) { + this.fillColor = fillColor; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public void setDimensions(double x, double y, double width, double height) { + this.x = x; + this.y = y; + this.width = Math.abs(width); + this.height = Math.abs(height); + if(width < 0 ){ this.x += width;} + if(height < 0){ this.y += height;} + } +} diff --git a/src/main/java/TP5/shape/Shape.java b/src/main/java/TP5/shape/Shape.java new file mode 100644 index 0000000000000000000000000000000000000000..3f01b05615ba44ff6ac77d307df06614e6191fa4 --- /dev/null +++ b/src/main/java/TP5/shape/Shape.java @@ -0,0 +1,12 @@ +package TP5.shape; + +import javafx.geometry.Point2D; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; + +public interface Shape { + void paint(GraphicsContext graphicsContext); + boolean contains(double x, double y); + void translate(double dx, double dy); + boolean isFinished(); +} diff --git a/src/main/java/TP5/state/App.java b/src/main/java/TP5/state/App.java new file mode 100644 index 0000000000000000000000000000000000000000..2ed103fa2707647a39d44ef02f388178a38f99ab --- /dev/null +++ b/src/main/java/TP5/state/App.java @@ -0,0 +1,24 @@ +package TP5.state; + +import javafx.application.Application; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.stage.Stage; +import TP5.shape.Circle; + +public class App extends Application { + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(Stage primaryStage) { + Group root = new Group(); + Drawer container = new Drawer(800, 600); + + root.getChildren().add(container); + primaryStage.setScene(new Scene(root)); + primaryStage.show(); + } +} \ No newline at end of file diff --git a/src/main/java/TP5/state/Drawer.java b/src/main/java/TP5/state/Drawer.java new file mode 100644 index 0000000000000000000000000000000000000000..d89b71308b00d5d83c0979da24927cb787d1bf04 --- /dev/null +++ b/src/main/java/TP5/state/Drawer.java @@ -0,0 +1,40 @@ +package TP5.state; + +import javafx.scene.canvas.Canvas; +import TP5.shape.Shape; + +import java.util.ArrayList; +import java.util.List; + + +public class Drawer extends Canvas { + protected List<Shape> shapes = new ArrayList<>(); + public DrawerContext context = new DrawerContext(this); + + public Drawer(int width, int height) { + super(width,height); + setFocusTraversable(true); + setOnMousePressed(event->context.mousePressed(event)); + setOnMouseReleased(event->context.mouseReleased(event)); + setOnMouseMoved(event->context.mouseMoved(event)); + setOnMouseDragged(event->context.mouseMoved(event)); + setOnKeyPressed(event -> context.keyPressed(event)); + } + + public void repaint(){ + this.getGraphicsContext2D().clearRect(0,0,this.getWidth(),this.getHeight()); + for(Shape shape : shapes){ + shape.paint(this.getGraphicsContext2D()); + } + } + public void addShape(Shape shape){ + shapes.add(shape); + repaint(); + } + public Shape shapeContains(double x, double y){ + for(Shape shape : shapes){ + if(shape.contains(x,y)) return shape; + } + return null; + } +} diff --git a/src/main/java/TP5/state/DrawerContext.java b/src/main/java/TP5/state/DrawerContext.java new file mode 100644 index 0000000000000000000000000000000000000000..590aa928b8cd05bf978a989d35a7202b7bbb7d04 --- /dev/null +++ b/src/main/java/TP5/state/DrawerContext.java @@ -0,0 +1,62 @@ +package TP5.state; + + +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.input.KeyEvent; +import javafx.scene.input.MouseEvent; + +public class DrawerContext { + + Drawer drawer; + DrawerState currentState; + + public DrawerContext(Drawer drawer) { + this.drawer = drawer; + this.currentState = new NullDrawerState(); + } + public void paint(GraphicsContext graphicsContext) { + drawer.repaint(); + } + + void mousePressed(MouseEvent event){ + currentState.mousePressed(this,event.getX(),event.getY()); + + } + + void mouseReleased(MouseEvent event){ + currentState.mouseReleased(this,event.getX(),event.getY()); + } + + void mouseMoved(MouseEvent event){ + currentState.mouseMoved(this,event.getX(),event.getY()); + } + + public void keyPressed(KeyEvent event) { + switch (event.getText()) { + case "c": + setState(new StateCircle0()); + System.out.println("circle state"); + break; + case "r": + setState(new StateRectangle0()); + break; + case "m": + setState(new StateMoveShape()); + System.out.println("state: " + currentState); + break; + default: + setState(new NullDrawerState()); + } + } + public Drawer drawer(){ + return drawer; + } + + public Drawer getDrawer() { + return drawer; + } + + public void setState(DrawerState state) { + this.currentState = state; + } +} diff --git a/src/main/java/TP5/state/DrawerState.java b/src/main/java/TP5/state/DrawerState.java new file mode 100644 index 0000000000000000000000000000000000000000..c09f08e3a69b9eb0ba27e55e24a19cb0263a4467 --- /dev/null +++ b/src/main/java/TP5/state/DrawerState.java @@ -0,0 +1,8 @@ +package TP5.state; + +public interface DrawerState { + void mousePressed(DrawerContext context, double x, double y); + void mouseReleased(DrawerContext context, double x, double y); + void mouseMoved(DrawerContext context, double x, double y); + public void paint(DrawerContext context); +} diff --git a/src/main/java/TP5/state/NullDrawerState.java b/src/main/java/TP5/state/NullDrawerState.java new file mode 100644 index 0000000000000000000000000000000000000000..ee48c3df11fc34c4be5634ea646d1c21417c70f7 --- /dev/null +++ b/src/main/java/TP5/state/NullDrawerState.java @@ -0,0 +1,17 @@ +package TP5.state; + +public class NullDrawerState implements DrawerState { + @Override + public void mousePressed(DrawerContext context, double x, double y) {} + + @Override + public void mouseReleased(DrawerContext context, double x, double y) {} + + @Override + public void mouseMoved(DrawerContext context, double x, double y) {} + + @Override + public void paint(DrawerContext context) { + + } +} diff --git a/src/main/java/TP5/state/Shapes.java b/src/main/java/TP5/state/Shapes.java new file mode 100644 index 0000000000000000000000000000000000000000..17dba3e0810fc02e109798d75114809152efdda1 --- /dev/null +++ b/src/main/java/TP5/state/Shapes.java @@ -0,0 +1,6 @@ +package TP5.state; + +public enum Shapes { + RECTANGLE, + CIRCLE, +} diff --git a/src/main/java/TP5/state/StateCircle0.java b/src/main/java/TP5/state/StateCircle0.java new file mode 100644 index 0000000000000000000000000000000000000000..6e52b21830ef9c7b75ea9688cb355474f7721357 --- /dev/null +++ b/src/main/java/TP5/state/StateCircle0.java @@ -0,0 +1,29 @@ +package TP5.state; + +import TP5.shape.Circle; + +public class StateCircle0 implements DrawerState { + @Override + public void mousePressed(DrawerContext context, double x, double y) { + Circle circle = new Circle(x, y,0); + circle.setFinished(false); + context.getDrawer().addShape(circle); + context.setState(new StateCircle1(circle)); + + } + + @Override + public void mouseReleased(DrawerContext context, double x, double y) { + + } + + @Override + public void mouseMoved(DrawerContext context, double x, double y) { + + } + + @Override + public void paint(DrawerContext context) { + + } +} diff --git a/src/main/java/TP5/state/StateCircle1.java b/src/main/java/TP5/state/StateCircle1.java new file mode 100644 index 0000000000000000000000000000000000000000..8656bafc57f4c1ba04fbd9e0d60fbf99e1e02c2f --- /dev/null +++ b/src/main/java/TP5/state/StateCircle1.java @@ -0,0 +1,32 @@ +package TP5.state; + +import TP5.shape.Circle; + +public class StateCircle1 implements DrawerState{ + private Circle circle; + + public StateCircle1(Circle circle) { + this.circle = circle; + } + @Override + public void mousePressed(DrawerContext context, double x, double y) {} + + @Override + public void mouseReleased(DrawerContext context, double x, double y) { + circle.setFinished(true); + context.paint(context.getDrawer().getGraphicsContext2D()); + context.setState(new StateCircle0()); + } + + @Override + public void mouseMoved(DrawerContext context, double x, double y) { + double radius = Math.sqrt(Math.pow(x - circle.getX(), 2) + Math.pow(y - circle.getY(), 2)); + circle.setDimensions(circle.getX(), circle.getY(), radius*2, radius*2); + context.paint(context.getDrawer().getGraphicsContext2D()); + } + + @Override + public void paint(DrawerContext context) { + + } +} diff --git a/src/main/java/TP5/state/StateMoveShape.java b/src/main/java/TP5/state/StateMoveShape.java new file mode 100644 index 0000000000000000000000000000000000000000..645c047486cfc4924fe52ab4a8286c684761058c --- /dev/null +++ b/src/main/java/TP5/state/StateMoveShape.java @@ -0,0 +1,41 @@ +package TP5.state; + +import TP5.shape.Shape; + +public class StateMoveShape implements DrawerState{ + private Shape selectedShape; + private double previousX, previousY; + + @Override + public void mousePressed(DrawerContext context, double x, double y) { + selectedShape = context.getDrawer().shapeContains(x,y); + System.out.println("selectedShape : " + selectedShape); + if(selectedShape != null) { + previousX = x; + previousY = y; + } + + } + + @Override + public void mouseReleased(DrawerContext context, double x, double y) { + selectedShape = null; + } + + @Override + public void mouseMoved(DrawerContext context, double x, double y) { + if(selectedShape != null) { + double deltaX = x - previousX; + double deltaY = y - previousY; + selectedShape.translate(deltaX, deltaY); + previousX = x; + previousY = y; + context.getDrawer().repaint(); + } + } + + @Override + public void paint(DrawerContext context) { + + } +} diff --git a/src/main/java/TP5/state/StateRectangle0.java b/src/main/java/TP5/state/StateRectangle0.java new file mode 100644 index 0000000000000000000000000000000000000000..54166ad7277c66b2da2d5bc5214aebd9fe1b08a8 --- /dev/null +++ b/src/main/java/TP5/state/StateRectangle0.java @@ -0,0 +1,30 @@ +package TP5.state; + +import TP5.shape.Rectangle; + +public class StateRectangle0 implements DrawerState{ + public StateRectangle0() { } + + @Override + public void mousePressed(DrawerContext context, double x, double y) { + Rectangle rectangle = new Rectangle(x, y,0,0); + rectangle.setFinished(false); + context.getDrawer().addShape(rectangle); + context.setState(new StateRectangle1(rectangle)); + } + + @Override + public void mouseReleased(DrawerContext context, double x, double y) { + + } + + @Override + public void mouseMoved(DrawerContext context, double x, double y) { + + } + + @Override + public void paint(DrawerContext context) { + + } +} diff --git a/src/main/java/TP5/state/StateRectangle1.java b/src/main/java/TP5/state/StateRectangle1.java new file mode 100644 index 0000000000000000000000000000000000000000..c524e01ec59aa3d55616ac588583440026c77198 --- /dev/null +++ b/src/main/java/TP5/state/StateRectangle1.java @@ -0,0 +1,35 @@ +package TP5.state; + +import TP5.shape.Rectangle; + +public class StateRectangle1 implements DrawerState { + private Rectangle rectangle; + private double startX, startY; + public StateRectangle1(Rectangle rectangle) { + this.rectangle = rectangle; + this.startX = rectangle.getX(); + this.startY = rectangle.getY(); + } + @Override + public void mousePressed(DrawerContext context, double x, double y) {} + + @Override + public void mouseReleased(DrawerContext context, double x, double y) { + rectangle.setFinished(true); + context.paint(context.getDrawer().getGraphicsContext2D()); + context.setState(new StateRectangle0()); + } + + @Override + public void mouseMoved(DrawerContext context, double x, double y) { + double width = x - startX; + double height = y - startY; + rectangle.setDimensions(startX,startY,width,height); + context.paint(context.getDrawer().getGraphicsContext2D()); + } + + @Override + public void paint(DrawerContext context) { + + } +} diff --git a/src/main/java/TP7/serializer/App.java b/src/main/java/TP7/serializer/App.java new file mode 100644 index 0000000000000000000000000000000000000000..7b0661778ebd01f95e03ad56bc52df91c3981452 --- /dev/null +++ b/src/main/java/TP7/serializer/App.java @@ -0,0 +1,31 @@ +package TP7.serializer; + +import javafx.application.Application; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.stage.Stage; + +public class App extends Application { + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(Stage primaryStage) { + Group root = new Group(); + DrawerWithSave container = new DrawerWithSave(800, 600); + root.getChildren().add(container); + primaryStage.setScene(new Scene(root)); + primaryStage.show(); + Button save = new Button("save"); + root.getChildren().add(save); + save.setLayoutX(0); + save.setLayoutY(0); + root.setOnKeyPressed(event->container.context.keyPressed(event)); + //save.setOnKeyPressed(event->container.context.keyPressed(event)); + save.setOnAction(event -> container.write()); + + } +} \ No newline at end of file diff --git a/src/main/java/TP7/serializer/CircleSerializer.java b/src/main/java/TP7/serializer/CircleSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..cc3eb10b459c145125e6bbe3585a082b3266912e --- /dev/null +++ b/src/main/java/TP7/serializer/CircleSerializer.java @@ -0,0 +1,24 @@ +package TP7.serializer; + +import TP7.shape.Circle; + +public class CircleSerializer implements ShapeSerializer<Circle> { + @Override + public String code() { + return "Circle"; + } + + @Override + public String serialize(Circle shape) { + return String.format("%f %f %f", shape.getX(), shape.getY(), shape.getRadius()); + } + + @Override + public Circle unserialize(String s) { + String[] split = s.split(" "); + double x = Double.parseDouble(split[0]); + double y = Double.parseDouble(split[1]); + double radius = Double.parseDouble(split[2]); + return new Circle(x, y, radius); + } +} diff --git a/src/main/java/TP7/serializer/DrawerWithSave.java b/src/main/java/TP7/serializer/DrawerWithSave.java new file mode 100644 index 0000000000000000000000000000000000000000..f1bdad54e7806a66d3e7b5034e6f9cab4a577f9a --- /dev/null +++ b/src/main/java/TP7/serializer/DrawerWithSave.java @@ -0,0 +1,48 @@ +package TP7.serializer; + +import javafx.scene.control.Alert; +import javafx.stage.FileChooser; + +import java.io.File; +import java.io.IOException; + + +public class DrawerWithSave extends TP7.state.Drawer { + + public DrawerWithSave(int width, int height) { + super(width, height); + } + + void write(){ + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Save"); + File file = fileChooser.showSaveDialog(getScene().getWindow()); + if (file == null) return; + try { + ShapeWriter.write(file, super.shapes); + } + catch (IOException e) { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Error Dialog"); + alert.setHeaderText(null); + alert.setContentText("Ooops, there was an error!"); + alert.showAndWait(); + } + } + public void load() { + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Load"); + File file = fileChooser.showOpenDialog(getScene().getWindow()); + if (file == null) return; + try { + super.shapes = ShapeReader.read(file); + repaint(); + } catch (IOException e) { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Error Dialog"); + alert.setHeaderText(null); + alert.setContentText("Ooops, there was an error!"); + alert.showAndWait(); + } + } +} diff --git a/src/main/java/TP7/serializer/RectangleSerializer.java b/src/main/java/TP7/serializer/RectangleSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..78106956bb6e2fa4c4d7bb83637d193d104e397a --- /dev/null +++ b/src/main/java/TP7/serializer/RectangleSerializer.java @@ -0,0 +1,25 @@ +package TP7.serializer; + +import TP7.shape.Rectangle; + +public class RectangleSerializer implements ShapeSerializer<Rectangle> { + @Override + public String code() { + return "Rectangle"; + } + + @Override + public String serialize(Rectangle shape) { + return String.format("%f %f %f %f", shape.getX(), shape.getY(), shape.getWidth(), shape.getHeight()); + } + + @Override + public Rectangle unserialize(String s) { + String[] split = s.split(" "); + double x = Double.parseDouble(split[0]); + double y = Double.parseDouble(split[1]); + double width = Double.parseDouble(split[2]); + double height = Double.parseDouble(split[3]); + return new Rectangle(x, y, width, height); + } +} diff --git a/src/main/java/TP7/serializer/ShapeReader.java b/src/main/java/TP7/serializer/ShapeReader.java new file mode 100644 index 0000000000000000000000000000000000000000..5042f8d222081def5653db5dfaef3f1eb6f458f8 --- /dev/null +++ b/src/main/java/TP7/serializer/ShapeReader.java @@ -0,0 +1,40 @@ +package TP7.serializer; + +import TP7.shape.Circle; +import TP7.shape.Shape; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ShapeReader { + + private static final Map<String, ShapeSerializer<?>> serializers = new HashMap<>(); + + static { + serializers.put("circle", new CircleSerializer()); + serializers.put("rectangle", new RectangleSerializer()); + } + public static List<Shape> read(File file) throws IOException { + List<Shape> shapes = new ArrayList<>(); + try(BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) { + String line ; + while ((line = bufferedReader.readLine()) != null) { + String[] parts = line.split(" ",2); + String code = parts[0]; + String data = parts[1]; + ShapeSerializer<?> serializer = serializers.get(code); + if (serializer != null) { + Shape shape = serializer.unserialize(data); + shapes.add(shape); + } + } + return shapes; + } + } +} diff --git a/src/main/java/TP7/serializer/ShapeSerializer.java b/src/main/java/TP7/serializer/ShapeSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..8db3d2d52254df0b063f8eccc95a5a814996a6de --- /dev/null +++ b/src/main/java/TP7/serializer/ShapeSerializer.java @@ -0,0 +1,9 @@ +package TP7.serializer; + +import TP7.shape.Shape; + +public interface ShapeSerializer<S extends Shape> { + String code(); + String serialize(S shape); + S unserialize(String s); +} diff --git a/src/main/java/TP7/serializer/ShapeVisitor.java b/src/main/java/TP7/serializer/ShapeVisitor.java new file mode 100644 index 0000000000000000000000000000000000000000..b86f765fc55945b1a223fad13b7b270a49cccf57 --- /dev/null +++ b/src/main/java/TP7/serializer/ShapeVisitor.java @@ -0,0 +1,10 @@ +package TP7.serializer; + +import TP7.shape.Circle; +import TP7.shape.Rectangle; + + +public interface ShapeVisitor { + void visit(Circle circle); + void visit(Rectangle rectangle); +} diff --git a/src/main/java/TP7/serializer/ShapeWriter.java b/src/main/java/TP7/serializer/ShapeWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..b678767ce9b713138df6c9c101cceb3f3fb81c21 --- /dev/null +++ b/src/main/java/TP7/serializer/ShapeWriter.java @@ -0,0 +1,39 @@ +package TP7.serializer; + +import TP7.shape.Circle; +import TP7.shape.Rectangle; +import TP7.shape.Shape; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.List; + +public class ShapeWriter implements ShapeVisitor { + + private PrintWriter printWriter; + + public ShapeWriter(PrintWriter printWriter) { + this.printWriter = printWriter; + } + + public static void write (File file, List<Shape> shapes) throws IOException { + try(PrintWriter printWriter = new PrintWriter(file)){ + ShapeWriter shapeWriter = new ShapeWriter(printWriter); + + for (Shape shape : shapes) { + shape.accept(shapeWriter); + } + } + } + + @Override + public void visit(Circle circle) { + printWriter.printf("Circle %f %f %f%n", circle.getX(), circle.getY(), circle.getRadius()); + } + + @Override + public void visit(Rectangle rectangle) { + printWriter.printf("Rectangle %f %f %f %f%n", rectangle.getX(), rectangle.getY(), rectangle.getWidth() ,rectangle.getHeight()); + } +} diff --git a/src/main/java/TP7/shape/App.java b/src/main/java/TP7/shape/App.java new file mode 100644 index 0000000000000000000000000000000000000000..3d8a8c3ce40c679283d604c6ffd1827ff0acf4bc --- /dev/null +++ b/src/main/java/TP7/shape/App.java @@ -0,0 +1,27 @@ +package TP7.shape; + +import javafx.application.Application; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.stage.Stage; + + +public class App extends Application { + + @Override + public void start(Stage primaryStage) { + Drawer drawer = new Drawer(600, 400); + + Group root = new Group(); + root.getChildren().add(drawer.getCanvas()); + + Scene scene = new Scene(root, 600, 400); + + primaryStage.setTitle("JavaFX Drawer"); + primaryStage.setScene(scene); + primaryStage.show(); + } + public static void main(String[] args) { + launch(args); + } +} \ No newline at end of file diff --git a/src/main/java/TP7/shape/Circle.java b/src/main/java/TP7/shape/Circle.java new file mode 100644 index 0000000000000000000000000000000000000000..7a4eb2156244645b6cd121878a0b00744d90a567 --- /dev/null +++ b/src/main/java/TP7/shape/Circle.java @@ -0,0 +1,87 @@ +package TP7.shape; + +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; +import TP7.serializer.ShapeVisitor; + +public class Circle implements Shape { + + private double radius, x, y; + private boolean isFinished; + + public Circle(double x, double y, double radius) { + this.x = x; + this.y = y; + this.radius = radius; + this.isFinished = true; + } + + + @Override + public void paint(GraphicsContext graphicsContext) { + graphicsContext.setStroke(Color.BLACK); + graphicsContext.setLineWidth(2); + if (isFinished) { + graphicsContext.setFill(Color.GREEN.deriveColor(0,1,1,0.5)); + graphicsContext.fillOval(x - radius, y - radius, 2 * radius, 2 * radius); + } + graphicsContext.strokeOval(x - radius, y - radius, 2 * radius, 2 * radius); + } + + @Override + public boolean contains(double x, double y) { + double dx = x - this.x; + double dy = y - this.y; + return Math.sqrt(dx * dx + dy * dy) <= radius; + } + + @Override + public void translate(double dx, double dy) { + this.x += dx; + this.y += dy; + } + + @Override + public boolean isFinished() { + return isFinished; + } + + @Override + public void accept(ShapeVisitor visitor) { + visitor.visit(this); + } + + public void setX(double x) { + this.x = x; + } + + public void setY(double y) { + this.y = y; + } + + public void setFinished(boolean finished) { + isFinished = finished; + } + + public void updateRadius(double newX, double newY) { + this.radius = Math.sqrt(Math.pow(newX - this.x, 2) + Math.pow(newY - this.y, 2)); + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public void setDimensions(double x, double y, double width, double height){ + this.x = x; + this.y = y; + this.radius = width/2; + } + + public double getRadius() { + return radius; + } +} diff --git a/src/main/java/TP7/shape/Drawer.java b/src/main/java/TP7/shape/Drawer.java new file mode 100644 index 0000000000000000000000000000000000000000..cc3809103e2415c507d745b5de74aaa93a764096 --- /dev/null +++ b/src/main/java/TP7/shape/Drawer.java @@ -0,0 +1,120 @@ +package TP7.shape; + + +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.input.KeyCode; +import javafx.scene.input.MouseButton; +import TP7.state.DrawerContext; +import TP7.state.StateMoveShape; + +import java.util.ArrayList; +import java.util.List; + +public class Drawer { + private List<Shape> shapes; +// private double width; +// private double height; + private Canvas canvas; + private GraphicsContext gc; + + private String currentShapeType = "rectangle"; + private Shape tempShape = null; + private boolean isFinished = false; + public DrawerContext context; + + + public Drawer(double width, double height) { +// this.width = width; +// this.height = height; + shapes = new ArrayList<>(); + canvas = new Canvas(width,height); + gc = canvas.getGraphicsContext2D(); + setupMouseHandlers(); + setupKeyHandlers(); + } + + public void add(Shape shape) { + shapes.add(shape); + } + public void repaint(){ + gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); + for(Shape shape : shapes){ + shape.paint(gc); + } + if (tempShape != null){ + tempShape.paint(gc); + } + } + + private void setupMouseHandlers(){ + canvas.setOnMousePressed(event -> { + if(event.getButton() == MouseButton.PRIMARY){ + double x = event.getX(); + double y = event.getY(); + // tempShape = new Rectangle(x, y, 0, 0); + System.out.println(currentShapeType); + if (currentShapeType.equals("rectangle")) { + tempShape = new Rectangle(x, y, 0, 0); + }else if (currentShapeType.equals("circle")) { + tempShape = new Circle(x, y, 0); + } + } + }); + + canvas.setOnMouseDragged(event ->{ + if (tempShape != null) { + double x = event.getX(); + double y = event.getY(); + if (tempShape instanceof Rectangle){ + ((Rectangle) tempShape).updateSize(x,y); + }else if (tempShape instanceof Circle){ + ((Circle) tempShape).updateRadius(x,y); + } + repaint(); + } + }); + + canvas.setOnMouseReleased(event -> { + if(event.getButton() == MouseButton.PRIMARY && tempShape != null){ + shapes.add(tempShape); + if (tempShape instanceof Rectangle){ + ((Rectangle) tempShape).setFinished(true); + }else if (tempShape instanceof Circle){ + + ((Circle) tempShape).setFinished(true); + } + repaint(); + tempShape = null; + } + }); + } + private void setupKeyHandlers(){ + canvas.setFocusTraversable(true); + canvas.setOnKeyPressed(event -> { + if (event.getCode() == KeyCode.R){ + currentShapeType = "rectangle"; + System.out.println("Current shape type is: " + currentShapeType); + }else if (event.getCode() == KeyCode.C){ + currentShapeType = "circle"; + System.out.println("Current shape type is: " + currentShapeType); + } else if (event.getCode() == KeyCode.M) { + currentShapeType = null ; + } + }); + } + + /* public Shape shapeContaining(double x, double y){ + for(Shape shape : shapes){ + if (shape.contains(x, y)){ + return shape; + } + } + return null; + }*/ + + + public Canvas getCanvas() { + return canvas; + } +} diff --git a/src/main/java/TP7/shape/Rectangle.java b/src/main/java/TP7/shape/Rectangle.java new file mode 100644 index 0000000000000000000000000000000000000000..e0cc3fa49ab05b771e43c8c12b7e97da32a57d1e --- /dev/null +++ b/src/main/java/TP7/shape/Rectangle.java @@ -0,0 +1,102 @@ +package TP7.shape; + +import javafx.geometry.Point2D; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; +import TP7.serializer.ShapeVisitor; + +public class Rectangle implements Shape{ + + private double x,y,width, height; + private boolean isFinished; + public Color fillColor; + + public Rectangle(double x, double y, double width, double height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + this.isFinished = true; + } + + @Override + public void paint(GraphicsContext graphicsContext) { + graphicsContext.setStroke(Color.BLACK); + graphicsContext.setLineWidth(2); + if(isFinished){ + graphicsContext.setFill(Color.RED.deriveColor(0,1,1,0.5)); + graphicsContext.fillRect(x, y, width, height); + } + graphicsContext.strokeRect(x, y, width, height); + + } + + @Override + public boolean contains(double x, double y) { + return x>= this.x && x<= this.x + this.width + && y>= this.y && y<= this.y + this.height; + } + + @Override + public void translate(double dx, double dy) { + x += dx; + y += dy; + } + + @Override + public boolean isFinished() { + return isFinished; + } + + @Override + public void accept(ShapeVisitor visitor) { + visitor.visit(this); + } + + + public void updateSize(double newX, double newY) { + this.width = Math.abs(newX - this.x); + this.height = Math.abs(newY - this.y); + if (newX < this.x && newY < this.y) { + this.x = newX; + this.y = newY; + } + } + + public Color getFillColor() { + return fillColor; + } + + public void setFinished(boolean finished) { + isFinished = finished; + } + + public void setFillColor(Color fillColor) { + this.fillColor = fillColor; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public void setDimensions(double x, double y, double width, double height) { + this.x = x; + this.y = y; + this.width = Math.abs(width); + this.height = Math.abs(height); + if(width < 0 ){ this.x += width;} + if(height < 0){ this.y += height;} + } + + public double getWidth() { + return width; + } + + public double getHeight() { + return height; + } +} diff --git a/src/main/java/TP7/shape/Shape.java b/src/main/java/TP7/shape/Shape.java new file mode 100644 index 0000000000000000000000000000000000000000..4c9f230fd6da34d1a1693e76306dbaa4a13edf66 --- /dev/null +++ b/src/main/java/TP7/shape/Shape.java @@ -0,0 +1,14 @@ +package TP7.shape; + +import javafx.geometry.Point2D; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; +import TP7.serializer.ShapeVisitor; + +public interface Shape { + void paint(GraphicsContext graphicsContext); + boolean contains(double x, double y); + void translate(double dx, double dy); + boolean isFinished(); + void accept(ShapeVisitor visitor); +} diff --git a/src/main/java/TP7/state/App.java b/src/main/java/TP7/state/App.java new file mode 100644 index 0000000000000000000000000000000000000000..d26870fb1cfa77f40b07401e9ded490cadbd4aca --- /dev/null +++ b/src/main/java/TP7/state/App.java @@ -0,0 +1,24 @@ +package TP7.state; + +import javafx.application.Application; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.stage.Stage; +import TP7.shape.Circle; + +public class App extends Application { + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(Stage primaryStage) { + Group root = new Group(); + Drawer container = new Drawer(800, 600); + + root.getChildren().add(container); + primaryStage.setScene(new Scene(root)); + primaryStage.show(); + } +} \ No newline at end of file diff --git a/src/main/java/TP7/state/Drawer.java b/src/main/java/TP7/state/Drawer.java new file mode 100644 index 0000000000000000000000000000000000000000..dfe52408a0c5d91c1d6cce7b2488d93b938be0a4 --- /dev/null +++ b/src/main/java/TP7/state/Drawer.java @@ -0,0 +1,40 @@ +package TP7.state; + +import javafx.scene.canvas.Canvas; +import TP7.shape.Shape; + +import java.util.ArrayList; +import java.util.List; + + +public class Drawer extends Canvas { + protected List<Shape> shapes = new ArrayList<>(); + public DrawerContext context = new DrawerContext(this); + + public Drawer(int width, int height) { + super(width,height); + setFocusTraversable(true); + setOnMousePressed(event->context.mousePressed(event)); + setOnMouseReleased(event->context.mouseReleased(event)); + setOnMouseMoved(event->context.mouseMoved(event)); + setOnMouseDragged(event->context.mouseMoved(event)); + setOnKeyPressed(event -> context.keyPressed(event)); + } + + public void repaint(){ + this.getGraphicsContext2D().clearRect(0,0,this.getWidth(),this.getHeight()); + for(Shape shape : shapes){ + shape.paint(this.getGraphicsContext2D()); + } + } + public void addShape(Shape shape){ + shapes.add(shape); + repaint(); + } + public Shape shapeContains(double x, double y){ + for(Shape shape : shapes){ + if(shape.contains(x,y)) return shape; + } + return null; + } +} diff --git a/src/main/java/TP7/state/DrawerContext.java b/src/main/java/TP7/state/DrawerContext.java new file mode 100644 index 0000000000000000000000000000000000000000..eff218a47b127d83a8f6d51b23baa67861e76e36 --- /dev/null +++ b/src/main/java/TP7/state/DrawerContext.java @@ -0,0 +1,62 @@ +package TP7.state; + + +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.input.KeyEvent; +import javafx.scene.input.MouseEvent; + +public class DrawerContext { + + Drawer drawer; + DrawerState currentState; + + public DrawerContext(Drawer drawer) { + this.drawer = drawer; + this.currentState = new NullDrawerState(); + } + public void paint(GraphicsContext graphicsContext) { + drawer.repaint(); + } + + void mousePressed(MouseEvent event){ + currentState.mousePressed(this,event.getX(),event.getY()); + + } + + void mouseReleased(MouseEvent event){ + currentState.mouseReleased(this,event.getX(),event.getY()); + } + + void mouseMoved(MouseEvent event){ + currentState.mouseMoved(this,event.getX(),event.getY()); + } + + public void keyPressed(KeyEvent event) { + switch (event.getText()) { + case "c": + setState(new StateCircle0()); + System.out.println("circle state"); + break; + case "r": + setState(new StateRectangle0()); + break; + case "m": + setState(new StateMoveShape()); + System.out.println("state: " + currentState); + break; + default: + setState(new NullDrawerState()); + } + } + public Drawer drawer(){ + return drawer; + } + + public Drawer getDrawer() { + return drawer; + } + + public void setState(DrawerState state) { + this.currentState = state; + } +} diff --git a/src/main/java/TP7/state/DrawerState.java b/src/main/java/TP7/state/DrawerState.java new file mode 100644 index 0000000000000000000000000000000000000000..2bfb22e97b36274a07b864db84ddb11e9990f2a1 --- /dev/null +++ b/src/main/java/TP7/state/DrawerState.java @@ -0,0 +1,8 @@ +package TP7.state; + +public interface DrawerState { + void mousePressed(DrawerContext context, double x, double y); + void mouseReleased(DrawerContext context, double x, double y); + void mouseMoved(DrawerContext context, double x, double y); + public void paint(DrawerContext context); +} diff --git a/src/main/java/TP7/state/NullDrawerState.java b/src/main/java/TP7/state/NullDrawerState.java new file mode 100644 index 0000000000000000000000000000000000000000..29bbe8a036b39ecc4491e6b04b5b1da8b41ca721 --- /dev/null +++ b/src/main/java/TP7/state/NullDrawerState.java @@ -0,0 +1,17 @@ +package TP7.state; + +public class NullDrawerState implements DrawerState { + @Override + public void mousePressed(DrawerContext context, double x, double y) {} + + @Override + public void mouseReleased(DrawerContext context, double x, double y) {} + + @Override + public void mouseMoved(DrawerContext context, double x, double y) {} + + @Override + public void paint(DrawerContext context) { + + } +} diff --git a/src/main/java/TP7/state/Shapes.java b/src/main/java/TP7/state/Shapes.java new file mode 100644 index 0000000000000000000000000000000000000000..b872a3c989ea1452a23a8ddffe548b69c08be597 --- /dev/null +++ b/src/main/java/TP7/state/Shapes.java @@ -0,0 +1,6 @@ +package TP7.state; + +public enum Shapes { + RECTANGLE, + CIRCLE, +} diff --git a/src/main/java/TP7/state/StateCircle0.java b/src/main/java/TP7/state/StateCircle0.java new file mode 100644 index 0000000000000000000000000000000000000000..e026c18dcf8fd0b4c62b3c0afbeb5220bbcf79b7 --- /dev/null +++ b/src/main/java/TP7/state/StateCircle0.java @@ -0,0 +1,29 @@ +package TP7.state; + +import TP7.shape.Circle; + +public class StateCircle0 implements DrawerState { + @Override + public void mousePressed(DrawerContext context, double x, double y) { + Circle circle = new Circle(x, y,0); + circle.setFinished(false); + context.getDrawer().addShape(circle); + context.setState(new StateCircle1(circle)); + + } + + @Override + public void mouseReleased(DrawerContext context, double x, double y) { + + } + + @Override + public void mouseMoved(DrawerContext context, double x, double y) { + + } + + @Override + public void paint(DrawerContext context) { + + } +} diff --git a/src/main/java/TP7/state/StateCircle1.java b/src/main/java/TP7/state/StateCircle1.java new file mode 100644 index 0000000000000000000000000000000000000000..88a3364c573b33d17282cd2d8f1c57728de82421 --- /dev/null +++ b/src/main/java/TP7/state/StateCircle1.java @@ -0,0 +1,32 @@ +package TP7.state; + +import TP7.shape.Circle; + +public class StateCircle1 implements DrawerState{ + private Circle circle; + + public StateCircle1(Circle circle) { + this.circle = circle; + } + @Override + public void mousePressed(DrawerContext context, double x, double y) {} + + @Override + public void mouseReleased(DrawerContext context, double x, double y) { + circle.setFinished(true); + context.paint(context.getDrawer().getGraphicsContext2D()); + context.setState(new StateCircle0()); + } + + @Override + public void mouseMoved(DrawerContext context, double x, double y) { + double radius = Math.sqrt(Math.pow(x - circle.getX(), 2) + Math.pow(y - circle.getY(), 2)); + circle.setDimensions(circle.getX(), circle.getY(), radius*2, radius*2); + context.paint(context.getDrawer().getGraphicsContext2D()); + } + + @Override + public void paint(DrawerContext context) { + + } +} diff --git a/src/main/java/TP7/state/StateMoveShape.java b/src/main/java/TP7/state/StateMoveShape.java new file mode 100644 index 0000000000000000000000000000000000000000..c1c3994b9bbf772eee5440c7986984888d793e09 --- /dev/null +++ b/src/main/java/TP7/state/StateMoveShape.java @@ -0,0 +1,41 @@ +package TP7.state; + +import TP7.shape.Shape; + +public class StateMoveShape implements DrawerState{ + private Shape selectedShape; + private double previousX, previousY; + + @Override + public void mousePressed(DrawerContext context, double x, double y) { + selectedShape = context.getDrawer().shapeContains(x,y); + System.out.println("selectedShape : " + selectedShape); + if(selectedShape != null) { + previousX = x; + previousY = y; + } + + } + + @Override + public void mouseReleased(DrawerContext context, double x, double y) { + selectedShape = null; + } + + @Override + public void mouseMoved(DrawerContext context, double x, double y) { + if(selectedShape != null) { + double deltaX = x - previousX; + double deltaY = y - previousY; + selectedShape.translate(deltaX, deltaY); + previousX = x; + previousY = y; + context.getDrawer().repaint(); + } + } + + @Override + public void paint(DrawerContext context) { + + } +} diff --git a/src/main/java/TP7/state/StateRectangle0.java b/src/main/java/TP7/state/StateRectangle0.java new file mode 100644 index 0000000000000000000000000000000000000000..ead84bb4dbac8e3d62870558e3e8e7f9dbdc82f4 --- /dev/null +++ b/src/main/java/TP7/state/StateRectangle0.java @@ -0,0 +1,30 @@ +package TP7.state; + +import TP7.shape.Rectangle; + +public class StateRectangle0 implements DrawerState{ + public StateRectangle0() { } + + @Override + public void mousePressed(DrawerContext context, double x, double y) { + Rectangle rectangle = new Rectangle(x, y,0,0); + rectangle.setFinished(false); + context.getDrawer().addShape(rectangle); + context.setState(new StateRectangle1(rectangle)); + } + + @Override + public void mouseReleased(DrawerContext context, double x, double y) { + + } + + @Override + public void mouseMoved(DrawerContext context, double x, double y) { + + } + + @Override + public void paint(DrawerContext context) { + + } +} diff --git a/src/main/java/TP7/state/StateRectangle1.java b/src/main/java/TP7/state/StateRectangle1.java new file mode 100644 index 0000000000000000000000000000000000000000..446afe61d283564950b80d015bedf7d7195eba24 --- /dev/null +++ b/src/main/java/TP7/state/StateRectangle1.java @@ -0,0 +1,35 @@ +package TP7.state; + +import TP7.shape.Rectangle; + +public class StateRectangle1 implements DrawerState { + private Rectangle rectangle; + private double startX, startY; + public StateRectangle1(Rectangle rectangle) { + this.rectangle = rectangle; + this.startX = rectangle.getX(); + this.startY = rectangle.getY(); + } + @Override + public void mousePressed(DrawerContext context, double x, double y) {} + + @Override + public void mouseReleased(DrawerContext context, double x, double y) { + rectangle.setFinished(true); + context.paint(context.getDrawer().getGraphicsContext2D()); + context.setState(new StateRectangle0()); + } + + @Override + public void mouseMoved(DrawerContext context, double x, double y) { + double width = x - startX; + double height = y - startY; + rectangle.setDimensions(startX,startY,width,height); + context.paint(context.getDrawer().getGraphicsContext2D()); + } + + @Override + public void paint(DrawerContext context) { + + } +}