diff --git a/pom.xml b/pom.xml index 3fc1d12..29a73c3 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.codeforall.online.simplegraphics + com.codeforall.simplegraphics simple-graphics 0.2.2-SNAPSHOT @@ -35,8 +35,8 @@ maven-compiler-plugin 3.5.1 - 1.8 - 1.8 + 17 + 17 UTF-8 diff --git a/src/main/java/com/codeforall/online/simplegraphics/graphics/Canvas.java b/src/main/java/com/codeforall/online/simplegraphics/graphics/Canvas.java deleted file mode 100755 index d1d5ed3..0000000 --- a/src/main/java/com/codeforall/online/simplegraphics/graphics/Canvas.java +++ /dev/null @@ -1,188 +0,0 @@ -package com.codeforall.online.simplegraphics.graphics; - -import javax.imageio.ImageIO; -import javax.swing.*; -import java.awt.*; -import java.awt.Color; -import java.awt.Rectangle; -import java.awt.event.KeyListener; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.awt.image.BufferedImage; -import java.awt.image.ImageObserver; -import java.awt.image.RescaleOp; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; - -/** - * Container of shapes - */ -public class Canvas { - private static final int MIN_SIZE = 100; - private static final int MARGIN = 10; - private static final int LOCATION_OFFSET = 120; - private static int MAX_X = 0; - private static int MAX_Y = 0; - private static Canvas canvas = new Canvas(); - private ArrayList shapes = new ArrayList(); - private BufferedImage background; - private JFrame frame = new JFrame(); - private Canvas.CanvasComponent component = new Canvas.CanvasComponent(); - - /** - * Defines a limit to the width of the canvas - * @param var0 - */ - public static void setMaxX(int var0) { - MAX_X = var0; - } - - /** - * Defines a limit to the height of the canvas - * @param var0 - */ - public static void setMaxY(int var0) { - MAX_Y = var0; - } - - private Canvas() { - this.frame.add(this.component); - this.frame.pack(); - this.frame.setLocation(LOCATION_OFFSET, LOCATION_OFFSET); - this.frame.setVisible(true); - } - - public static Canvas getInstance() { - return canvas; - } - - public static void pause() { - JFrame var0 = getInstance().frame; - if (var0 != null) { - JOptionPane.showMessageDialog(var0, "Click Ok to continue"); - } - } - - public static void snapshot() { - Dimension var0 = getInstance().component.getPreferredSize(); - java.awt.Rectangle var1 = new java.awt.Rectangle(0, 0, var0.width, var0.height); - BufferedImage var2 = new BufferedImage(var1.width, var1.height, 1); - Graphics var3 = var2.getGraphics(); - var3.setColor(java.awt.Color.WHITE); - var3.fillRect(0, 0, var1.width, var1.height); - var3.setColor(java.awt.Color.BLACK); - getInstance().component.paintComponent(var3); - float var4 = 0.8F; - float var5 = 255.0F * (1.0F - var4); - RescaleOp var6 = new RescaleOp(var4, var5, (RenderingHints)null); - BufferedImage var7 = new BufferedImage(var2.getWidth(), var2.getHeight(), var2.getType()); - var6.filter(var2, var7); - getInstance().background = var7; - getInstance().component.repaint(); - } - - public void show(Shape var1) { - if (!this.shapes.contains(var1)) { - this.shapes.add(var1); - } - - this.repaint(); - } - - public void hide(Shape var1) { - if (this.shapes.contains(var1)) { - this.shapes.remove(var1); - } - - this.repaint(); - } - - public void repaint() { - if (this.frame != null) { - Dimension var1 = this.component.getPreferredSize(); - if (var1.getWidth() <= (double)this.component.getWidth() && var1.getHeight() <= (double)this.component.getHeight()) { - this.frame.repaint(); - } else { - this.frame.pack(); - } - - } - } - - public void saveToDisk(String var1) { - Dimension var2 = this.component.getPreferredSize(); - java.awt.Rectangle var3 = new Rectangle(0, 0, var2.width, var2.height); - BufferedImage var4 = new BufferedImage(var3.width, var3.height, 1); - Graphics2D var5 = (Graphics2D)var4.getGraphics(); - var5.setColor(java.awt.Color.WHITE); - var5.fill(var3); - var5.setColor(java.awt.Color.BLACK); - this.component.paintComponent(var5); - String var6 = var1.substring(var1.lastIndexOf(46) + 1); - - try { - ImageIO.write(var4, var6, new File(var1)); - } catch (IOException var8) { - System.err.println("Was unable to save the image to " + var1); - } - - var5.dispose(); - } - - public void addKeyListener(KeyListener var1) { - this.frame.addKeyListener(var1); - } - - public void addMouseListener(MouseListener var1) { - this.frame.addMouseListener(var1); - } - - public void addMouseMotionListener(MouseMotionListener var1) { - this.frame.addMouseMotionListener(var1); - } - - class CanvasComponent extends JComponent { - CanvasComponent() { - } - - public void paintComponent(Graphics var1) { - var1.setColor(java.awt.Color.WHITE); - var1.fillRect(0, 0, this.getWidth(), this.getHeight()); - var1.setColor(Color.BLACK); - if (Canvas.this.background != null) { - var1.drawImage(Canvas.this.background, 0, 0, (ImageObserver)null); - } - - Iterator var2 = (new ArrayList(Canvas.this.shapes)).iterator(); - - while(var2.hasNext()) { - Shape var3 = (Shape)var2.next(); - Graphics2D var4 = (Graphics2D)var1.create(); - var3.paintShape(var4); - var4.dispose(); - } - - } - - public Dimension getPreferredSize() { - int var1 = Canvas.MAX_X == 0 ? MIN_SIZE : Canvas.MAX_X; - int var2 = Canvas.MAX_Y == 0 ? MIN_SIZE : Canvas.MAX_Y; - if (Canvas.this.background != null) { - var1 = Math.max(var1, Canvas.this.background.getWidth()); - var2 = Math.max(var1, Canvas.this.background.getHeight()); - } - - Shape var4; - if (Canvas.MAX_X == 0 && Canvas.MAX_Y == 0) { - for(Iterator var3 = Canvas.this.shapes.iterator(); var3.hasNext(); var2 = Math.max(var2, var4.getY() + var4.getHeight())) { - var4 = (Shape)var3.next(); - var1 = Math.max(var1, var4.getX() + var4.getWidth()); - } - } - - return new Dimension(var1 + MARGIN, var2 + MARGIN); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/codeforall/online/simplegraphics/graphics/Line.java b/src/main/java/com/codeforall/online/simplegraphics/graphics/Line.java deleted file mode 100755 index 75ad6e5..0000000 --- a/src/main/java/com/codeforall/online/simplegraphics/graphics/Line.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.codeforall.online.simplegraphics.graphics; - -import java.awt.*; -import java.awt.geom.Line2D; - -public class Line implements Shape, Colorable, Movable { - private Color color = Color.BLACK; - private double x1; - private double y1; - private double x2; - private double y2; - - /** - * Constructs a line with a given starting and ending location. - * - * @param x1 the x-coordinate of the starting point - * @param y1 the y-coordinate of the starting point - * @param x2 the x-coordinate of the ending point - * @param y2 the y-coordinate of the ending point - */ - public Line(double x1, double y1, double x2, double y2) { - this.x1 = x1; - this.x2 = x2; - this.y1 = y1; - this.y2 = y2; - } - - /** - * Gets the leftmost x-position of the line. - * - * @return the leftmost x-position - */ - public int getX() { - return (int) Math.round(Math.min(x1, x2)); - } - - /** - * Gets the topmost y-position of the line. - * - * @return the topmost y-position - */ - public int getY() { - return (int) Math.round(Math.min(y1, y2)); - } - - /** - * Gets the width of the bounding box. - * - * @return the width - */ - public int getWidth() { - return (int) Math.round(Math.abs(x2 - x1)); - } - - /** - * Gets the height of the bounding box. - * - * @return the height - */ - public int getHeight() { - return (int) Math.round(Math.abs(y2 - y1)); - } - - /** - * Moves this line by a given amount. - * - * @param dx the amount by which to move in x-direction - * @param dy the amount by which to move in y-direction - */ - public void translate(double dx, double dy) { - x1 += dx; - y1 += dy; - x2 += dx; - y2 += dy; - Canvas.getInstance().repaint(); - } - - /** - * Resizes this line both horizontally and vertically. - * - * @param dw the amount by which to resize the width on each side - * @param dh the amount by which to resize the height on each side - */ - public void grow(double dw, double dh) { - if (x1 <= x2) { - x1 -= dw; - x2 += dw; - } else { - x1 += dw; - x2 -= dw; - } - if (y1 <= y2) { - y1 -= dh; - y2 += dh; - } else { - y1 += dh; - y2 -= dh; - } - - Canvas.getInstance().repaint(); - } - - /** - * Sets the color for drawing this line. - * - * @param newColor the new color - */ - public void setColor(Color newColor) { - color = newColor; - Canvas.getInstance().repaint(); - } - - /** - * Shows this line on the canvas. - */ - public void draw() { - Canvas.getInstance().show(this); - } - - /** - * Deletes this line from the canvas. - */ - public void delete() { - Canvas.getInstance().hide(this); - } - - public String toString() { - return "Line[x1=" + x1 + ",y1=" + y1 + ",x2=" + x2 + ",y2=" + y2 + "]"; - } - - public void paintShape(Graphics2D g2) { - if (color != null) { - g2.setColor(new java.awt.Color((int) color.getRed(), (int) color.getGreen(), (int) color.getBlue())); - Line2D.Double line = new Line2D.Double(x1, y1, x2, y2); - g2.draw(line); - } - } -} diff --git a/src/main/java/com/codeforall/online/simplegraphics/keyboard/Keyboard.java b/src/main/java/com/codeforall/online/simplegraphics/keyboard/Keyboard.java deleted file mode 100644 index 7637262..0000000 --- a/src/main/java/com/codeforall/online/simplegraphics/keyboard/Keyboard.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.codeforall.online.simplegraphics.keyboard; - -import com.codeforall.online.simplegraphics.graphics.Canvas; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.util.ArrayList; -import java.util.List; -import java.util.Iterator; - -/** - * Instantiate a Keyboard for obtaining key handling capability - */ -public class Keyboard implements KeyListener { - - KeyboardHandler handler; - List keyboardEventArrayList; - - /** - * @param handler the keyboard handler - */ - public Keyboard(KeyboardHandler handler) { - - Canvas.getInstance().addKeyListener(this); - - this.handler = handler; - keyboardEventArrayList = new ArrayList(); - - } - - /** - * Add a new Keyboard event listener - * @param keyboardEvent the event to add - */ - public void addEventListener(KeyboardEvent keyboardEvent) { - keyboardEventArrayList.add(keyboardEvent); - } - - /** - * Remove an existing Keyboard event listener - * @param keyboardEvent the event to remove - */ - public void removeEventListener(KeyboardEvent keyboardEvent) { - keyboardEventArrayList.remove(keyboardEvent); - } - - /** - * @see KeyListener#keyTyped(KeyEvent) - * @param e the event - */ - @Override - public void keyTyped(KeyEvent e) { - } - - /** - * @see KeyboardHandler#keyPressed(KeyboardEvent) - */ - @Override - public void keyPressed(KeyEvent e) { - - if (handler == null) { - return; - } - - Iterator iterator = keyboardEventArrayList.iterator(); - while (iterator.hasNext()) { - KeyboardEvent ke = iterator.next(); - if (ke.getKeyboardEventType() == KeyboardEventType.KEY_PRESSED && - ke.getKey() == e.getKeyCode()) { - handler.keyPressed(ke); - } - } - } - - /** - * @see KeyboardHandler#keyReleased(KeyboardEvent) - */ - @Override - public void keyReleased(KeyEvent e) { - - if (handler == null) { - return; - } - - Iterator iterator = keyboardEventArrayList.iterator(); - while (iterator.hasNext()) { - KeyboardEvent ke = iterator.next(); - if (ke.getKeyboardEventType() == KeyboardEventType.KEY_RELEASED && - ke.getKey() == e.getKeyCode()) { - handler.keyReleased(ke); - } - } - } -} diff --git a/src/main/java/com/codeforall/online/simplegraphics/mouse/Mouse.java b/src/main/java/com/codeforall/online/simplegraphics/mouse/Mouse.java deleted file mode 100644 index ed45375..0000000 --- a/src/main/java/com/codeforall/online/simplegraphics/mouse/Mouse.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.codeforall.online.simplegraphics.mouse; - -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import com.codeforall.online.simplegraphics.graphics.Canvas; - - -public class Mouse implements MouseListener, MouseMotionListener { - MouseHandler handler; - List mouseEventArrayList; - - public Mouse(MouseHandler var1) { - Canvas.getInstance().addMouseListener(this); - Canvas.getInstance().addMouseMotionListener(this); - this.handler = var1; - this.mouseEventArrayList = new ArrayList(); - } - - public void addEventListener(MouseEventType var1) { - this.mouseEventArrayList.add(var1); - } - - public void removeEventListener(MouseEventType var1) { - this.mouseEventArrayList.remove(var1); - } - - public void mouseClicked(MouseEvent var1) { - if (this.handler != null) { - Iterator var2 = this.mouseEventArrayList.iterator(); - - while(var2.hasNext()) { - MouseEventType var3 = (MouseEventType)var2.next(); - if (var3 == MouseEventType.MOUSE_CLICKED) { - this.handler.mouseClicked(new com.codeforall.online.simplegraphics.mouse.MouseEvent((double)var1.getX(), (double)var1.getY(), MouseEventType.MOUSE_CLICKED)); - } - } - } - - } - - public void mouseMoved(MouseEvent var1) { - if (this.handler != null) { - Iterator var2 = this.mouseEventArrayList.iterator(); - - while(var2.hasNext()) { - MouseEventType var3 = (MouseEventType)var2.next(); - if (var3 == MouseEventType.MOUSE_MOVED) { - this.handler.mouseMoved(new com.codeforall.online.simplegraphics.mouse.MouseEvent((double)var1.getX(), (double)var1.getY(), MouseEventType.MOUSE_MOVED)); - } - } - } - - } - - public void mousePressed(MouseEvent var1) { - } - - public void mouseReleased(MouseEvent var1) { - } - - public void mouseEntered(MouseEvent var1) { - } - - public void mouseExited(MouseEvent var1) { - } - - public void mouseDragged(MouseEvent var1) { - } -} diff --git a/src/main/java/com/codeforall/online/simplegraphics/mouse/MouseEvent.java b/src/main/java/com/codeforall/online/simplegraphics/mouse/MouseEvent.java deleted file mode 100644 index 16a5d88..0000000 --- a/src/main/java/com/codeforall/online/simplegraphics/mouse/MouseEvent.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.codeforall.online.simplegraphics.mouse; - -public class MouseEvent { - private double x; - private double y; - private MouseEventType eventType; - - public double getX() { - return this.x; - } - - public double getY() { - return this.y; - } - - public void setX(double var1) { - this.x = var1; - } - - public void setY(double var1) { - this.y = var1; - } - - public MouseEvent(double var1, double var3, MouseEventType var5) { - this.x = var1; - this.y = var3; - this.eventType = var5; - } - - public MouseEventType getEventType() { - return this.eventType; - } - - public String toString() { - return "MouseEvent{x=" + this.x + ", y=" + this.y + ", eventType=" + this.eventType + '}'; - } -} diff --git a/src/main/java/com/codeforall/simplegraphics/graphics/Canvas.java b/src/main/java/com/codeforall/simplegraphics/graphics/Canvas.java new file mode 100755 index 0000000..c19761b --- /dev/null +++ b/src/main/java/com/codeforall/simplegraphics/graphics/Canvas.java @@ -0,0 +1,266 @@ +package com.codeforall.simplegraphics.graphics; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.awt.Color; +import java.awt.Rectangle; +import java.awt.event.KeyListener; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.image.BufferedImage; +import java.awt.image.RescaleOp; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; + +/** + * Singleton Canvas class responsible for managing and displaying graphical shapes. + */ +public class Canvas { + + private static final int MIN_SIZE = 100; + private static final int MARGIN = 10; + private static final int LOCATION_OFFSET = 120; + + private static int MAX_X = 0; + private static int MAX_Y = 0; + private static Canvas instance = new Canvas(); + + private ArrayList shapes = new ArrayList<>(); + private BufferedImage background; + private JFrame frame; + private CanvasComponent component; + + /** + * Private constructor to enforce Singleton pattern. + */ + private Canvas() { + component = new CanvasComponent(); + + frame = new JFrame(); + frame.add(component); + frame.pack(); + frame.setLocation(LOCATION_OFFSET, LOCATION_OFFSET); + frame.setVisible(true); + } + + /** + * Sets the maximum width of the canvas. + * + * @param width maximum width + */ + public static void setMaxX(int width) { + MAX_X = width; + } + + /** + * Sets the maximum height of the canvas. + * + * @param height maximum height + */ + public static void setMaxY(int height) { + MAX_Y = height; + } + + /** + * Returns the singleton instance of the Canvas. + * + * @return Canvas instance + */ + public static Canvas getInstance() { + return instance; + } + + + /** + * Pauses so that the user can see the picture before it is transformed. + */ + public static void pause() { + JFrame frame = getInstance().frame; + + if (frame == null) { + return; + } + + JOptionPane.showMessageDialog(frame, "Click Ok to continue"); + } + + /** + * Takes a snapshot of the screen, fades it, and sets it as the background. + */ + public static void snapshot() { + Dimension dim = getInstance().component.getPreferredSize(); + Rectangle rect = new Rectangle(0, 0, dim.width, dim.height); + BufferedImage image = new BufferedImage(rect.width, rect.height, BufferedImage.TYPE_INT_RGB); + + Graphics g = image.getGraphics(); + g.setColor(Color.WHITE); + g.fillRect(0, 0, rect.width, rect.height); + g.setColor(Color.BLACK); + getInstance().component.paintComponent(g); + + float factor = 0.8f; + float base = 255f * (1f - factor); + RescaleOp op = new RescaleOp(factor, base, null); + BufferedImage filteredImage = new BufferedImage(image.getWidth(), image.getHeight(), image.getType()); + op.filter(image, filteredImage); + getInstance().background = filteredImage; + getInstance().component.repaint(); + } + + /** + * Displays the given shape on the canvas. + * + * @param shape the shape to display + */ + public void show(Shape shape) { + if (!shapes.contains(shape)) { + shapes.add(shape); + } + + repaint(); + } + + /** + * Hides the given shape from the canvas. + * + * @param shape the shape to hide + */ + public void hide(Shape shape) { + if (shapes.contains(shape)) { + shapes.remove(shape); + } + + repaint(); + } + + /** + * Repaints the canvas if needed. + */ + public void repaint() { + if (frame == null) { + return; + } + + Dimension dim = component.getPreferredSize(); + + if (dim.getWidth() > component.getWidth() + || dim.getHeight() > component.getHeight()) { + frame.pack(); + + } else { + frame.repaint(); + } + } + + /** + * Saves the current canvas view to disk as an image. + * + * @param fileName the path and fileName to save to + */ + public void saveToDisk(String fileName) { + Dimension dim = component.getPreferredSize(); + Rectangle rect = new Rectangle(0, 0, dim.width, dim.height); + BufferedImage image = new BufferedImage(rect.width, rect.height, BufferedImage.TYPE_INT_RGB); + + Graphics2D g = (Graphics2D) image.getGraphics(); + g.setColor(Color.WHITE); + g.fill(rect); + g.setColor(Color.BLACK); + component.paintComponent(g); + + String extension = fileName.substring(fileName.lastIndexOf('.') + 1); + + try { + ImageIO.write(image, extension, new File(fileName)); + + } catch (IOException e) { + System.err.println("Was unable to save the image to " + fileName); + } + + g.dispose(); + } + + /** + * Adds a KeyListener to the canvas. + * + * @param handler the KeyListener to add + */ + public void addKeyListener(KeyListener handler) { + frame.addKeyListener(handler); + } + + /** + * Adds a MouseListener to the canvas. + * + * @param handler the MouseListener to add + */ + public void addMouseListener(MouseListener handler) { + frame.addMouseListener(handler); + } + + /** + * Adds a MouseMotionListener to the canvas. + * + * @param handler the MouseMotionListener to add + */ + public void addMouseMotionListener(MouseMotionListener handler) { + frame.addMouseMotionListener(handler); + } + + /** + * Inner component class responsible for custom painting of the canvas. + */ + class CanvasComponent extends JComponent { + CanvasComponent() { + } + + /** + * Paints the component by drawing the background and all visible shapes. + * + * @param g the Graphics context in which to paint + */ + public void paintComponent(Graphics g) { + g.setColor(Color.WHITE); + g.fillRect(0, 0, getWidth(), getHeight()); + g.setColor(Color.BLACK); + + if (background != null) { + g.drawImage(background, 0, 0, null); + } + + for (Shape s : new ArrayList<>(shapes)) { + Graphics2D g2D = (Graphics2D) g.create(); + s.paintShape(g2D); + g2D.dispose(); + } + } + + /** + * Calculates the preferred size of the canvas based on the shapes and background image. + * + * @return the preferred Dimension of the canvas + */ + public Dimension getPreferredSize() { + int width = Canvas.MAX_X == 0 ? MIN_SIZE : Canvas.MAX_X; + int height = Canvas.MAX_Y == 0 ? MIN_SIZE : Canvas.MAX_Y; + + if (background != null) { + width = Math.max(width, background.getWidth()); + height = Math.max(width, background.getHeight()); + } + + if (Canvas.MAX_X == 0 && Canvas.MAX_Y == 0) { + + for (Shape s : shapes) { + width = Math.max(width, s.getX() + s.getWidth()); + height = Math.max(height, s.getY() + s.getHeight()); + } + + } + + return new Dimension(width + MARGIN, height + MARGIN); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/codeforall/online/simplegraphics/graphics/Color.java b/src/main/java/com/codeforall/simplegraphics/graphics/Color.java similarity index 63% rename from src/main/java/com/codeforall/online/simplegraphics/graphics/Color.java rename to src/main/java/com/codeforall/simplegraphics/graphics/Color.java index 9f8c275..fd49524 100755 --- a/src/main/java/com/codeforall/online/simplegraphics/graphics/Color.java +++ b/src/main/java/com/codeforall/simplegraphics/graphics/Color.java @@ -1,15 +1,20 @@ -package com.codeforall.online.simplegraphics.graphics; +package com.codeforall.simplegraphics.graphics; +/** + * Represents a simple RGB color definition used for graphical shapes. + * This class provides predefined constants for commonly used colors + * and allows the creation of custom colors using red, green, and blue components. + * Values for red, green, and blue should be between 0 and 255. + * Note: This class is distinct from {@code java.awt.Color} + * and is intended for use within the simplegraphics library. + */ public class Color { - private int red; - private int green; - private int blue; - - // Color constants public static final Color RED = new Color(255, 0, 0); public static final Color GREEN = new Color(0, 255, 0); public static final Color BLUE = new Color(0, 0, 255); + + // Color constants public static final Color WHITE = new Color(255, 255, 255); public static final Color LIGHT_GRAY = new Color(192, 192, 192); public static final Color GRAY = new Color(128, 128, 128); @@ -20,15 +25,19 @@ public class Color { public static final Color YELLOW = new Color(255, 255, 0); public static final Color PINK = new Color(255, 175, 175); public static final Color ORANGE = new Color(255, 200, 0); - + + private int red; + private int green; + private int blue; + /** * Constructs a new Color object. - * @param red the red value of the color (between 0 and 255) + * + * @param red the red value of the color (between 0 and 255) * @param green the green value of the color (between 0 and 255) - * @param blue the blue value of the color (between 0 and 255) + * @param blue the blue value of the color (between 0 and 255) */ - public Color(int red, int green, int blue) - { + public Color(int red, int green, int blue) { this.red = red; this.green = green; this.blue = blue; @@ -36,28 +45,28 @@ public Color(int red, int green, int blue) /** * Gets the red value of this color. + * * @return the red value (between 0 and 255) */ - public int getRed() - { - return red; + public int getRed() { + return red; } /** * Gets the green value of this color. + * * @return the green value (between 0 and 255) */ - public int getGreen() - { - return green; + public int getGreen() { + return green; } /** * Gets the blue value of this color. + * * @return the blue value (between 0 and 255) */ - public int getBlue() - { - return blue; + public int getBlue() { + return blue; } } diff --git a/src/main/java/com/codeforall/online/simplegraphics/graphics/Colorable.java b/src/main/java/com/codeforall/simplegraphics/graphics/Colorable.java similarity index 82% rename from src/main/java/com/codeforall/online/simplegraphics/graphics/Colorable.java rename to src/main/java/com/codeforall/simplegraphics/graphics/Colorable.java index d71a1be..5c2afc0 100644 --- a/src/main/java/com/codeforall/online/simplegraphics/graphics/Colorable.java +++ b/src/main/java/com/codeforall/simplegraphics/graphics/Colorable.java @@ -1,4 +1,4 @@ -package com.codeforall.online.simplegraphics.graphics; +package com.codeforall.simplegraphics.graphics; /** * Methods for modifying a shape color diff --git a/src/main/java/com/codeforall/online/simplegraphics/graphics/Ellipse.java b/src/main/java/com/codeforall/simplegraphics/graphics/Ellipse.java similarity index 71% rename from src/main/java/com/codeforall/online/simplegraphics/graphics/Ellipse.java rename to src/main/java/com/codeforall/simplegraphics/graphics/Ellipse.java index e058ef2..33c8bc4 100755 --- a/src/main/java/com/codeforall/online/simplegraphics/graphics/Ellipse.java +++ b/src/main/java/com/codeforall/simplegraphics/graphics/Ellipse.java @@ -1,9 +1,23 @@ -package com.codeforall.online.simplegraphics.graphics; +package com.codeforall.simplegraphics.graphics; import java.awt.*; import java.awt.geom.Ellipse2D; +/** + * Represents an ellipse shape that can be drawn, filled, moved, and resized. + * The ellipse is defined by its bounding box, which determines its x/y position, width, and height. + * This class integrates with the {@link Canvas} to visually render itself. + * + * Implements: + *
    + *
  • {@link Shape} – for rendering and bounding box info
  • + *
  • {@link Colorable} – for setting its color
  • + *
  • {@link Fillable} – for supporting fill operations
  • + *
  • {@link Movable} – for translation and scaling
  • + *
+ */ public class Ellipse implements Shape, Colorable, Fillable, Movable { + private Color color = Color.BLACK; private boolean filled = false; private double x; @@ -73,6 +87,7 @@ public int getHeight() { * @param dx the amount by which to move in x-direction * @param dy the amount by which to move in y-direction */ + @Override public void translate(double dx, double dy) { x += dx; y += dy; @@ -85,6 +100,7 @@ public void translate(double dx, double dy) { * @param dw the amount by which to resize the width on each side * @param dh the amount by which to resize the height on each side */ + @Override public void grow(double dw, double dh) { width += 2 * dw; height += 2 * dh; @@ -98,6 +114,7 @@ public void grow(double dw, double dh) { * * @param newColor the new color */ + @Override public void setColor(Color newColor) { color = newColor; Canvas.getInstance().repaint(); @@ -106,6 +123,7 @@ public void setColor(Color newColor) { /** * Draws this ellipse on the canvas. */ + @Override public void draw() { filled = false; Canvas.getInstance().show(this); @@ -114,6 +132,7 @@ public void draw() { /** * Deletes this ellipse from the canvas */ + @Override public void delete() { Canvas.getInstance().hide(this); } @@ -121,22 +140,38 @@ public void delete() { /** * Fills this ellipse. */ + @Override public void fill() { filled = true; Canvas.getInstance().show(this); } + /** + * Returns a string representation of this ellipse. + * + * @return a string describing the ellipse's position and dimensions + */ + @Override public String toString() { return "Ellipse[x=" + getX() + ",y=" + getY() + ",width=" + getWidth() + ",height=" + getHeight() + "]"; } - public void paintShape(Graphics2D g2) { + /** + * Paints this ellipse using the given Graphics2D context. + * This is called by the canvas to render the shape. + * + * @param g2D the Graphics2D context to draw with + */ + @Override + public void paintShape(Graphics2D g2D) { Ellipse2D.Double ellipse = new Ellipse2D.Double(getX(), getY(), getWidth(), getHeight()); - g2.setColor(new java.awt.Color((int) color.getRed(), (int) color.getGreen(), (int) color.getBlue())); + g2D.setColor(new java.awt.Color((int) color.getRed(), (int) color.getGreen(), (int) color.getBlue())); + if (filled) { - g2.fill(ellipse); + g2D.fill(ellipse); + } else { - g2.draw(ellipse); + g2D.draw(ellipse); } } } diff --git a/src/main/java/com/codeforall/online/simplegraphics/graphics/Fillable.java b/src/main/java/com/codeforall/simplegraphics/graphics/Fillable.java similarity index 73% rename from src/main/java/com/codeforall/online/simplegraphics/graphics/Fillable.java rename to src/main/java/com/codeforall/simplegraphics/graphics/Fillable.java index f59c6b6..2ef4b9d 100644 --- a/src/main/java/com/codeforall/online/simplegraphics/graphics/Fillable.java +++ b/src/main/java/com/codeforall/simplegraphics/graphics/Fillable.java @@ -1,4 +1,4 @@ -package com.codeforall.online.simplegraphics.graphics; +package com.codeforall.simplegraphics.graphics; /** * Methods for filling a shape @@ -9,5 +9,4 @@ public interface Fillable { * Paints the shape with the current shape color */ void fill(); - } diff --git a/src/main/java/com/codeforall/simplegraphics/graphics/Line.java b/src/main/java/com/codeforall/simplegraphics/graphics/Line.java new file mode 100755 index 0000000..284b836 --- /dev/null +++ b/src/main/java/com/codeforall/simplegraphics/graphics/Line.java @@ -0,0 +1,176 @@ +package com.codeforall.simplegraphics.graphics; + +import java.awt.*; +import java.awt.geom.Line2D; + +/** + * Represents a straight line defined by two endpoints. + * The line can be drawn, translated, resized, or deleted from a canvas. + * It supports color customization and integrates with the {@link Canvas} for rendering. + * + * Implements: + *
    + *
  • {@link Shape} – provides geometric and canvas-renderable properties
  • + *
  • {@link Colorable} – allows setting the drawing color
  • + *
  • {@link Movable} – supports translation and resizing via grow
  • + *
+ */ +public class Line implements Shape, Colorable, Movable { + + private Color color = Color.BLACK; + private double startX; + private double startY; + private double endX; + private double endY; + + /** + * Constructs a line with a given starting and ending location. + * + * @param startX the x-coordinate of the starting point + * @param startY the y-coordinate of the starting point + * @param endX the x-coordinate of the ending point + * @param endY the y-coordinate of the ending point + */ + public Line(double startX, double startY, double endX, double endY) { + this.startX = startX; + this.endX = endX; + this.startY = startY; + this.endY = endY; + } + + /** + * Gets the leftmost x-position of the line. + * + * @return the leftmost x-position + */ + @Override + public int getX() { + return (int) Math.round(Math.min(startX, endX)); + } + + /** + * Gets the topmost y-position of the line. + * + * @return the topmost y-position + */ + @Override + public int getY() { + return (int) Math.round(Math.min(startY, endY)); + } + + /** + * Gets the width of the bounding box. + * + * @return the width + */ + @Override + public int getWidth() { + return (int) Math.round(Math.abs(endX - startX)); + } + + /** + * Gets the height of the bounding box. + * + * @return the height + */ + @Override + public int getHeight() { + return (int) Math.round(Math.abs(endY - startY)); + } + + /** + * Moves this line by a given amount. + * + * @param dx the amount by which to move in x-direction + * @param dy the amount by which to move in y-direction + */ + @Override + public void translate(double dx, double dy) { + startX += dx; + startY += dy; + endX += dx; + endY += dy; + Canvas.getInstance().repaint(); + } + + /** + * Resizes this line both horizontally and vertically. + * + * @param dw the amount by which to resize the width on each side + * @param dh the amount by which to resize the height on each side + */ + @Override + public void grow(double dw, double dh) { + + if (startX <= endX) { + startX -= dw; + endX += dw; + + } else { + startX += dw; + endX -= dw; + } + + if (startY <= endY) { + startY -= dh; + endY += dh; + + } else { + startY += dh; + endY -= dh; + } + + Canvas.getInstance().repaint(); + } + + /** + * Sets the color for drawing this line. + * + * @param newColor the new color + */ + @Override + public void setColor(Color newColor) { + color = newColor; + Canvas.getInstance().repaint(); + } + + /** + * Shows this line on the canvas. + */ + @Override + public void draw() { + Canvas.getInstance().show(this); + } + + /** + * Deletes this line from the canvas. + */ + @Override + public void delete() { + Canvas.getInstance().hide(this); + } + + /** + * Returns a string representation of the line, including both endpoints. + * + * @return a string describing the line's coordinates + */ + @Override + public String toString() { + return "Line[startX=" + startX + ",startY=" + startY + ",endX=" + endX + ",endY=" + endY + "]"; + } + + /** + * Paints the line using the specified Graphics2D context. + * + * @param g2D the graphics context to paint with + */ + @Override + public void paintShape(Graphics2D g2D) { + if (color != null) { + g2D.setColor(new java.awt.Color((int) color.getRed(), (int) color.getGreen(), (int) color.getBlue())); + Line2D.Double line = new Line2D.Double(startX, startY, endX, endY); + g2D.draw(line); + } + } +} diff --git a/src/main/java/com/codeforall/online/simplegraphics/graphics/Movable.java b/src/main/java/com/codeforall/simplegraphics/graphics/Movable.java similarity index 69% rename from src/main/java/com/codeforall/online/simplegraphics/graphics/Movable.java rename to src/main/java/com/codeforall/simplegraphics/graphics/Movable.java index d90e9d7..a98bdbd 100644 --- a/src/main/java/com/codeforall/online/simplegraphics/graphics/Movable.java +++ b/src/main/java/com/codeforall/simplegraphics/graphics/Movable.java @@ -1,4 +1,4 @@ -package com.codeforall.online.simplegraphics.graphics; +package com.codeforall.simplegraphics.graphics; /** * Methods for moving a shape @@ -11,6 +11,5 @@ public interface Movable { * @param dx the amount by which to move in x-direction * @param dy the amount by which to move in y-direction */ - public void translate(double dx, double dy); - + void translate(double dx, double dy); } diff --git a/src/main/java/com/codeforall/online/simplegraphics/graphics/Rectangle.java b/src/main/java/com/codeforall/simplegraphics/graphics/Rectangle.java similarity index 71% rename from src/main/java/com/codeforall/online/simplegraphics/graphics/Rectangle.java rename to src/main/java/com/codeforall/simplegraphics/graphics/Rectangle.java index 6fd4c43..3fb45ac 100755 --- a/src/main/java/com/codeforall/online/simplegraphics/graphics/Rectangle.java +++ b/src/main/java/com/codeforall/simplegraphics/graphics/Rectangle.java @@ -1,9 +1,26 @@ -package com.codeforall.online.simplegraphics.graphics; +package com.codeforall.simplegraphics.graphics; import java.awt.*; import java.awt.geom.Rectangle2D; +/** + * The {@code Rectangle} class represents a drawable and optionally filled rectangle + * that can be displayed on a canvas. This class allows manipulation of the rectangle's + * size, position, and color, and provides basic drawing and transformation capabilities. + * + * Implements: + *
    + *
  • {@link com.codeforall.simplegraphics.graphics.Shape} – for rendering and bounding box info
  • + *
  • {@link Colorable} – for setting its color
  • + *
  • {@link Fillable} – for supporting fill operations
  • + *
  • {@link Movable} – for translation and scaling
  • + *
+ * + * Note: This class is distinct from {@code java.awt.Rectangle} + * and is intended for use within the simplegraphics library. + */ public class Rectangle implements Shape, Colorable, Fillable, Movable { + private Color color = Color.BLACK; private boolean filled = false; private double x; @@ -82,6 +99,7 @@ public int getHeight() { * @param dx the amount by which to move in x-direction * @param dy the amount by which to move in y-direction */ + @Override public void translate(double dx, double dy) { x += dx; y += dy; @@ -139,22 +157,31 @@ public void fill() { Canvas.getInstance().show(this); } + /** + * Returns a string representation of the rectangle, including both endpoints. + * + * @return a string describing the rectangle's coordinates + */ @Override public String toString() { return "Rectangle[x=" + getX() + ",y=" + getY() + ",width=" + getWidth() + ",height=" + getHeight() + "]"; } + /** + * Paints the rectangle using the specified Graphics2D context. + * + * @param g2D the graphics context to paint with + */ @Override - public void paintShape(Graphics2D g2) { + public void paintShape(Graphics2D g2D) { Rectangle2D.Double rect = new Rectangle2D.Double(getX(), getY(), getWidth(), getHeight()); - g2.setColor(new java.awt.Color((int) color.getRed(), (int) color.getGreen(), (int) color.getBlue())); + g2D.setColor(new java.awt.Color((int) color.getRed(), (int) color.getGreen(), (int) color.getBlue())); if (filled) { - - g2.fill(rect); + g2D.fill(rect); } else { - g2.draw(rect); + g2D.draw(rect); } } } diff --git a/src/main/java/com/codeforall/online/simplegraphics/graphics/Shape.java b/src/main/java/com/codeforall/simplegraphics/graphics/Shape.java similarity index 88% rename from src/main/java/com/codeforall/online/simplegraphics/graphics/Shape.java rename to src/main/java/com/codeforall/simplegraphics/graphics/Shape.java index f1a8589..7c4c313 100755 --- a/src/main/java/com/codeforall/online/simplegraphics/graphics/Shape.java +++ b/src/main/java/com/codeforall/simplegraphics/graphics/Shape.java @@ -1,4 +1,4 @@ -package com.codeforall.online.simplegraphics.graphics; +package com.codeforall.simplegraphics.graphics; import java.awt.*; @@ -6,6 +6,7 @@ * A shape that can be drawn on a canvas. */ public interface Shape { + /** * Gets the leftmost x-position of the shape. * @@ -55,8 +56,7 @@ public interface Shape { /** * Paints the shape * - * @param g2 the graphics object + * @param g2D the graphics object */ - void paintShape(Graphics2D g2); - + void paintShape(Graphics2D g2D); } diff --git a/src/main/java/com/codeforall/online/simplegraphics/graphics/Text.java b/src/main/java/com/codeforall/simplegraphics/graphics/Text.java similarity index 73% rename from src/main/java/com/codeforall/online/simplegraphics/graphics/Text.java rename to src/main/java/com/codeforall/simplegraphics/graphics/Text.java index ce74b9a..53b7b3b 100755 --- a/src/main/java/com/codeforall/online/simplegraphics/graphics/Text.java +++ b/src/main/java/com/codeforall/simplegraphics/graphics/Text.java @@ -1,9 +1,25 @@ -package com.codeforall.online.simplegraphics.graphics; +package com.codeforall.simplegraphics.graphics; import javax.swing.*; import java.awt.*; +/** + * The {@code Text} class represents a drawable text label that can be displayed + * on a canvas. It allows setting the text content, changing its position, resizing + * the bounding box, and customizing its color. + * The text is rendered using a {@link JLabel} and drawn via a {@link Graphics2D} + * context. + * + * Implements: + *
    + *
  • {@link Shape} – for rendering and bounding box info
  • + *
  • {@link Colorable} – for setting its color
  • + *
  • {@link Movable} – for translation and scaling
  • + *
+ * + */ public class Text implements Shape, Colorable, Movable { + private Color color = Color.BLACK; private JLabel label = new JLabel(); private double x; @@ -68,6 +84,7 @@ public int getHeight() { * @param dx the amount by which to move in x-direction * @param dy the amount by which to move in y-direction */ + @Override public void translate(double dx, double dy) { x += dx; y += dy; @@ -91,6 +108,7 @@ public void grow(double dw, double dh) { * * @param newColor the new color */ + @Override public void setColor(Color newColor) { color = newColor; Canvas.getInstance().repaint(); @@ -119,19 +137,31 @@ public void delete() { Canvas.getInstance().hide(this); } + /** + * Returns a string representation of the text, including both endpoints and the content. + * + * @return a string describing the text's coordinates and content + */ public String toString() { return "Text[x=" + getX() + ",y=" + getY() + ",message=" + label.getText() + "]"; } - public void paintShape(Graphics2D g2) { + /** + * Paints the text using the specified Graphics2D context. + * + * @param g2D the graphics context to paint with + */ + public void paintShape(Graphics2D g2D) { + if (color != null) { label.setForeground(new java.awt.Color((int) color.getRed(), (int) color.getGreen(), (int) color.getBlue())); Dimension dim = label.getPreferredSize(); + if (dim.width > 0 && dim.height > 0) { label.setBounds(0, 0, dim.width, dim.height); - g2.translate(getX(), getY()); - g2.scale(getWidth() / dim.width, getHeight() / dim.height); - label.paint(g2); + g2D.translate(getX(), getY()); + g2D.scale(getWidth() / dim.width, getHeight() / dim.height); + label.paint(g2D); } } } diff --git a/src/main/java/com/codeforall/simplegraphics/keyboard/Keyboard.java b/src/main/java/com/codeforall/simplegraphics/keyboard/Keyboard.java new file mode 100644 index 0000000..6a2ce98 --- /dev/null +++ b/src/main/java/com/codeforall/simplegraphics/keyboard/Keyboard.java @@ -0,0 +1,133 @@ +package com.codeforall.simplegraphics.keyboard; + +import com.codeforall.simplegraphics.graphics.Canvas; + +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.ArrayList; +import java.util.List; +import java.util.Iterator; + +/** + * Instantiate a Keyboard for obtaining key handling capability + */ +public class Keyboard implements KeyListener { + + private KeyboardHandler handler; + private List keyboardEvents; + + public Keyboard(KeyboardHandler handler) { + Canvas.getInstance().addKeyListener(this); + + this.handler = handler; + keyboardEvents = new ArrayList<>(); + } + + /** + * Add a new Keyboard event listener + * + * @param keyboardEvent the event to add + */ + public void addEventListener(KeyboardEvent keyboardEvent) { + keyboardEvents.add(keyboardEvent); + } + + /** + * Remove an existing Keyboard event listener + * + * @param keyboardEvent the event to remove + */ + public void removeEventListener(KeyboardEvent keyboardEvent) { + keyboardEvents.remove(keyboardEvent); + } + + /** + * @param e the event + * @see KeyListener#keyTyped(KeyEvent) + */ + @Override + public void keyTyped(KeyEvent e) { + } + + /** + * @param e the event + * @see KeyboardHandler#keyPressed(KeyboardEvent) + */ + @Override + public void keyPressed(KeyEvent e) { + + if (handler == null) { + return; + } + + Iterator iterator = keyboardEvents.iterator(); + + while (iterator.hasNext()) { + KeyboardEvent event = iterator.next(); + + if (event.getKeyboardEventType() == KeyboardEventType.KEY_PRESSED && + event.getKey() == e.getKeyCode()) { + handler.keyPressed(event); + } + } + } + + /** + * @param e the event + * @see KeyboardHandler#keyReleased(KeyboardEvent) + */ + @Override + public void keyReleased(KeyEvent e) { + + if (handler == null) { + return; + } + + Iterator iterator = keyboardEvents.iterator(); + + while (iterator.hasNext()) { + KeyboardEvent event = iterator.next(); + + if (event.getKeyboardEventType() == KeyboardEventType.KEY_RELEASED && + event.getKey() == e.getKeyCode()) { + handler.keyReleased(event); + } + } + } + + /** + * Returns the current {@link KeyboardHandler} assigned to handle keyboard events. + * + * @return the keyboard handler + */ + public KeyboardHandler getHandler() { + return handler; + } + + /** + * Sets the {@link KeyboardHandler} that will be used to handle keyboard events. + * + * @param handler the keyboard handler to set + */ + public void setHandler(KeyboardHandler handler) { + this.handler = handler; + } + + /** + * Returns the list of registered {@link KeyboardEvent}s that this class listens for. + * + * @return the list of keyboard events + */ + public List getKeyboardEvents() { + return keyboardEvents; + } + + /** + * Sets the list of {@link KeyboardEvent}s that this class should listen for. + * + * @param keyboardEvents the list of keyboard events to set + */ + public void setKeyboardEvents(List keyboardEvents) { + this.keyboardEvents = keyboardEvents; + } +} diff --git a/src/main/java/com/codeforall/online/simplegraphics/keyboard/KeyboardEvent.java b/src/main/java/com/codeforall/simplegraphics/keyboard/KeyboardEvent.java similarity index 98% rename from src/main/java/com/codeforall/online/simplegraphics/keyboard/KeyboardEvent.java rename to src/main/java/com/codeforall/simplegraphics/keyboard/KeyboardEvent.java index 0dae99f..e807f1b 100644 --- a/src/main/java/com/codeforall/online/simplegraphics/keyboard/KeyboardEvent.java +++ b/src/main/java/com/codeforall/simplegraphics/keyboard/KeyboardEvent.java @@ -1,4 +1,4 @@ -package com.codeforall.online.simplegraphics.keyboard; +package com.codeforall.simplegraphics.keyboard; import java.awt.event.KeyEvent; @@ -75,7 +75,6 @@ public class KeyboardEvent { public static final int KEY_SHIFT = KeyEvent.VK_SHIFT; public static final int KEY_TAB = KeyEvent.VK_TAB; - private KeyboardEventType keyboardEventType; private int key; diff --git a/src/main/java/com/codeforall/online/simplegraphics/keyboard/KeyboardEventType.java b/src/main/java/com/codeforall/simplegraphics/keyboard/KeyboardEventType.java similarity index 72% rename from src/main/java/com/codeforall/online/simplegraphics/keyboard/KeyboardEventType.java rename to src/main/java/com/codeforall/simplegraphics/keyboard/KeyboardEventType.java index d8bf5aa..47bc4d8 100644 --- a/src/main/java/com/codeforall/online/simplegraphics/keyboard/KeyboardEventType.java +++ b/src/main/java/com/codeforall/simplegraphics/keyboard/KeyboardEventType.java @@ -1,10 +1,11 @@ -package com.codeforall.online.simplegraphics.keyboard; +package com.codeforall.simplegraphics.keyboard; /** * The type of events supported by the Keyboard * @see Keyboard */ public enum KeyboardEventType { + KEY_PRESSED, KEY_RELEASED } diff --git a/src/main/java/com/codeforall/online/simplegraphics/keyboard/KeyboardHandler.java b/src/main/java/com/codeforall/simplegraphics/keyboard/KeyboardHandler.java similarity index 72% rename from src/main/java/com/codeforall/online/simplegraphics/keyboard/KeyboardHandler.java rename to src/main/java/com/codeforall/simplegraphics/keyboard/KeyboardHandler.java index 8ef6db5..eeb0779 100644 --- a/src/main/java/com/codeforall/online/simplegraphics/keyboard/KeyboardHandler.java +++ b/src/main/java/com/codeforall/simplegraphics/keyboard/KeyboardHandler.java @@ -1,4 +1,4 @@ -package com.codeforall.online.simplegraphics.keyboard; +package com.codeforall.simplegraphics.keyboard; import java.awt.event.KeyEvent; @@ -12,12 +12,11 @@ public interface KeyboardHandler { * @see java.awt.event.KeyListener#keyPressed(KeyEvent) * @param e the event */ - public void keyPressed(KeyboardEvent e); + void keyPressed(KeyboardEvent e); /** * @see java.awt.event.KeyListener#keyReleased(KeyEvent) * @param e the event */ - public void keyReleased(KeyboardEvent e); - + void keyReleased(KeyboardEvent e); } diff --git a/src/main/java/com/codeforall/simplegraphics/mouse/Mouse.java b/src/main/java/com/codeforall/simplegraphics/mouse/Mouse.java new file mode 100644 index 0000000..c3feaef --- /dev/null +++ b/src/main/java/com/codeforall/simplegraphics/mouse/Mouse.java @@ -0,0 +1,156 @@ +package com.codeforall.simplegraphics.mouse; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import com.codeforall.simplegraphics.graphics.Canvas; + +/** + * Instantiate a Mouse for obtaining mouse handling capability + */ +public class Mouse implements MouseListener, MouseMotionListener { + + private MouseHandler handler; + private List mouseEventTypes; + + public Mouse(MouseHandler handler) { + Canvas.getInstance().addMouseListener(this); + Canvas.getInstance().addMouseMotionListener(this); + + this.handler = handler; + this.mouseEventTypes = new ArrayList(); + } + + /** + * Add a new Mouse event listener + * + * @param mouseEventType the event type to add + */ + public void addEventListener(MouseEventType mouseEventType) { + mouseEventTypes.add(mouseEventType); + } + + /** + * Remove an existing Mouse event listener + * + * @param mouseEventType the event to remove + */ + public void removeEventListener(MouseEventType mouseEventType) { + mouseEventTypes.remove(mouseEventType); + } + + /** + * @param e the event to be processed + * @see MouseListener#mouseClicked(MouseEvent) + */ + @Override + public void mouseClicked(MouseEvent e) { + + if (handler != null) { + Iterator iterator = mouseEventTypes.iterator(); + + while (iterator.hasNext()) { + MouseEventType eventType = (MouseEventType) iterator.next(); + + if (eventType == MouseEventType.MOUSE_CLICKED) { + handler.mouseClicked(new com.codeforall.simplegraphics.mouse.MouseEvent(e.getX(), e.getY(), MouseEventType.MOUSE_CLICKED)); + } + } + } + } + + /** + * @param e the event to be processed + * @see MouseMotionListener#mouseMoved(MouseEvent) + */ + @Override + public void mouseMoved(MouseEvent e) { + + if (handler != null) { + Iterator iterator = mouseEventTypes.iterator(); + + while (iterator.hasNext()) { + MouseEventType eventType = (MouseEventType) iterator.next(); + + if (eventType == MouseEventType.MOUSE_MOVED) { + handler.mouseMoved(new com.codeforall.simplegraphics.mouse.MouseEvent(e.getX(), e.getY(), MouseEventType.MOUSE_MOVED)); + } + } + } + } + + /** + * @param e the event to be processed + * @see MouseListener#mousePressed(MouseEvent) + */ + @Override + public void mousePressed(MouseEvent e) {} + + /** + * @param e the event to be processed + * @see MouseListener#mouseReleased(MouseEvent) + */ + @Override + public void mouseReleased(MouseEvent e) {} + + /** + * @param e the event to be processed + * @see MouseListener#mouseEntered(MouseEvent) + */ + @Override + public void mouseEntered(MouseEvent e) {} + + /** + * @param e the event to be processed + * @see MouseListener#mouseExited(MouseEvent) + */ + @Override + public void mouseExited(MouseEvent e) {} + + /** + * @param e the event to be processed + * @see MouseMotionListener#mouseDragged(MouseEvent) + */ + @Override + public void mouseDragged(MouseEvent e) {} + + /** + * Returns the current {@link MouseHandler} assigned to handle mouse events. + * + * @return the mouse handler + */ + public MouseHandler getHandler() { + return handler; + } + + /** + * Sets the {@link MouseHandler} that will be used to handle mouse events. + * + * @param handler the mouse handler to set + */ + public void setHandler(MouseHandler handler) { + this.handler = handler; + } + + /** + * Returns the list of registered {@link MouseEventType}s that this class listens for. + * + * @return the list of mouse event types + */ + public List getMouseEventTypes() { + return mouseEventTypes; + } + + /** + * Sets the list of {@link MouseEventType}s that this class should listen for. + * + * @param mouseEventTypes the list of mouse event types to set + */ + public void setMouseEventTypes(List mouseEventTypes) { + this.mouseEventTypes = mouseEventTypes; + } +} diff --git a/src/main/java/com/codeforall/simplegraphics/mouse/MouseEvent.java b/src/main/java/com/codeforall/simplegraphics/mouse/MouseEvent.java new file mode 100644 index 0000000..241e6e3 --- /dev/null +++ b/src/main/java/com/codeforall/simplegraphics/mouse/MouseEvent.java @@ -0,0 +1,70 @@ +package com.codeforall.simplegraphics.mouse; + +/** + * Mouse event containing x and y coordinates and the mouse event type + */ +public class MouseEvent { + + private double x; + private double y; + private MouseEventType eventType; + + public MouseEvent(double x, double y, MouseEventType mouseEventType) { + this.x = x; + this.y = y; + this.eventType = mouseEventType; + } + + /** + * Gets the X coordinate where the mouse clicked + * @return the x coordinate + */ + public double getX() { + return x; + } + + /** + * Gets the Y coordinate where the mouse cliecked + * @return the y coordinate + */ + public double getY() { + return y; + } + + /** + * Sets the x-coordinate of the mouse event. + * + * @param x the new x-coordinate + */ + public void setX(double x) { + this.x = x; + } + + /** + * Sets the y-coordinate of the mouse event. + * + * @param y the new y-coordinate + */ + public void setY(double y) { + this.y = y; + } + + /** + * Gets the type of this mouse event. + * + * @return the {@link MouseEventType} for this event + */ + public MouseEventType getEventType() { + return eventType; + } + + /** + * Returns a string representation of the mouse event, including coordinates and event type. + * + * @return a string describing the event + */ + @Override + public String toString() { + return "MouseEvent{x=" + x + ", y=" + y + ", eventType=" + eventType + '}'; + } +} diff --git a/src/main/java/com/codeforall/online/simplegraphics/mouse/MouseEventType.java b/src/main/java/com/codeforall/simplegraphics/mouse/MouseEventType.java similarity index 67% rename from src/main/java/com/codeforall/online/simplegraphics/mouse/MouseEventType.java rename to src/main/java/com/codeforall/simplegraphics/mouse/MouseEventType.java index 01bd08e..a17b454 100644 --- a/src/main/java/com/codeforall/online/simplegraphics/mouse/MouseEventType.java +++ b/src/main/java/com/codeforall/simplegraphics/mouse/MouseEventType.java @@ -1,6 +1,7 @@ -package com.codeforall.online.simplegraphics.mouse; +package com.codeforall.simplegraphics.mouse; public enum MouseEventType { + MOUSE_CLICKED, MOUSE_MOVED; diff --git a/src/main/java/com/codeforall/online/simplegraphics/mouse/MouseHandler.java b/src/main/java/com/codeforall/simplegraphics/mouse/MouseHandler.java similarity index 73% rename from src/main/java/com/codeforall/online/simplegraphics/mouse/MouseHandler.java rename to src/main/java/com/codeforall/simplegraphics/mouse/MouseHandler.java index 83de890..c0b19e4 100644 --- a/src/main/java/com/codeforall/online/simplegraphics/mouse/MouseHandler.java +++ b/src/main/java/com/codeforall/simplegraphics/mouse/MouseHandler.java @@ -1,21 +1,21 @@ -package com.codeforall.online.simplegraphics.mouse; +package com.codeforall.simplegraphics.mouse; /** * Interface to be implemented by all classes that want to receive mouse events + * * @see MouseEvent */ public interface MouseHandler { /** - * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent) * @param e the event + * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent) */ - public void mouseClicked(MouseEvent e); + void mouseClicked(MouseEvent e); /** - * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent) * @param e the event + * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent) */ - public void mouseMoved(MouseEvent e); - + void mouseMoved(MouseEvent e); } diff --git a/src/main/java/com/codeforall/online/simplegraphics/pictures/Color.java b/src/main/java/com/codeforall/simplegraphics/pictures/Color.java similarity index 74% rename from src/main/java/com/codeforall/online/simplegraphics/pictures/Color.java rename to src/main/java/com/codeforall/simplegraphics/pictures/Color.java index f5eb330..0d8b00b 100755 --- a/src/main/java/com/codeforall/online/simplegraphics/pictures/Color.java +++ b/src/main/java/com/codeforall/simplegraphics/pictures/Color.java @@ -1,7 +1,27 @@ -package com.codeforall.online.simplegraphics.pictures; +package com.codeforall.simplegraphics.pictures; +/** + * A simple representation of an RGB color for pictures. + * This class encapsulates the red, green, and blue components of a color, + * each represented by an integer value between 0 and 255. + */ public class Color { + // Color constants + public static final Color RED = new Color(255, 0, 0); + public static final Color GREEN = new Color(0, 255, 0); + public static final Color BLUE = new Color(0, 0, 255); + public static final Color WHITE = new Color(255, 255, 255); + public static final Color LIGHT_GRAY = new Color(192, 192, 192); + public static final Color GRAY = new Color(128, 128, 128); + public static final Color DARK_GRAY = new Color(64, 64, 64); + public static final Color BLACK = new Color(0, 0, 0); + public static final Color CYAN = new Color(0, 255, 255); + public static final Color MAGENTA = new Color(255, 0, 255); + public static final Color YELLOW = new Color(255, 255, 0); + public static final Color PINK = new Color(255, 175, 175); + public static final Color ORANGE = new Color(255, 200, 0); + private int red; private int green; private int blue; @@ -20,49 +40,38 @@ public Color(int red, int green, int blue) { /** * Gets the red value of this color. + * * @return the red value (between 0 and 255) */ - public int getRed() - { - return red; + public int getRed() { + return red; } /** * Gets the green value of this color. + * * @return the green value (between 0 and 255) */ - public int getGreen() - { - return green; + public int getGreen() { + return green; } /** * Gets the blue value of this color. + * * @return the blue value (between 0 and 255) */ - public int getBlue() - { - return blue; + public int getBlue() { + return blue; } - public String toString() - { + /** + * Returns a string representation of the color. + * + * @return a string describing the RGB color + */ + @Override + public String toString() { return "Color[red=" + red + ",green=" + green + ",blue=" + blue + "]"; } - - // Color constants - - public static final Color RED = new Color(255, 0, 0); - public static final Color GREEN = new Color(0, 255, 0); - public static final Color BLUE = new Color(0, 0, 255); - public static final Color WHITE = new Color(255, 255, 255); - public static final Color LIGHT_GRAY = new Color(192, 192, 192); - public static final Color GRAY = new Color(128, 128, 128); - public static final Color DARK_GRAY = new Color(64, 64, 64); - public static final Color BLACK = new Color(0, 0, 0); - public static final Color CYAN = new Color(0, 255, 255); - public static final Color MAGENTA = new Color(255, 0, 255); - public static final Color YELLOW = new Color(255, 255, 0); - public static final Color PINK = new Color(255, 175, 175); - public static final Color ORANGE = new Color(255, 200, 0); } diff --git a/src/main/java/com/codeforall/online/simplegraphics/pictures/Picture.java b/src/main/java/com/codeforall/simplegraphics/pictures/Picture.java similarity index 73% rename from src/main/java/com/codeforall/online/simplegraphics/pictures/Picture.java rename to src/main/java/com/codeforall/simplegraphics/pictures/Picture.java index cf0ca42..10cbb00 100755 --- a/src/main/java/com/codeforall/online/simplegraphics/pictures/Picture.java +++ b/src/main/java/com/codeforall/simplegraphics/pictures/Picture.java @@ -1,9 +1,7 @@ -package com.codeforall.online.simplegraphics.pictures; +package com.codeforall.simplegraphics.pictures; -import com.codeforall.online.simplegraphics.graphics.Movable; -import com.codeforall.online.simplegraphics.graphics.Shape; -import com.codeforall.online.simplegraphics.graphics.Color; -import com.codeforall.online.simplegraphics.graphics.Canvas; +import com.codeforall.simplegraphics.graphics.Movable; +import com.codeforall.simplegraphics.graphics.Shape; import javax.imageio.ImageIO; import javax.swing.*; @@ -14,18 +12,26 @@ /** * A picture from an image file. + * + * Implements: + *
    + *
  • {@link Shape} – for rendering and bounding box info
  • + *
  • {@link Movable} – for translation and scaling
  • + *
*/ public class Picture implements Shape, Movable { + private BufferedImage image; private JLabel label = new JLabel(); private String source; + private double x; private double y; private double xGrow; private double yGrow; /** - * Constructs a picture with no image. + * Constructs a picture object with no image. */ public Picture() { } @@ -39,6 +45,7 @@ public Picture() { public Picture(double width, double height) { image = new BufferedImage((int) Math.round(width), (int) Math.round(height), BufferedImage.TYPE_INT_RGB); + label.setIcon(new ImageIcon(image)); label.setText(""); } @@ -53,23 +60,46 @@ public Picture(double width, double height) { public Picture(double x, double y, String source) { this.x = x; this.y = y; + load(source); } + /** + * Constructs a picture from a 2D array of grayscale values. + * Each element in the array represents a pixel's grayscale intensity, where + * 0 is black, 255 is white, and values in between are shades of gray. + * The resulting image is built pixel by pixel using these values. + * + * @param grayLevels a 2D array representing grayscale values for the image; + * rows correspond to image height and columns to width + */ public Picture(int[][] grayLevels) { image = new BufferedImage(grayLevels[0].length, grayLevels.length, BufferedImage.TYPE_INT_RGB); - for (int i = 0; i < image.getWidth(); i++) + + for (int i = 0; i < image.getWidth(); i++) { + for (int j = 0; j < image.getHeight(); j++) { int gray = grayLevels[j][i]; - if (gray < 0) gray = 0; - if (gray > 255) gray = 255; + + if (gray < 0) { + gray = 0; + } + + if (gray > 255) { + gray = 255; + } + int rgb = gray * (65536 + 256 + 1); + image.setRGB(i, j, rgb); } + } + label.setIcon(new ImageIcon(image)); label.setText(""); } + /** * Loads a new image from a given file or URL. * @@ -81,7 +111,7 @@ public void load(String source) { this.source = source; // Load from the web - if (source.startsWith("http://")) { + if (source.startsWith("http://") || source.startsWith("https://")) { image = ImageIO.read(new URL(source).openStream()); @@ -89,8 +119,10 @@ public void load(String source) { // Attempt to load from the class path (as in JAR file..) URL url = getClass().getResource(source.startsWith("/") ? source : "/" + source); + if (url != null) { image = ImageIO.read(url.openStream()); + } else { // Load from file @@ -100,12 +132,14 @@ public void load(String source) { label.setIcon(new ImageIcon(image)); label.setText(""); + } catch (Exception ex) { image = null; label.setIcon(null); ex.printStackTrace(); } - Canvas.getInstance().repaint(); + + com.codeforall.simplegraphics.graphics.Canvas.getInstance().repaint(); } /** @@ -113,6 +147,7 @@ public void load(String source) { * * @return the leftmost x-position */ + @Override public int getX() { return (int) Math.round(x - xGrow); } @@ -122,6 +157,7 @@ public int getX() { * * @return the topmost y-position */ + @Override public int getY() { return (int) Math.round(y - yGrow); } @@ -147,6 +183,7 @@ public int getMaxY() { /** * Gets the width of this picture. */ + @Override public int getWidth() { return (int) Math.round( (image == null ? 0 : image.getWidth()) + 2 * xGrow); @@ -155,6 +192,7 @@ public int getWidth() { /** * Gets the height of this picture. */ + @Override public int getHeight() { return (int) Math.round( (image == null ? 0 : image.getHeight()) + 2 * yGrow); @@ -168,24 +206,38 @@ public int getHeight() { public int pixels() { if (image == null) { return 0; + } else { return image.getWidth() * image.getHeight(); } } public int[][] getGrayLevels() { - if (image == null) return new int[0][0]; + + if (image == null) { + return new int[0][0]; + } + int[][] grayLevels = new int[getHeight()][getWidth()]; - for (int i = 0; i < grayLevels.length; i++) + for (int i = 0; i < grayLevels.length; i++) { + for (int j = 0; j < grayLevels[i].length; j++) { int rgb = image.getRGB(j, i); + // Use NTSC/PAL algorithm to convert RGB to gray level grayLevels[i][j] = (int) (0.2989 * ((rgb >> 16) & 0xFF) + 0.5866 * ((rgb >> 8) & 0xFF) + 0.1144 * (rgb & 0xFF)); } + } return grayLevels; } + /** + * Returns a string representation of the image. + * + * @return a string describing the image's coordinates, size and source + */ + @Override public String toString() { return "Picture[x=" + getX() + ",y=" + getY() + ",width=" + getWidth() + ",height=" + getHeight() + ",source=" + source + "]"; } @@ -196,9 +248,11 @@ public String toString() { * @param i the pixel index * @return the color at pixel i */ - public Color getColorAt(int i) { + public com.codeforall.simplegraphics.graphics.Color getColorAt(int i) { + if (image == null || i < 0 || i >= pixels()) { throw new IndexOutOfBoundsException("" + i); + } else { return getColorAt(i % image.getWidth(), i / image.getWidth()); } @@ -210,9 +264,11 @@ public Color getColorAt(int i) { * @param i the pixel index * @param color the new color for the pixel */ - public void setColorAt(int i, Color color) { + public void setColorAt(int i, com.codeforall.simplegraphics.graphics.Color color) { + if (image == null || i < 0 || i >= pixels()) { throw new IndexOutOfBoundsException("" + i); + } else { setColorAt(i % image.getWidth(), i / image.getWidth(), color); } @@ -225,12 +281,14 @@ public void setColorAt(int i, Color color) { * @param y the y-coordinate (row) of the pixel * @return the color of the pixel */ - public Color getColorAt(int x, int y) { + public com.codeforall.simplegraphics.graphics.Color getColorAt(int x, int y) { + if (image == null || x < 0 || x >= image.getWidth() || y < 0 || y >= image.getHeight()) { throw new IndexOutOfBoundsException("(" + x + "," + y + ")"); + } else { int rgb = image.getRGB(x, y) & 0xFFFFFF; - return new Color(rgb / 65536, (rgb / 256) % 256, rgb % 256); + return new com.codeforall.simplegraphics.graphics.Color(rgb / 65536, (rgb / 256) % 256, rgb % 256); } } @@ -241,12 +299,14 @@ public Color getColorAt(int x, int y) { * @param y the y-coordinate (row) of the pixel * @param color the color of the pixel at the given row and column */ - public void setColorAt(int x, int y, Color color) { + public void setColorAt(int x, int y, com.codeforall.simplegraphics.graphics.Color color) { + if (image == null || x < 0 || x >= image.getWidth() || y < 0 || y >= image.getHeight()) { throw new IndexOutOfBoundsException("(" + x + "," + y + ")"); + } else { image.setRGB(x, y, ((int) color.getRed()) * 65536 + ((int) color.getGreen()) * 256 + (int) color.getBlue()); - Canvas.getInstance().repaint(); + com.codeforall.simplegraphics.graphics.Canvas.getInstance().repaint(); } } @@ -256,10 +316,11 @@ public void setColorAt(int x, int y, Color color) { * @param dx the amount by which to move in x-direction * @param dy the amount by which to move in y-direction */ + @Override public void translate(double dx, double dy) { x += dx; y += dy; - Canvas.getInstance().repaint(); + com.codeforall.simplegraphics.graphics.Canvas.getInstance().repaint(); } /** @@ -268,40 +329,48 @@ public void translate(double dx, double dy) { * @param dw the amount by which to resize the width on each side * @param dh the amount by which to resize the height on each side */ + @Override public void grow(double dw, double dh) { xGrow += dw; yGrow += dh; - Canvas.getInstance().repaint(); + com.codeforall.simplegraphics.graphics.Canvas.getInstance().repaint(); } /** * Shows this picture on the canvas. */ + @Override public void draw() { - Canvas.getInstance().show(this); + com.codeforall.simplegraphics.graphics.Canvas.getInstance().show(this); } /** * Deletes this picture from the canvas. */ + @Override public void delete() { - Canvas.getInstance().hide(this); + com.codeforall.simplegraphics.graphics.Canvas.getInstance().hide(this); } /** * Draws this shape. * - * @param g2 the graphics context + * @param g2D the graphics context */ - public void paintShape(Graphics2D g2) { + @Override + public void paintShape(Graphics2D g2D) { + if (image != null) { Dimension dim = label.getPreferredSize(); + if (dim.width > 0 && dim.height > 0) { label.setBounds(0, 0, dim.width, dim.height); - g2.translate(getX(), getY()); - g2.scale((image.getWidth() + 2 * xGrow) / dim.width, + g2D.translate(getX(), getY()); + + g2D.scale((image.getWidth() + 2 * xGrow) / dim.width, (image.getHeight() + 2 * yGrow) / dim.height); - label.paint(g2); + + label.paint(g2D); } } }