diff --git a/shapes/.classpath b/shapes/.classpath
new file mode 100755
index 0000000..fceb480
--- /dev/null
+++ b/shapes/.classpath
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/shapes/.gitignore b/shapes/.gitignore
new file mode 100644
index 0000000..cdd27a2
--- /dev/null
+++ b/shapes/.gitignore
@@ -0,0 +1,21 @@
+!/src/
+/bin/
+*.class
+*.log*
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.ear
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+.DS_Store
+
+# Ignore automatically generated HTML and CSS
+*.html
+*.css
diff --git a/shapes/.project b/shapes/.project
new file mode 100755
index 0000000..c51b6c7
--- /dev/null
+++ b/shapes/.project
@@ -0,0 +1,17 @@
+
+
+ Shapes
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/shapes/.settings/org.eclipse.jdt.core.prefs b/shapes/.settings/org.eclipse.jdt.core.prefs
new file mode 100755
index 0000000..3a21537
--- /dev/null
+++ b/shapes/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/shapes/README.md b/shapes/README.md
new file mode 100644
index 0000000..13602df
--- /dev/null
+++ b/shapes/README.md
@@ -0,0 +1,3 @@
+# Shapes
+
+la classe
\ No newline at end of file
diff --git a/shapes/index.html b/shapes/index.html
new file mode 100644
index 0000000..b024700
--- /dev/null
+++ b/shapes/index.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+TP Shape COLICCHIO et GASSER
+
+
+
+
+
+
+
+hello
+
+
+
+
diff --git a/shapes/pom.xml b/shapes/pom.xml
new file mode 100644
index 0000000..b88810c
--- /dev/null
+++ b/shapes/pom.xml
@@ -0,0 +1,12 @@
+
+
+ 4.0.0
+
+ fr.uha.graphics
+ Shapes
+ 1.0-SNAPSHOT
+
+
+
\ No newline at end of file
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/SCircle.java b/shapes/src/main/java/fr/uha/graphics/shapes/SCircle.java
new file mode 100755
index 0000000..50e5315
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/SCircle.java
@@ -0,0 +1,81 @@
+package fr.uha.graphics.shapes;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.util.logging.Logger;
+
+import fr.uha.graphics.shapes.ui.ShapesController;
+
+public class SCircle extends Shape {
+
+ private static final int DEFAULT_RADIUS = 1;
+ private int radius;
+ private Point loc;
+
+ public SCircle() {
+ this.radius = DEFAULT_RADIUS;
+ this.loc = new Point();
+ }
+
+ public SCircle(Point loc, int radius) {
+ this.loc = loc;
+ this.radius = radius;
+ }
+
+ @Override
+ public Point getLoc() {
+ return this.loc;
+ }
+
+ @Override
+ public void setLoc(Point p) {
+ this.loc = p;
+ }
+
+ @Override
+ public void translate(int dx, int dy) {
+ this.loc.translate(dx, dy);
+ }
+
+ public int getRadius() {
+ return this.radius;
+ }
+
+ @Override
+ public Rectangle getBounds() {
+ return new Rectangle(loc.x, loc.y, radius, radius);
+ }
+
+ @Override
+ public void accept(ShapeVisitor sv) {
+ sv.visitCircle(this);
+ }
+
+ @Override
+ public String toString() {
+ return "SCircle [radius=" + radius + ", loc=" + loc + "]";
+ }
+
+ @Override
+ public String htmlShape() {
+ return "";
+ }
+
+ @Override
+ public String cssShape() {
+ StringBuilder strBuilder = new StringBuilder(".circle" + this.hashCode() + "{ ");
+ strBuilder.append("position: absolute;");
+ strBuilder.append("top:" + this.loc.y + "px;");
+ strBuilder.append("left:" + this.loc.x + "px;");
+ strBuilder.append("width:" + this.radius + "px;");
+ strBuilder.append("height:" + this.radius + "px;");
+ strBuilder.append("border-radius:" + this.radius/2 + "px;");
+ strBuilder.append("-webkit-border-radius:" + this.radius/2 + "px;");
+ strBuilder.append("-o-border-radius:" + this.radius/2 + "px;");
+ strBuilder.append("-moz-border-radius:" + this.radius/2 + "px;");
+ strBuilder.append(this.attributesCss());
+ strBuilder.append(" }");
+ return strBuilder.toString();
+ }
+
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/SCollection.java b/shapes/src/main/java/fr/uha/graphics/shapes/SCollection.java
new file mode 100755
index 0000000..c45e452
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/SCollection.java
@@ -0,0 +1,103 @@
+package fr.uha.graphics.shapes;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.logging.Logger;
+
+import fr.uha.graphics.shapes.attributes.Attributes;
+import fr.uha.graphics.shapes.ui.Editor;
+
+public class SCollection extends Shape {
+
+ private static final Logger LOGGER = Logger.getLogger(SCollection.class.getName());
+
+ private List childShapes = new ArrayList();
+ private Point loc;
+
+ public Iterator getIterator() {
+ return childShapes.listIterator();
+ }
+
+ public void add(Shape s) {
+ // LOGGER.log(Level.INFO, "Adding to collection : {0}", s.toString());
+ childShapes.add(s);
+ relocate();
+ }
+
+ public void remove(Shape s) {
+ if (childShapes.remove(s)) relocate();
+ }
+
+ @Override
+ public Point getLoc() {
+ return this.loc;
+ }
+
+ @Override
+ public void setLoc(Point p) {
+ this.loc = p;
+ }
+
+ @Override
+ public void translate(int dx, int dy) {
+ for (Shape s : this.childShapes) {
+ s.translate(dx, dy);
+ }
+ relocate();
+ }
+
+ @Override
+ public void addAttributes(Attributes attrs) {
+ super.addAttributes(attrs);
+ // Propagate all atrributes to the members of SCollection.
+ for (Shape s : this.childShapes) s.addAttributes(attrs);
+ }
+
+ @Override
+ public Rectangle getBounds() {
+ Rectangle bounds;
+ try {
+ bounds = childShapes.get(0).getBounds();
+ for (Shape s : childShapes)
+ bounds = bounds.union(s.getBounds());
+ } catch (IndexOutOfBoundsException e){
+ // If the SCollection is empty, set the bounds to fill the window
+ return new Rectangle(Editor.WIN_SIZE);
+ }
+ return bounds;
+ }
+
+ @Override
+ public void accept(ShapeVisitor sv) {
+ sv.visitCollection(this);
+ }
+
+ private void relocate() {
+ // Recalculate the location of the SCollection (Upper-left corner)
+ this.loc = this.getBounds().getLocation();
+ }
+
+ @Override
+ public String htmlShape() {
+ StringBuilder prepare= new StringBuilder();
+ for(Iterator it=childShapes.iterator();it.hasNext();){
+ Shape current = it.next();
+ prepare.append(current.htmlShape());
+ }
+ return prepare.toString();
+ }
+
+ @Override
+ public String cssShape() {
+ StringBuilder prepare= new StringBuilder();
+ for(Iterator it=childShapes.iterator();it.hasNext();){
+ Shape current = it.next();
+ prepare.append(current.cssShape());
+ }
+ return prepare.toString();
+ }
+
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/SRectangle.java b/shapes/src/main/java/fr/uha/graphics/shapes/SRectangle.java
new file mode 100755
index 0000000..ef57ecb
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/SRectangle.java
@@ -0,0 +1,66 @@
+package fr.uha.graphics.shapes;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+
+import fr.uha.graphics.shapes.attributes.ColorAttributes;
+
+public class SRectangle extends Shape {
+ private Rectangle rect;
+
+ public SRectangle(Point loc, int width, int length) {
+ this.rect = new Rectangle(loc.x, loc.y, width, length);
+ }
+
+ public Rectangle getRect() {
+ return this.rect;
+ }
+
+ @Override
+ public Point getLoc() {
+ return this.rect.getLocation();
+ }
+
+ @Override
+ public void setLoc(Point p) {
+ this.rect.setLocation(p);
+ }
+
+ @Override
+ public void translate(int dx, int dy) {
+ this.rect.translate(dx, dy);
+
+ }
+
+ @Override
+ public Rectangle getBounds() {
+ return this.rect.getBounds();
+ }
+
+ @Override
+ public void accept(ShapeVisitor sv) {
+ sv.visitRectangle(this);
+ }
+
+ @Override
+ public String toString() {
+ return "SRectangle [x=" + rect.x + " y=" + rect.y + " height=" + rect.height + " width=" + rect.width + "]";
+ }
+
+ @Override
+ public String htmlShape() {
+ return "";
+ }
+
+ @Override
+ public String cssShape() {
+ StringBuilder strBuilder = new StringBuilder(".rectangle" + this.hashCode() + "{ ");
+ strBuilder.append("position:absolute;");
+ strBuilder.append("top:" + this.getLoc().y + "px;");
+ strBuilder.append("left:" + this.getLoc().x + "px;");
+ strBuilder.append("width:" + this.rect.width + "px;");
+ strBuilder.append("height:" + this.rect.height + "px;");
+ strBuilder.append(this.attributesCss() + " }");
+ return strBuilder.toString();
+ }
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/SSelection.java b/shapes/src/main/java/fr/uha/graphics/shapes/SSelection.java
new file mode 100644
index 0000000..e85d5c2
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/SSelection.java
@@ -0,0 +1,35 @@
+package fr.uha.graphics.shapes;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+
+public class SSelection extends SRectangle {
+
+ public SSelection(){
+ super(new Point(0, 0), 0, 0);
+ }
+
+ public SSelection(Point loc, int width, int length) {
+ super(loc, width, length);
+ }
+
+ public void resize(int width, int height){
+ this.getRect().setSize(width, height);
+ }
+
+ @Override
+ public String toString() {
+ Rectangle rect = this.getRect();
+ return "SSelection [x=" + rect.x + " y=" + rect.y + " height=" + rect.height + " width=" + rect.width + "]";
+ }
+
+ @Override
+ public String cssShape() {
+ return "";
+ }
+
+ @Override
+ public String htmlShape() {
+ return "";
+ }
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/SText.java b/shapes/src/main/java/fr/uha/graphics/shapes/SText.java
new file mode 100755
index 0000000..795f0a0
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/SText.java
@@ -0,0 +1,89 @@
+package fr.uha.graphics.shapes;
+
+import java.awt.Canvas;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Point;
+import java.awt.Rectangle;
+
+import fr.uha.graphics.shapes.attributes.ColorAttributes;
+import fr.uha.graphics.shapes.attributes.FontAttributes;
+
+public class SText extends Shape {
+
+ private String text;
+ private Point loc;
+
+ public SText(Point loc, String string) {
+ this.text = string;
+ this.loc = loc;
+ }
+
+ public String getText() {
+ return this.text;
+ }
+
+ @Override
+ public Point getLoc() {
+ return this.loc;
+ }
+
+ @Override
+ public void setLoc(Point loc) {
+ this.loc = loc;
+ }
+
+ @Override
+ public void translate(int dx, int dy) {
+ this.loc.translate(dx, dy);
+ }
+
+ @Override
+ public Rectangle getBounds() {
+ FontAttributes attrs = (FontAttributes) this.getAttributes(FontAttributes.ID);
+ Canvas can = new Canvas();
+ FontMetrics fontMetrics = can.getFontMetrics(attrs.font);
+
+ int w = fontMetrics.stringWidth(this.text);
+ int h = attrs.font.getSize();
+ return new Rectangle(loc.x, loc.y - h, w, h);
+ }
+
+ @Override
+ public void accept(ShapeVisitor sv) {
+ sv.visitText(this);
+ }
+
+ @Override
+ public String htmlShape() {
+ return ""+getText()+"
";
+ }
+
+ @Override
+ public String cssShape() {
+ Rectangle bounds = this.getBounds();
+ FontAttributes fontAttrs = (FontAttributes) this.getAttributes(FontAttributes.ID);
+ String hexFontColor = String.format("#%02x%02x%02x",
+ fontAttrs.fontColor.getRed(),
+ fontAttrs.fontColor.getGreen(),
+ fontAttrs.fontColor.getBlue());
+ Font font = fontAttrs.font;
+
+ StringBuilder strBuilder = new StringBuilder(".text" + this.hashCode() + "{ ");
+ strBuilder.append("position: absolute;");
+ strBuilder.append("top: " + this.loc.y + "px;");
+ strBuilder.append("left: " + this.loc.x + "px;");
+ strBuilder.append("width: " + bounds.width + "px;");
+ strBuilder.append("height: " + bounds.height + "px;");
+ strBuilder.append("font-family: \"" + font.getName() + "\";");
+ strBuilder.append("font-size: " + font.getSize() + "px;");
+ strBuilder.append("color: " + hexFontColor +";");
+ if (font.isBold()) strBuilder.append("font-weight: bold;");
+ if (font.isItalic()) strBuilder.append("font-style: italic;");
+ strBuilder.append(this.attributesCss());
+ strBuilder.append(" }");
+ return strBuilder.toString();
+ }
+
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/STriangle.java b/shapes/src/main/java/fr/uha/graphics/shapes/STriangle.java
new file mode 100644
index 0000000..4ccac73
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/STriangle.java
@@ -0,0 +1,80 @@
+package fr.uha.graphics.shapes;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+
+import fr.uha.graphics.shapes.attributes.ColorAttributes;
+
+public class STriangle extends Shape {
+
+ private static final int DEFAULT_SIZE = 1;
+ private Point loc;
+ private int size;
+
+ public STriangle(){
+ this.size = DEFAULT_SIZE;
+ this.loc = new Point();
+ }
+
+ public STriangle(Point loc, int size){
+ this.loc = loc;
+ this.size = size;
+ }
+
+ @Override
+ public void translate(int dx, int dy) {
+ this.loc.translate(dx, dy);
+ }
+
+ @Override
+ public Point getLoc() {
+ return this.loc;
+ }
+
+ @Override
+ public void setLoc(Point p) {
+ this.loc = p;
+ }
+
+ public int getSize(){
+ return this.size;
+ }
+
+ @Override
+ public Rectangle getBounds() {
+ return new Rectangle(loc.x, loc.y, size, size);
+ }
+
+ @Override
+ public void accept(ShapeVisitor sv) {
+ sv.visitTriangle(this);
+ }
+
+ @Override
+ public String htmlShape() {
+ return "";
+ }
+
+ @Override
+ public String cssShape() {
+ ColorAttributes colAttrs = (ColorAttributes) this.getAttributes(ColorAttributes.ID);
+ String colorString = String.format("#%02x%02x%02x",
+ colAttrs.filledColor.getRed(),
+ colAttrs.filledColor.getGreen(),
+ colAttrs.filledColor.getBlue());
+ StringBuilder strBuilder = new StringBuilder(".triangle" + this.hashCode() + "{ ");
+ strBuilder.append("position: absolute;");
+ strBuilder.append("top: " + this.loc.y + "px;");
+ strBuilder.append("left: " + this.loc.x + "px;");
+ strBuilder.append("width: 0px;");
+ strBuilder.append("height: 0px;");
+ strBuilder.append("border: 0 solid transparent;");
+ strBuilder.append("border-left-width: " + Math.ceil(this.size/1.72) + "px;");
+ strBuilder.append("border-right-width: " + Math.ceil(this.size/1.72) + "px;");
+ strBuilder.append("border-bottom: " + this.size + "px solid " + colorString + ";");
+ strBuilder.append("}");
+
+ return strBuilder.toString();
+ }
+
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/Shape.java b/shapes/src/main/java/fr/uha/graphics/shapes/Shape.java
new file mode 100755
index 0000000..54749ec
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/Shape.java
@@ -0,0 +1,63 @@
+package fr.uha.graphics.shapes;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import fr.uha.graphics.shapes.attributes.Attributes;
+import fr.uha.graphics.shapes.attributes.ColorAttributes;
+
+public abstract class Shape {
+
+ private static final Logger LOGGER = Logger.getLogger(SCollection.class.getName());
+ private Map attributes = new TreeMap();
+
+ public void addAttributes(Attributes attrs) {
+ attributes.put(attrs.getId(), attrs);
+ }
+
+ public Attributes getAttributes(String str) {
+ return attributes.get(str);
+ }
+
+ public String attributesCss(){
+
+ ColorAttributes colAttrs = (ColorAttributes) this.getAttributes(ColorAttributes.ID);
+ String strokedColor = "#ffffff";
+ String filledColor = "#ffffff";
+ if (colAttrs.filledColor != null){
+ filledColor = String.format("#%02x%02x%02x", colAttrs.filledColor.getRed(), colAttrs.filledColor.getGreen(), colAttrs.filledColor.getBlue());
+ }
+ if (colAttrs.strokedColor != null){
+ strokedColor = String.format("#%02x%02x%02x", colAttrs.strokedColor.getRed(), colAttrs.strokedColor.getGreen(), colAttrs.strokedColor.getBlue());
+ }
+
+ if(colAttrs.stroked && colAttrs.filled){
+ return "background: " + filledColor + ";border:1px solid " + strokedColor + ";";
+ }
+ if (colAttrs.stroked){
+ return "background:#ffffff;border:1px solid "+strokedColor+";";
+ }
+ if (colAttrs.filled) {
+ return "background: "+filledColor+";";
+ }
+ return null;
+ }
+
+ public abstract void translate(int dx, int dy);
+
+ public abstract Point getLoc();
+
+ public abstract void setLoc(Point p);
+
+ public abstract Rectangle getBounds();
+
+ public abstract void accept(ShapeVisitor sv);
+
+ public abstract String htmlShape();
+
+ public abstract String cssShape();
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/ShapeVisitor.java b/shapes/src/main/java/fr/uha/graphics/shapes/ShapeVisitor.java
new file mode 100755
index 0000000..02abdbe
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/ShapeVisitor.java
@@ -0,0 +1,15 @@
+package fr.uha.graphics.shapes;
+
+public interface ShapeVisitor {
+ public void visitRectangle(SRectangle rect);
+
+ public void visitCircle(SCircle circle);
+
+ public void visitText(SText text);
+
+ public void visitCollection(SCollection col);
+
+ public void visitTriangle(STriangle sTriangle);
+
+ public void visitSelection(SSelection sel);
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/attributes/Attributes.java b/shapes/src/main/java/fr/uha/graphics/shapes/attributes/Attributes.java
new file mode 100755
index 0000000..b2f93de
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/attributes/Attributes.java
@@ -0,0 +1,5 @@
+package fr.uha.graphics.shapes.attributes;
+
+public abstract class Attributes {
+ public abstract String getId();
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/attributes/ColorAttributes.java b/shapes/src/main/java/fr/uha/graphics/shapes/attributes/ColorAttributes.java
new file mode 100755
index 0000000..c42edec
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/attributes/ColorAttributes.java
@@ -0,0 +1,48 @@
+package fr.uha.graphics.shapes.attributes;
+
+import java.awt.Color;
+
+public class ColorAttributes extends Attributes {
+
+ public static final String ID = "colors";
+
+ public boolean filled;
+ public boolean stroked;
+ public Color strokedColor;
+ public Color filledColor;
+
+ public ColorAttributes(boolean filled, boolean stroked, Color filledColor, Color strokedColor) {
+ this.filled = filled;
+ this.stroked = stroked;
+ this.strokedColor = strokedColor;
+ this.filledColor = filledColor;
+ }
+
+ public ColorAttributes(ColorAttributes colAttrs){
+ // Copy constructor.
+ this.filled = colAttrs.filled;
+ this.stroked = colAttrs.stroked;
+ this.strokedColor = colAttrs.strokedColor;
+ this.filledColor = colAttrs.filledColor;
+ }
+
+ public ColorAttributes() {
+ // Constructor for color attributes with default values
+ this.filled = false;
+ this.stroked = true;
+ this.strokedColor = Color.BLACK;
+ this.filledColor = Color.BLACK;
+ }
+
+ @Override
+ public String getId() {
+ return ID;
+ }
+
+ @Override
+ public String toString() {
+ return "ColorAttributes [filled=" + filled + ", stroked=" + stroked + ", strokedColor=" + strokedColor
+ + ", filledColor=" + filledColor + "]";
+ }
+
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/attributes/FontAttributes.java b/shapes/src/main/java/fr/uha/graphics/shapes/attributes/FontAttributes.java
new file mode 100755
index 0000000..ffee35a
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/attributes/FontAttributes.java
@@ -0,0 +1,34 @@
+package fr.uha.graphics.shapes.attributes;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Rectangle;
+
+public class FontAttributes extends Attributes {
+ public static final String ID = "font";
+
+ public Font font;
+ public Color fontColor;
+
+ public FontAttributes(Font font, Color fontColor) {
+ this.font = font;
+ this.fontColor = fontColor;
+ }
+
+ public FontAttributes() {
+ // Constructor with default font attributes values.
+ this.font = new Font("TimesRoman", Font.PLAIN, 18);
+ this.fontColor = Color.BLACK;
+ }
+
+ @Override
+ public String toString() {
+ return "FontAttributes [font=" + font + ", fontColor=" + fontColor + "]";
+ }
+
+ @Override
+ public String getId() {
+ return ID;
+ }
+
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/attributes/SelectionAttributes.java b/shapes/src/main/java/fr/uha/graphics/shapes/attributes/SelectionAttributes.java
new file mode 100755
index 0000000..0165ed3
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/attributes/SelectionAttributes.java
@@ -0,0 +1,33 @@
+package fr.uha.graphics.shapes.attributes;
+
+public class SelectionAttributes extends Attributes {
+ public static final String ID = "selection";
+
+ private boolean selected;
+
+ public SelectionAttributes() {
+ this.selected = false;
+ }
+
+ public void select() {
+ selected = true;
+ }
+
+ public void unselect() {
+ selected = false;
+ }
+
+ public void toggleSelection() {
+ selected = !selected;
+ }
+
+ public boolean isSelected() {
+ return this.selected;
+ }
+
+ @Override
+ public String getId() {
+ return ID;
+ }
+
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/ui/Editor.java b/shapes/src/main/java/fr/uha/graphics/shapes/ui/Editor.java
new file mode 100755
index 0000000..263cdb0
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/ui/Editor.java
@@ -0,0 +1,210 @@
+package fr.uha.graphics.shapes.ui;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.util.logging.FileHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.SimpleFormatter;
+
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+
+import fr.uha.graphics.shapes.SCircle;
+import fr.uha.graphics.shapes.SCollection;
+import fr.uha.graphics.shapes.SRectangle;
+import fr.uha.graphics.shapes.SSelection;
+import fr.uha.graphics.shapes.SText;
+import fr.uha.graphics.shapes.STriangle;
+import fr.uha.graphics.shapes.attributes.ColorAttributes;
+import fr.uha.graphics.shapes.attributes.FontAttributes;
+import fr.uha.graphics.shapes.attributes.SelectionAttributes;
+import fr.uha.graphics.shapes.ui.menu.MenuAddListener;
+import fr.uha.graphics.shapes.ui.menu.MenuEditListener;
+
+public class Editor extends JFrame {
+ private static final Logger LOGGER = Logger.getLogger(Editor.class.getName());
+ private static FileHandler fh = null;
+ public static final Dimension WIN_SIZE = new Dimension(800, 600);
+
+ private ShapesView sview;
+ private SCollection model;
+ private JMenuBar menubar;
+
+ public Editor() {
+ super("Shapes Editor");
+
+ this.addWindowListener(new java.awt.event.WindowAdapter() {
+ @Override
+ public void windowClosing(java.awt.event.WindowEvent evt) {
+ System.exit(0);
+ }
+ });
+
+ this.buildModel();
+
+ this.sview = new ShapesView(this.model);
+ this.sview.setPreferredSize(WIN_SIZE);
+ this.getContentPane().add(this.sview, java.awt.BorderLayout.CENTER);
+ this.buildMenu();
+ }
+
+ private static void initLogger() {
+ try {
+ fh = new FileHandler("Shapes.log", false);
+ } catch (SecurityException | IOException e) {
+ e.printStackTrace();
+ }
+ Logger l = Logger.getLogger("");
+ fh.setFormatter(new SimpleFormatter());
+ l.addHandler(fh);
+ l.setLevel(Level.INFO);
+ }
+
+ private void buildModel() {
+ this.model = new SCollection();
+ this.model.addAttributes(new SelectionAttributes());
+
+ SSelection sel=new SSelection(new Point (0,0),0,0);
+ sel.addAttributes(new ColorAttributes(false, true, Color.BLACK, Color.BLACK));
+ this.model.add(sel);
+
+ SRectangle r = new SRectangle(new Point(10, 10), 40, 60);
+ r.addAttributes(new ColorAttributes(true, true, Color.BLUE, Color.BLACK));
+ r.addAttributes(new SelectionAttributes());
+ this.model.add(r);
+
+ SCircle c = new SCircle(new Point(100, 100), 30);
+ c.addAttributes(new ColorAttributes(false, true, Color.RED, Color.RED));
+ c.addAttributes(new SelectionAttributes());
+ this.model.add(c);
+
+ SText t = new SText(new Point(150, 150), "hello");
+ t.addAttributes(new ColorAttributes(true, false, Color.YELLOW, Color.BLUE));
+ t.addAttributes(new FontAttributes(new Font("Arial", Font.BOLD, 30), Color.BLUE));
+ t.addAttributes(new SelectionAttributes());
+ this.model.add(t);
+
+ SCollection sc = new SCollection();
+ sc.addAttributes(new SelectionAttributes());
+ r = new SRectangle(new Point(20, 30), 60, 60);
+ r.addAttributes(new ColorAttributes(true, false, Color.MAGENTA, Color.BLUE));
+ r.addAttributes(new SelectionAttributes());
+ sc.add(r);
+
+ c = new SCircle(new Point(150, 100), 40);
+ c.addAttributes(new ColorAttributes(false, true, Color.BLUE, Color.DARK_GRAY));
+ c.addAttributes(new SelectionAttributes());
+ sc.add(c);
+ this.model.add(sc);
+
+ STriangle tri = new STriangle(new Point(200, 200), 50);
+ tri.addAttributes(new ColorAttributes(true, true, Color.YELLOW, Color.BLACK));
+ tri.addAttributes(new SelectionAttributes());
+ this.model.add(tri);
+ }
+
+ private void buildMenu(){
+ this.menubar = new JMenuBar();
+
+ // Add menu
+ JMenu menuFile = new JMenu("File");
+ JMenuItem addRectItem = new JMenuItem("Add SRectangle");
+ JMenuItem addCircleItem = new JMenuItem("Add SCircle");
+ JMenuItem addTriItem = new JMenuItem("Add STriangle");
+ JMenuItem addTextItem = new JMenuItem("Add SText");
+ JMenuItem htmlExportItem = new JMenuItem("Export to HTML");
+ JMenuItem exitItem = new JMenuItem("Exit");
+ addRectItem.addActionListener(new MenuAddListener("SRectangle", model, sview));
+ addCircleItem.addActionListener(new MenuAddListener("SCircle", model, sview));
+ addTriItem.addActionListener(new MenuAddListener("STriangle", model, sview));
+ addTextItem.addActionListener(new MenuAddListener("SText", model, sview));
+ htmlExportItem.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ try {
+ ((ShapesController) sview.getController()).generateHtml();
+ JOptionPane.showMessageDialog(null, "HTML/CSS generated successfully !", "Success",
+ JOptionPane.INFORMATION_MESSAGE);
+ } catch (Exception e) {
+ LOGGER.log(Level.SEVERE, e.getMessage());
+ JOptionPane.showMessageDialog(null, "Error while generating the HTML/CSS. See log for more details",
+ "Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ });
+ exitItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ System.exit(0);
+ }
+ });
+ menuFile.add(addRectItem);
+ menuFile.add(addCircleItem);
+ menuFile.add(addTriItem);
+ menuFile.add(addTextItem);
+ menuFile.addSeparator();
+ menuFile.add(htmlExportItem);
+ menuFile.add(exitItem);
+
+ // Edit menu
+ MenuEditListener editListener = new MenuEditListener(model, sview, sview.getController());
+ JMenu menuEdit = new JMenu("Edit");
+ JMenuItem editColor = new JMenuItem("Change color");
+ JMenuItem editBorderColor = new JMenuItem("Change border color");
+ JMenuItem deleteItem = new JMenuItem("Delete");
+ JMenuItem undoItem = new JMenuItem("Undo");
+ JCheckBoxMenuItem editFill = new JCheckBoxMenuItem("Fill Shape");
+ JCheckBoxMenuItem editBorder = new JCheckBoxMenuItem("Draw border");
+ editColor.addActionListener(editListener);
+ editBorderColor.addActionListener(editListener);
+ deleteItem.addActionListener(editListener);
+ undoItem.addActionListener(editListener);
+ editFill.addActionListener(editListener);
+ editBorder.addActionListener(editListener);
+
+ menuEdit.add(editColor);
+ menuEdit.add(editBorderColor);
+ menuEdit.add(deleteItem);
+ menuEdit.add(undoItem);
+ menuEdit.addSeparator();
+ menuEdit.add(editBorder);
+ menuEdit.add(editFill);
+
+ // About
+ JMenu helpMenu = new JMenu("Help");
+ JMenuItem aboutItem = new JMenuItem("About");
+ aboutItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ JOptionPane.showMessageDialog(null, "This project was created by Alexandre Colicchio and Thibaud Gasser", "About this project",
+ JOptionPane.INFORMATION_MESSAGE);
+ }
+ });
+ helpMenu.add(aboutItem);
+
+ menubar.add(menuFile);
+ menubar.add(menuEdit);
+ menubar.add(helpMenu);
+ this.setJMenuBar(this.menubar);
+ }
+
+ public static void main(String[] args) {
+ Editor.initLogger();
+ Editor self = new Editor();
+ self.pack();
+ self.sview.requestFocusInWindow();
+ self.setVisible(true);
+
+ }
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/ui/ShapeDraftman.java b/shapes/src/main/java/fr/uha/graphics/shapes/ui/ShapeDraftman.java
new file mode 100755
index 0000000..13310bb
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/ui/ShapeDraftman.java
@@ -0,0 +1,161 @@
+package fr.uha.graphics.shapes.ui;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.util.Iterator;
+import java.util.logging.Logger;
+
+import fr.uha.graphics.shapes.SCircle;
+import fr.uha.graphics.shapes.SCollection;
+import fr.uha.graphics.shapes.SRectangle;
+import fr.uha.graphics.shapes.SSelection;
+import fr.uha.graphics.shapes.SText;
+import fr.uha.graphics.shapes.STriangle;
+import fr.uha.graphics.shapes.Shape;
+import fr.uha.graphics.shapes.ShapeVisitor;
+import fr.uha.graphics.shapes.attributes.ColorAttributes;
+import fr.uha.graphics.shapes.attributes.FontAttributes;
+import fr.uha.graphics.shapes.attributes.SelectionAttributes;
+
+public class ShapeDraftman implements ShapeVisitor {
+
+ private static final Logger LOGGER = Logger.getLogger(ShapeDraftman.class.getName());
+
+ // Default attributes
+ private static final ColorAttributes DEFAULT_COLOR_ATTRIBUTES = new ColorAttributes(false, true, Color.BLACK, Color.BLACK);
+
+ private Graphics2D graph;
+
+ public ShapeDraftman(Graphics graph) {
+ this.graph = (Graphics2D) graph;
+ }
+
+ @Override
+ public void visitRectangle(SRectangle rect) {
+ Rectangle r = rect.getRect();
+ ColorAttributes colAttrs = (ColorAttributes) rect.getAttributes(ColorAttributes.ID);
+
+ if (colAttrs == null){
+ colAttrs = DEFAULT_COLOR_ATTRIBUTES;
+ }
+ if (colAttrs.filled) {
+ this.graph.setColor(colAttrs.filledColor);
+ this.graph.fillRect(r.x, r.y, r.width, r.height);
+ }
+ if (colAttrs.stroked) {
+ this.graph.setColor(colAttrs.strokedColor);
+ this.graph.drawRect(r.x, r.y, r.width, r.height);
+ }
+ drawHandlerIfSelected(rect);
+ }
+
+ @Override
+ public void visitCircle(SCircle circle) {
+ ColorAttributes colAttrs = (ColorAttributes) circle.getAttributes(ColorAttributes.ID);
+
+ if (colAttrs == null) {
+ colAttrs = DEFAULT_COLOR_ATTRIBUTES;
+ }
+ if (colAttrs.filled) {
+ this.graph.setColor(colAttrs.filledColor);
+ this.graph.fillOval(circle.getLoc().x, circle.getLoc().y, circle.getRadius(), circle.getRadius());
+ }
+ if (colAttrs.stroked) this.graph.setColor(colAttrs.strokedColor);
+ this.graph.drawOval(circle.getLoc().x, circle.getLoc().y, circle.getRadius(), circle.getRadius());
+
+ drawHandlerIfSelected(circle);
+}
+
+ @Override
+ public void visitText(SText text) {
+ Point loc = text.getLoc();
+ Rectangle bounds = text.getBounds();
+ // Fetch SText attributes
+ ColorAttributes colAttrs = (ColorAttributes) text.getAttributes(ColorAttributes.ID);
+ FontAttributes fontAttrs = (FontAttributes) text.getAttributes(FontAttributes.ID);
+
+ if (colAttrs == null){
+ colAttrs = DEFAULT_COLOR_ATTRIBUTES;
+ }
+ if (colAttrs.filled) {
+ this.graph.setColor(colAttrs.filledColor);
+ // The reference point for Rectangle is the upper-left corner,
+ // whereas it is the bottom-left corner for Font.drawString().
+ this.graph.fillRect(loc.x, loc.y - bounds.height, bounds.width, bounds.height);
+ }
+ if (colAttrs.stroked){
+ this.graph.setColor(colAttrs.strokedColor);
+ this.graph.drawRect(loc.x, loc.y - bounds.height, bounds.width, bounds.height);
+ }
+ this.graph.setFont(fontAttrs.font);
+ this.graph.setPaint(fontAttrs.fontColor);
+ this.graph.drawString(text.getText(), loc.x, loc.y);
+
+ drawHandlerIfSelected(text);
+ }
+
+ @Override
+ public void visitCollection(SCollection col) {
+ for (Iterator it = col.getIterator(); it.hasNext();) {
+ Shape current = it.next();
+ current.accept(this);
+ }
+
+ drawHandlerIfSelected(col);
+ }
+
+ public void visitTriangle(STriangle tri){
+ Point loc = tri.getLoc();
+ int size = tri.getSize();
+ ColorAttributes colAttrs = (ColorAttributes) tri.getAttributes(ColorAttributes.ID);
+
+ if (colAttrs == null){
+ colAttrs = DEFAULT_COLOR_ATTRIBUTES;
+ }
+ if (colAttrs.filled) {
+ this.graph.setColor(colAttrs.filledColor);
+ this.graph.fillPolygon(new int[]{loc.x, loc.x+(size/2), loc.x + size},
+ new int[]{loc.y+size, loc.y, loc.y+size},
+ 3);
+ }
+ if (colAttrs.stroked) this.graph.setColor(colAttrs.strokedColor);
+ this.graph.drawPolygon(new int[]{loc.x, loc.x+(size/2), loc.x + size},
+ new int[]{loc.y+size, loc.y, loc.y+size},
+ 3);
+
+ drawHandlerIfSelected(tri);
+ }
+
+ @Override
+ public void visitSelection(SSelection sel) {
+ Rectangle r = sel.getRect();
+ ColorAttributes attrs = (ColorAttributes) sel.getAttributes(ColorAttributes.ID);
+
+ if (attrs == null) attrs = DEFAULT_COLOR_ATTRIBUTES;
+ this.graph.drawRect(r.x, r.y, r.width, r.height);
+ }
+
+ /*
+ * Draw handlers on all selected shapes.
+ */
+ private void drawHandlerIfSelected(Shape s){
+ SelectionAttributes selAttrs = (SelectionAttributes) s.getAttributes(SelectionAttributes.ID);
+ if ((selAttrs != null)&&(selAttrs.isSelected())){
+ Rectangle bounds = s.getBounds();
+ drawHandler(bounds);
+ }
+ }
+
+ public void drawHandler(Rectangle bounds) {
+ this.graph.setColor(Color.RED);
+ this.graph.drawRect(bounds.x - 5, bounds.y - 5, 5, 5);
+ this.graph.drawRect(bounds.x + bounds.width, bounds.y + bounds.height, 5, 5);
+ }
+
+ public void setGraphics(Graphics g) {
+ this.graph = (Graphics2D) g;
+ }
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/ui/ShapesController.java b/shapes/src/main/java/fr/uha/graphics/shapes/ui/ShapesController.java
new file mode 100644
index 0000000..758669e
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/ui/ShapesController.java
@@ -0,0 +1,321 @@
+package fr.uha.graphics.shapes.ui;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import fr.uha.graphics.shapes.SCircle;
+import fr.uha.graphics.shapes.SCollection;
+import fr.uha.graphics.shapes.SRectangle;
+import fr.uha.graphics.shapes.SSelection;
+import fr.uha.graphics.shapes.SText;
+import fr.uha.graphics.shapes.STriangle;
+import fr.uha.graphics.shapes.Shape;
+import fr.uha.graphics.shapes.attributes.ColorAttributes;
+import fr.uha.graphics.shapes.attributes.FontAttributes;
+import fr.uha.graphics.shapes.attributes.SelectionAttributes;
+import fr.uha.graphics.ui.Controller;
+
+public class ShapesController extends Controller {
+
+ private static final Logger LOGGER = Logger.getLogger(ShapesController.class.getName());
+ private boolean shiftDown;
+ private Point locClicked;
+ private SSelection sel;
+ private List copyMem = new ArrayList();
+ private List delMem = new ArrayList();
+
+
+ public ShapesController(Shape model) {
+ super(model);
+
+ this.locClicked = new Point();
+ this.shiftDown = false;
+ this.sel = new SSelection();
+ }
+
+ @Override
+ public Object getModel() {
+ return super.getModel();
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ super.mousePressed(e);
+ this.locClicked = e.getPoint();
+ Shape target = getTarget();
+
+ if (!shiftDown()){
+ unselectAll();
+ }
+
+ if (target != null){
+ SelectionAttributes selAttrs = (SelectionAttributes) target.getAttributes(SelectionAttributes.ID);
+ if (selAttrs != null){
+ selAttrs.toggleSelection();
+ }
+ }
+ getView().repaint();
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ super.mouseClicked(e);
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ SSelection currentSSelection = this.sel;
+ for (Iterator it = ((SCollection) this.getModel()).getIterator(); it.hasNext();) {
+ Shape current = it.next();
+
+ if (this.sel.getBounds().contains(current.getBounds())) {
+ select(current);
+ getView().repaint();
+ }
+ if (current instanceof SSelection) current = currentSSelection;
+ }
+ currentSSelection.setLoc(new Point(0, 0));
+ currentSSelection.resize(0, 0);
+ this.sel = currentSSelection;
+ getView().repaint();
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent evt) {
+ super.mouseDragged(evt);
+ boolean anyShapeSelected = isAnyShapeSelected();
+
+ for (Iterator it = ((SCollection) this.getModel()).getIterator(); it.hasNext();) {
+ Shape current = it.next();
+
+ if ((!anyShapeSelected) && (current instanceof SSelection)) {
+ this.sel = (SSelection) current;
+ this.sel.setLoc(this.locClicked);
+ this.sel.resize(evt.getX()-this.locClicked.x, evt.getY()-this.locClicked.y);
+ getView().repaint();
+ }
+ // Translate all selected shapes.
+ if(isSelected(current)){
+ int dx = evt.getPoint().x - current.getLoc().x;
+ int dy = evt.getPoint().y - current.getLoc().y;
+ translateSelected(dx, dy);
+ }
+ }
+ }
+
+ @Override
+ public void keyPressed(KeyEvent evt) {
+ super.keyPressed(evt);
+ switch (evt.getKeyCode()) {
+ case KeyEvent.VK_SHIFT:
+ shiftDown = true;
+ break;
+ case KeyEvent.VK_DELETE:
+ deleteSelected();
+ break;
+ case KeyEvent.VK_Z:
+ undo();
+ break;
+ case KeyEvent.VK_C:
+ copy();
+ break;
+ case KeyEvent.VK_V:
+ paste();
+ break;
+ case KeyEvent.VK_H:
+ LOGGER.info("HTML/CSS generated");
+ try {
+ generateHtml();
+ } catch (IOException e) {
+ LOGGER.log(Level.SEVERE, e.getMessage());
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ @Override
+ public void keyReleased(KeyEvent evt) {
+ super.keyReleased(evt);
+ switch (evt.getKeyCode()) {
+ case KeyEvent.VK_SHIFT:
+ shiftDown = false;
+ break;
+ }
+ }
+
+ public Shape getTarget() {
+ SCollection model = (SCollection) getModel();
+ Iterator it = model.getIterator();
+ while (it.hasNext()) {
+ Shape current = it.next();
+ if (current.getBounds().contains(this.locClicked)) {
+ LOGGER.log(Level.INFO, "Shape selected : {0}", current);
+ return current;
+ }
+ }
+ return null;
+ }
+
+ public void translateSelected(int dx, int dy) {
+ for (Iterator it = ((SCollection) this.getModel()).getIterator(); it.hasNext();) {
+ Shape current = it.next();
+ if (isSelected(current)) current.translate(dx, dy);
+ }
+ getView().repaint();
+ }
+
+ public void deleteSelected(){
+ ArrayList toDelete = new ArrayList();
+ for (Iterator it = ((SCollection) this.getModel()).getIterator(); it.hasNext();) {
+ Shape current = it.next();
+ if(isSelected(current)){
+ this.delMem.add(current);
+ toDelete.add(current);
+ }
+ }
+ for (Shape current: toDelete){
+ LOGGER.log(Level.INFO, "Removing shape {0}", current);
+ ((SCollection)this.getModel()).remove(current);
+ }
+ unselectAll(); // unselectAll() takes care of the graphical update (repaint).
+ }
+
+ public void unselectAll() {
+ for (Iterator it = ((SCollection) this.getModel()).getIterator(); it.hasNext();) {
+ Shape current = it.next();
+ unselect(current);
+ }
+ getView().repaint();
+ }
+
+ public void generateHtml() throws IOException {
+ PrintWriter index = new PrintWriter("index.html", "UTF-8");
+ PrintWriter style = new PrintWriter("style.css", "UTF-8");
+
+ index.println("");
+ index.println("");
+ index.println("");
+ index.println("");
+ index.println("");
+ index.println("TP Shape COLICCHIO et GASSER");
+ index.println("");
+ index.println("");
+
+ for (Iterator it = ((SCollection) this.getModel()).getIterator(); it.hasNext();) {
+ Shape current = it.next();
+ index.println(current.htmlShape());
+ }
+ index.flush();
+ index.println("");
+ index.println("");
+ index.println("");
+ index.close();
+
+ style.println("footer{text-align:center;margin:auto;height:50px;position:fixed;bottom:0;font-weight:bold;}");
+
+ for (Iterator it = ((SCollection) this.getModel()).getIterator(); it.hasNext();) {
+ Shape current = it.next();
+ style.println(current.cssShape());
+ }
+ style.close();
+ }
+
+ public boolean shiftDown() {
+ return this.shiftDown;
+ }
+
+ private boolean isAnyShapeSelected(){
+ for (Iterator it = ((SCollection) this.getModel()).getIterator(); it.hasNext();) {
+ Shape current = it.next();
+ if (isSelected(current)) return true;
+ }
+ return false;
+ }
+
+ private boolean isSelected(Shape s) {
+ SelectionAttributes attrs = (SelectionAttributes) s.getAttributes(SelectionAttributes.ID);
+ if (attrs == null) return false;
+ return attrs.isSelected();
+ }
+
+ private int select(Shape s) {
+ LOGGER.log(Level.INFO, "Selecting {0}", s);
+ SelectionAttributes attrs = (SelectionAttributes) s.getAttributes(SelectionAttributes.ID);
+ // If this shape has no selection attributes
+ if (attrs == null) return -1;
+ attrs.select();
+ return 0;
+ }
+
+ private int unselect(Shape s) {
+ SelectionAttributes attrs = (SelectionAttributes) s.getAttributes(SelectionAttributes.ID);
+ // If this shape has no selection attributes
+ if (attrs == null) return -1;
+ attrs.unselect();
+ return 0;
+ }
+
+ public void undo(){
+ ListIterator it = delMem.listIterator();
+ while(it.hasNext()){
+ Shape str = it.next();
+ ((SCollection) getModel()).add(str);
+ }
+ delMem.clear();
+ getView().repaint();
+ }
+
+ private void copy(){
+ for (Iterator it = ((SCollection) this.getModel()).getIterator(); it.hasNext();) {
+ Shape current = it.next();
+ if(isSelected(current)){
+ copyMem.add(current);
+ }
+ }
+ }
+
+ private void paste(){
+ SCollection model = (SCollection) this.getModel();
+ for (Iterator it = copyMem.iterator(); it.hasNext();) {
+ Shape current = (Shape) it.next();
+ Shape s = cloneShape(current);
+ model.add(s);
+ }
+ copyMem.clear();
+ getView().repaint();
+ }
+
+ private Shape cloneShape(Shape s){
+ Rectangle bounds = s.getBounds();
+ Shape newShape = null;
+
+ if (s instanceof STriangle) {
+ newShape = new STriangle(new Point(), bounds.width);
+ } else if (s instanceof SRectangle) {
+ newShape = new SRectangle(new Point(), bounds.width, bounds.height);
+ } else if (s instanceof SCircle) {
+ newShape = new SCircle(new Point(), bounds.width);
+ } else if (s instanceof SText) {
+ System.out.println("Texte : " + ((SText) s).getText());
+ newShape = new SText(new Point(0, bounds.height), ((SText) s).getText());
+ newShape.addAttributes((FontAttributes) s.getAttributes(FontAttributes.ID));
+ }
+ newShape.addAttributes(new SelectionAttributes());
+ newShape.addAttributes(s.getAttributes(ColorAttributes.ID));
+ return newShape;
+ }
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/ui/ShapesView.java b/shapes/src/main/java/fr/uha/graphics/shapes/ui/ShapesView.java
new file mode 100755
index 0000000..01fa84a
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/ui/ShapesView.java
@@ -0,0 +1,37 @@
+package fr.uha.graphics.shapes.ui;
+
+import java.awt.Graphics;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import fr.uha.graphics.shapes.Shape;
+import fr.uha.graphics.ui.Controller;
+import fr.uha.graphics.ui.View;
+
+public class ShapesView extends View {
+
+ private static final Logger LOGGER = Logger.getLogger(ShapesView.class.getName());
+
+ private ShapeDraftman draftman;
+
+ public ShapesView(Shape model) {
+ super(model);
+ LOGGER.log(Level.INFO, "ShapesView({0})", model);
+ }
+
+ @Override
+ public void paintComponent(Graphics component) {
+ // Draw the default (blank) JPanel
+ super.paintComponent(component);
+ // LOGGER.log(Level.INFO, "Drawing component : {0}", component);
+ Shape model = (Shape) this.getModel();
+ this.draftman = new ShapeDraftman(component);
+ model.accept(draftman);
+ }
+
+ @Override
+ public Controller defaultController(Object model) {
+ return new ShapesController((Shape) this.getModel());
+ }
+
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/ui/menu/MenuAddListener.java b/shapes/src/main/java/fr/uha/graphics/shapes/ui/menu/MenuAddListener.java
new file mode 100644
index 0000000..4c7043c
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/ui/menu/MenuAddListener.java
@@ -0,0 +1,59 @@
+package fr.uha.graphics.shapes.ui.menu;
+
+import java.awt.Color;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import fr.uha.graphics.shapes.SCircle;
+import fr.uha.graphics.shapes.SCollection;
+import fr.uha.graphics.shapes.SRectangle;
+import fr.uha.graphics.shapes.SText;
+import fr.uha.graphics.shapes.STriangle;
+import fr.uha.graphics.shapes.Shape;
+import fr.uha.graphics.shapes.attributes.ColorAttributes;
+import fr.uha.graphics.shapes.attributes.FontAttributes;
+import fr.uha.graphics.shapes.attributes.SelectionAttributes;
+import fr.uha.graphics.shapes.ui.ShapesView;
+
+public class MenuAddListener implements ActionListener {
+ private String shape;
+ private ShapesView view;
+ private SCollection model;
+
+ public MenuAddListener(String shape, SCollection model, ShapesView view) {
+ this.shape = shape;
+ this.model = model;
+ this.view = view;
+ }
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ Shape s;
+ Rectangle bounds = model.getBounds();
+ // All new shapes will be in the center of the panel.
+ Point loc = new Point((int)bounds.getCenterX(), (int)bounds.getCenterY());
+
+ if (this.shape.equals("SRectangle")){
+ s = new SRectangle(loc, 50, 50);
+ } else if (this.shape.equals("SCircle")){
+ s = new SCircle(loc, 50);
+ } else if (this.shape.equals("STriangle")){
+ s = new STriangle(loc, 50);
+ } else if (this.shape.equals("SText")){
+ s = new SText(loc, "Lorem ipsum");
+ s.addAttributes(new FontAttributes());
+ }
+ else return;
+
+ s.addAttributes(new SelectionAttributes());
+ s.addAttributes(new ColorAttributes(true, false, randomColor(), null));
+ model.add(s);
+ view.repaint();
+ }
+
+ private Color randomColor(){
+ return new Color((int)(Math.random() * 0x1000000));
+ }
+
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/shapes/ui/menu/MenuEditListener.java b/shapes/src/main/java/fr/uha/graphics/shapes/ui/menu/MenuEditListener.java
new file mode 100644
index 0000000..a38c07a
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/shapes/ui/menu/MenuEditListener.java
@@ -0,0 +1,115 @@
+package fr.uha.graphics.shapes.ui.menu;
+
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Iterator;
+import java.util.logging.Logger;
+
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JColorChooser;
+
+import fr.uha.graphics.shapes.SCollection;
+import fr.uha.graphics.shapes.Shape;
+import fr.uha.graphics.shapes.attributes.ColorAttributes;
+import fr.uha.graphics.shapes.attributes.SelectionAttributes;
+import fr.uha.graphics.shapes.ui.ShapesController;
+import fr.uha.graphics.shapes.ui.ShapesView;
+import fr.uha.graphics.ui.Controller;
+
+public class MenuEditListener implements ActionListener {
+ private static final Logger LOGGER = Logger.getLogger(SCollection.class.getName());
+
+ private SCollection model;
+ private ShapesView view;
+ private ShapesController controller;
+
+ public MenuEditListener(SCollection model, ShapesView view, Controller controller) {
+ this.model = model;
+ this.view = view;
+ this.controller = (ShapesController) controller;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ Object source = e.getSource();
+ if (e.getActionCommand().equals("Change color")){
+ Color newColor = JColorChooser.showDialog(null, "Choose a color", Color.RED);
+ changeColor(newColor);
+ } else if (e.getActionCommand().equals("Change border color")){
+ Color newColor = JColorChooser.showDialog(null, "Choose a color", Color.RED);
+ changeBorderColor(newColor);
+ } else if (e.getActionCommand().equals("Delete")) this.controller.deleteSelected();
+ else if (e.getActionCommand().equals("Undo")) this.controller.undo();
+ else if (source instanceof JCheckBoxMenuItem) {
+ JCheckBoxMenuItem item = (JCheckBoxMenuItem) source;
+ if (item.getText().equals("Draw border")) setBorder(item.isSelected());
+ if (item.getText().equals("Fill Shape")) setShapeFilled(item.getState());
+ }
+ view.repaint();
+ }
+
+ private Color randomColor(){
+ return new Color((int)(Math.random() * 0x1000000));
+ }
+
+ private void changeColor(Color filledColor){
+ for (Iterator it = model.getIterator(); it.hasNext();) {
+ Shape current = (Shape)it.next();
+ SelectionAttributes selAttrs = (SelectionAttributes) current.getAttributes(SelectionAttributes.ID);
+ if ((selAttrs == null) || (! selAttrs.isSelected())) continue;
+
+ ColorAttributes currentColAttrs = (ColorAttributes) current.getAttributes(ColorAttributes.ID);
+ if (currentColAttrs != null) {
+ current.addAttributes(new ColorAttributes(currentColAttrs.filled, currentColAttrs.stroked, filledColor, currentColAttrs.strokedColor));
+ } else {
+ current.addAttributes(new ColorAttributes(true, true, filledColor, Color.BLACK));
+ }
+ }
+ }
+
+ private void changeBorderColor(Color strockedColor){
+ for (Iterator it = model.getIterator(); it.hasNext();) {
+ Shape current = (Shape)it.next();
+ SelectionAttributes selAttrs = (SelectionAttributes) current.getAttributes(SelectionAttributes.ID);
+ if ((selAttrs == null) || (! selAttrs.isSelected())) continue;
+
+ ColorAttributes currentColAttrs = (ColorAttributes) current.getAttributes(ColorAttributes.ID);
+ if (currentColAttrs != null) {
+ current.addAttributes(new ColorAttributes(currentColAttrs.filled, currentColAttrs.stroked, currentColAttrs.filledColor, strockedColor));
+ } else {
+ current.addAttributes(new ColorAttributes(true, true, Color.WHITE, strockedColor));
+ }
+ }
+ }
+
+ /*
+ * Change the state of the border of all selected shapes.
+ */
+ private void setBorder(boolean state){
+ for (Iterator it=model.getIterator(); it.hasNext();){
+ Shape current = (Shape)it.next();
+ SelectionAttributes selAttrs = (SelectionAttributes)current.getAttributes(SelectionAttributes.ID);
+ if ((selAttrs == null) || (! selAttrs.isSelected())) continue;
+ ColorAttributes colAttrs = (ColorAttributes) current.getAttributes(ColorAttributes.ID);
+ colAttrs.stroked = state;
+ current.addAttributes(new ColorAttributes(colAttrs));
+ }
+ }
+
+ /*
+ * Change the filled state for all selected shapes.
+ */
+ private void setShapeFilled(boolean state){
+ LOGGER.info("setShapeFilled(" + state + ")");
+ for (Iterator it=model.getIterator(); it.hasNext();){
+ Shape current = it.next();
+ SelectionAttributes selAttrs = (SelectionAttributes)current.getAttributes(SelectionAttributes.ID);
+ if ((selAttrs == null) || (!selAttrs.isSelected())) continue;
+ ColorAttributes colAttrs = (ColorAttributes) current.getAttributes(ColorAttributes.ID);
+ colAttrs.filled = state;
+ current.addAttributes(new ColorAttributes(colAttrs));
+ }
+ }
+
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/ui/Controller.java b/shapes/src/main/java/fr/uha/graphics/ui/Controller.java
new file mode 100755
index 0000000..9787210
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/ui/Controller.java
@@ -0,0 +1,73 @@
+package fr.uha.graphics.ui;
+
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+
+public class Controller implements MouseListener, MouseMotionListener, KeyListener {
+ protected Object model;
+ private View view;
+
+ public Controller(Object newModel) {
+ model = newModel;
+ }
+
+ public void setView(View view) {
+ this.view = view;
+ }
+
+ final public View getView() {
+ return this.view;
+ }
+
+ public void setModel(Object model) {
+ this.model = model;
+ }
+
+ public Object getModel() {
+ return this.model;
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseExited(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent evt) {
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent evt) {
+ }
+
+ @Override
+ public void keyTyped(KeyEvent evt) {
+ }
+
+ @Override
+ public void keyPressed(KeyEvent evt) {
+ }
+
+ @Override
+ public void keyReleased(KeyEvent evt) {
+ }
+
+}
diff --git a/shapes/src/main/java/fr/uha/graphics/ui/View.java b/shapes/src/main/java/fr/uha/graphics/ui/View.java
new file mode 100755
index 0000000..c39052a
--- /dev/null
+++ b/shapes/src/main/java/fr/uha/graphics/ui/View.java
@@ -0,0 +1,34 @@
+package fr.uha.graphics.ui;
+
+import javax.swing.JPanel;
+
+public abstract class View extends JPanel {
+ private Object model;
+ private Controller controller;
+
+ public View(Object model) {
+ this.model = model;
+ this.controller = defaultController(model);
+ this.controller.setView(this);
+ this.addMouseListener(this.controller);
+ this.addMouseMotionListener(this.controller);
+ this.addKeyListener(this.controller);
+ }
+
+ public void setModel(Object model) {
+ this.model = model;
+ this.controller.setModel(model);
+ }
+
+ public Object getModel() {
+ return this.model;
+ }
+
+ public Controller defaultController(Object model) {
+ return new Controller(model);
+ }
+
+ final public Controller getController() {
+ return this.controller;
+ }
+}
diff --git a/shapes/style.css b/shapes/style.css
new file mode 100644
index 0000000..0e6d916
--- /dev/null
+++ b/shapes/style.css
@@ -0,0 +1,8 @@
+footer{text-align:center;margin:auto;height:50px;position:fixed;bottom:0;font-weight:bold;}
+
+.rectangle813589267{ position:absolute;top:89px;left:95px;width:60px;height:60px;background: #999999;border:1px solid #000000; }.circle1577038754{ position: absolute;top:159px;left:225px;width:40px;height:40px;border-radius:20px;-webkit-border-radius:20px;-o-border-radius:20px;-moz-border-radius:20px;background: #999999;border:1px solid #000000; }
+.triangle527292885{ position: absolute;top: 38px;left: 243px;width: 0px;height: 0px;border: 0 solid transparent;border-left-width: 30.0px;border-right-width: 30.0px;border-bottom: 50px solid #ecb4ee;}
+.rectangle1045587243{ position:absolute;top:105px;left:319px;width:40px;height:60px;background: #0000ff;border:1px solid #000000; }
+.circle2117079733{ position: absolute;top:42px;left:109px;width:30px;height:30px;border-radius:15px;-webkit-border-radius:15px;-o-border-radius:15px;-moz-border-radius:15px;background: #999999;border:1px solid #ff0000; }
+.text997905906{ position: absolute;top: 139px;left: 179px;width: 69px;height: 30px;font-family: "Arial";font-size: 30px;color: #0000ff;font-weight: bold;background: #ecb4ee;border:1px solid #0000ff; }
+.rectangle1033207963{ position:absolute;top:185px;left:299px;width:50px;height:50px;background: #ecb4ee;border:1px solid #ffffff; }