diff --git a/src/GUI/DrawingArea.java b/src/GUI/DrawingArea.java index 21069490ac09b3a85c3eb35b876440ee928f206a..a6bb2ad9ad79df1b386c4d3aef6decd14a106abb 100644 --- a/src/GUI/DrawingArea.java +++ b/src/GUI/DrawingArea.java @@ -16,9 +16,10 @@ import java.awt.geom.RectangularShape; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; +import java.io.Serializable; import java.rmi.RemoteException; -public class DrawingArea extends JPanel implements MouseMotionListener, MouseListener { +public class DrawingArea extends JPanel implements MouseMotionListener, MouseListener, Serializable { @@ -42,12 +43,14 @@ public class DrawingArea extends JPanel implements MouseMotionListener, MouseLis private Color shapeColor;// = new Color(0, 0, 0); private Mode currentMode;// = Mode.FREEHAND; + /// Create a empty canvas /// + private BufferedImage image;// = new BufferedImage(AREA_WIDTH, AREA_HEIGHT, BufferedImage.TYPE_INT_ARGB); /// Drawing tool - private Graphics2D g2;// = (Graphics2D) image.getGraphics(); + private Graphics2D g2;// = (Graphics2D) image.getGraphics(); public DrawingArea(Client client) { this.client = client; @@ -64,7 +67,6 @@ public class DrawingArea extends JPanel implements MouseMotionListener, MouseLis addMouseMotionListener(this); } - public Shape getDrawing() { return drawing; } @@ -73,6 +75,16 @@ public class DrawingArea extends JPanel implements MouseMotionListener, MouseLis this.drawing = drawing; } + public Graphics2D getG2() { return g2; } + + + public void setG2(Graphics2D g2) { this.g2 = g2; } + + + public BufferedImage getImage() { return image; } + + public void setImage(BufferedImage image) { this.image = image; } + @Override public Dimension getPreferredSize() @@ -108,12 +120,7 @@ public class DrawingArea extends JPanel implements MouseMotionListener, MouseLis Color borderColor = currentMode != Mode.ERASE ? shapeColor : Color.WHITE; g2.setColor(borderColor); g2.draw(drawing); - IDrawingController drawingController = client.getDrawingController(); - try { - drawingController.broadcastDrawing(client.getUserName(), drawing); - } catch (RemoteException ex) { - ex.printStackTrace(); - } + } } @@ -269,22 +276,23 @@ public class DrawingArea extends JPanel implements MouseMotionListener, MouseLis @Override public void mouseReleased(MouseEvent e) { + IDrawingController drawingController = client.getDrawingController(); switch (currentMode) { case OVAL: case RECTANGLE: case CIRCLE: -/// Abort drawing if 2D has no width or height /// + /// Abort drawing if 2D has no width or height /// if (((RectangularShape) drawing).getWidth() == 0 || ((RectangularShape) drawing).getHeight() == 0) { break; } case FREEHAND: case LINE: -// Graphics2D g2 = (Graphics2D) image.getGraphics(); + // Graphics2D g2 = (Graphics2D) image.getGraphics(); g2.setColor(shapeColor); -/// Uncomment the line below to fill the shapes with color /// -// g2.fill(drawing); + /// Uncomment the line below to fill the shapes with color /// + // g2.fill(drawing); g2.draw(drawing); } @@ -292,9 +300,15 @@ public class DrawingArea extends JPanel implements MouseMotionListener, MouseLis g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(shapeColor); -/// This repaint is needed if we want to fill the drawing shape with color + /// This repaint is needed if we want to fill the drawing shape with color repaint(); + try { + drawingController.broadcastDrawing(client.getUserName(), drawing, currentMode.toString(), shapeColor); + } catch (RemoteException ex) { + ex.printStackTrace(); + } + drawing = null; } @@ -310,8 +324,9 @@ public class DrawingArea extends JPanel implements MouseMotionListener, MouseLis @Override public void mouseDragged(MouseEvent e) { - currentPoint = e.getPoint(); + IDrawingController drawingController = client.getDrawingController(); + currentPoint = e.getPoint(); int x = Math.min(startPoint.x, e.getX()); int y = Math.min(startPoint.y, e.getY()); int width = Math.abs(startPoint.x - e.getX()); @@ -365,6 +380,11 @@ public class DrawingArea extends JPanel implements MouseMotionListener, MouseLis } repaint(); + try { + drawingController.broadcastDraggingDrawing(client.getUserName(), drawing, currentMode.toString(), shapeColor); + } catch (RemoteException ex) { + ex.printStackTrace(); + } } @Override diff --git a/src/GUI/PaintGUI.java b/src/GUI/PaintGUI.java index 40a63589b23c67847eade7ad28d6ae306516d3fd..fd2a2e32da3b742db1af1aff285bddf04c241cf5 100644 --- a/src/GUI/PaintGUI.java +++ b/src/GUI/PaintGUI.java @@ -217,16 +217,16 @@ public class PaintGUI extends JPanel { - public void showGUI() { - frame = new JFrame("Shared Whiteboard System"); - JFrame.setDefaultLookAndFeelDecorated(true); - frame.setContentPane(global); - - frame.setSize(800, 600); - frame.setLocationRelativeTo( null ); - frame.setResizable(false); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setVisible(true); - } +// public void showGUI() { +// frame = new JFrame("Shared Whiteboard System"); +// JFrame.setDefaultLookAndFeelDecorated(true); +// frame.setContentPane(global); +// +// frame.setSize(800, 600); +// frame.setLocationRelativeTo( null ); +// frame.setResizable(false); +// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); +// frame.setVisible(true); +// } } \ No newline at end of file diff --git a/src/client/DrawingUpdate.java b/src/client/DrawingUpdate.java index 4b41c0285681b1674f9b35cc61336ca6d4451426..abc1fa4b035108e5e32989a3fea31bdfe600a6fd 100644 --- a/src/client/DrawingUpdate.java +++ b/src/client/DrawingUpdate.java @@ -18,12 +18,45 @@ public class DrawingUpdate extends UnicastRemoteObject implements IDrawingUpdate } @Override - public boolean notifyDrawing(String fromClient, Shape drawing) throws RemoteException { - client.getApplicationMain().getPaintGUI().getDrawingArea().setDrawing(drawing); + public boolean notifyDrawing(String fromClient, Shape drawing, String mode, Color color) throws RemoteException { + Graphics2D g2 = client.getApplicationMain().getPaintGUI().getDrawingArea().getG2(); + switch (mode) { + case "OVAL": + case "RECTANGLE": + case "CIRCLE": + case "FREEHAND": + case "LINE": + g2.setColor(color); + g2.draw(drawing); + break; + default: + System.out.println("Erased"); + } + g2 = (Graphics2D) client.getApplicationMain().getPaintGUI().getDrawingArea().getImage().getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setColor(color); client.getApplicationMain().getPaintGUI().getDrawingArea().repaint(); -// DrawingArea drawingArea = (DrawingArea) client.getChatScreen().getDrawingPanel().getComponent(1); -// drawingArea.setDrawing(drawing); -// drawingArea.repaint(); - return false; + return true; + } + + public boolean notifyDraggingDrawing(String fromClient, Shape drawing, String mode, Color color) throws RemoteException { + Graphics2D g2 = client.getApplicationMain().getPaintGUI().getDrawingArea().getG2(); + switch (mode) { + case "FREEHAND": + g2.setColor(color); + g2.draw(drawing); + break; + + case "ERASE": + g2.setColor(Color.WHITE); + g2.fill(drawing); + g2.draw(drawing); + break; + + default: + break; + } + client.getApplicationMain().getPaintGUI().getDrawingArea().repaint(); + return true; } } diff --git a/src/remote/IDrawingController.java b/src/remote/IDrawingController.java index 145cc49619dcab3c25de449b706221fff56ecab6..1c39d4e5cf0900d1cd15c0ed9042edc4ed08b836 100644 --- a/src/remote/IDrawingController.java +++ b/src/remote/IDrawingController.java @@ -1,6 +1,7 @@ package remote; import java.awt.*; +import java.awt.image.BufferedImage; import java.rmi.Remote; import java.rmi.RemoteException; @@ -15,7 +16,8 @@ import java.rmi.RemoteException; */ public interface IDrawingController extends Remote { - boolean broadcastDrawing(String fromClient, Shape drawing) throws RemoteException; - + boolean broadcastDrawing(String fromClient, Shape drawing, String mode, Color color) throws RemoteException; + boolean broadcastDraggingDrawing(String fromClient, Shape drawing, String mode, Color color) throws RemoteException; +// BufferedImage getCurrentImage() throws RemoteException; } diff --git a/src/remote/IDrawingUpdate.java b/src/remote/IDrawingUpdate.java index 3df14ff51b7f3bbb41069b15f36ea23627699439..fdfbd616a5f0da92156b1d480f31a9a628edb4b0 100644 --- a/src/remote/IDrawingUpdate.java +++ b/src/remote/IDrawingUpdate.java @@ -6,5 +6,6 @@ import java.rmi.Remote; import java.rmi.RemoteException; public interface IDrawingUpdate extends Remote, Serializable { - boolean notifyDrawing(String fromClient, Shape drawing) throws RemoteException; + boolean notifyDrawing(String fromClient, Shape drawing, String mode, Color color) throws RemoteException; + boolean notifyDraggingDrawing(String fromClient, Shape drawing, String mode, Color color) throws RemoteException; } diff --git a/src/server/DrawingController.java b/src/server/DrawingController.java index 1471e8a38a33c3fc1d496f36ffa306ad0f0a1888..2fb582de348d07447d99c25f52fd8821907836c6 100644 --- a/src/server/DrawingController.java +++ b/src/server/DrawingController.java @@ -3,32 +3,108 @@ package server; import remote.IDrawingController; import remote.IDrawingUpdate; +import javax.imageio.ImageIO; import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.reflect.Array; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; +import java.util.ArrayList; public class DrawingController extends UnicastRemoteObject implements IDrawingController { + private final static int AREA_WIDTH = 600; + private final static int AREA_HEIGHT = 620; + private Server server; + private BufferedImage bufferedImage; +// private ImageCanvas image; + private Graphics2D g2; protected DrawingController(Server server) throws RemoteException { this.server = server; + this.bufferedImage = new BufferedImage(AREA_WIDTH, AREA_HEIGHT, BufferedImage.TYPE_INT_ARGB); + g2 = (Graphics2D) bufferedImage.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } @Override - public boolean broadcastDrawing(String fromClient, Shape drawing) throws RemoteException { + public boolean broadcastDrawing(String fromClient, Shape drawing, String mode, Color color) throws RemoteException { System.out.print("Broadcasting drawing to everyone..."); + // 1. Draw on server + g2.setColor(color); + g2.draw(drawing); + g2 = (Graphics2D) bufferedImage.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setColor(color); + g2.drawImage(bufferedImage, 0,0, null); + + // 2. Broadcast to other clients IDrawingUpdate client; for( User u : server.users ) { - client = u.getIDrawingUpdate(); - client.notifyDrawing(fromClient, drawing); + if (!u.getUserName().equals(fromClient)) { + client = u.getIDrawingUpdate(); + client.notifyDrawing(fromClient, drawing, mode, color); + } } System.out.print("...DONE\n"); return true; } + + public boolean broadcastDraggingDrawing(String fromClient, Shape drawing, String mode, Color color) throws RemoteException { + System.out.print("Broadcasting dragging drawing to everyone..."); + + // 1. Draw on server +// g2.setColor(color); +// g2.draw(drawing); + + // 2. Broadcast to other clients + IDrawingUpdate client; + + for( User u : server.users ) + { + if (!u.getUserName().equals(fromClient)) { + client = u.getIDrawingUpdate(); + client.notifyDraggingDrawing(fromClient, drawing, mode, color); + } + } + + System.out.print("...DONE\n"); + + return true; + } + +// public ImageCanvas getCurrentImage() { +// return image; +// } +} + +class ImageCanvas implements Serializable { + transient ArrayList<BufferedImage> images; + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeInt(images.size()); // how many images are serialized? + for (BufferedImage eachImage : images) { + ImageIO.write(eachImage, "png", out); // png is lossless + } + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + final int imageCount = in.readInt(); + images = new ArrayList<BufferedImage>(imageCount); + for (int i=0; i<imageCount; i++) { + images.add(ImageIO.read(in)); + } + } } \ No newline at end of file