import java.awt.Color; import java.awt.Canvas; import java.awt.Graphics; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.MouseEvent; import java.io.File; import java.awt.Image; import javax.swing.ImageIcon; import java.awt.Cursor; import java.awt.Robot; import java.awt.AWTException; import java.awt.image.BufferedImage; import java.awt.print.Printable; import java.awt.print.PageFormat; import java.awt.print.PrinterException; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.AWTException; import java.awt.Font; import java.awt.image.PixelGrabber; import java.awt.image.MemoryImageSource; import java.awt.geom.CubicCurve2D; import java.awt.geom.CubicCurve2D.Float; import java.awt.geom.Point2D; import java.awt.event.FocusListener; import java.awt.event.FocusEvent; import java.awt.geom.AffineTransform; public class DrawingCanvas extends Canvas implements MouseListener, MouseMotionListener, Printable, FocusListener { public static final int FILL = 1, NORMAL = 2, OUTLINE = 3, RECT = 4, OVAL = 5, LINE = 6; public static BufferedImage selectImage; public static int extraOperations, lineWidth, radius, amtLines; private Color drawColor, oppositeColor; private BufferedImage printImage, resizeImage; private CubicCurve2D c; private Point2D p1, p2, p3, p4; private boolean polyStart, arcStart, curveMade, curveMade2, save, dragSave; private int mouseX, mouseY, prevX, prevY, originX, originY, width, height; private int[] pixels; /** Creates a default DrawingCanvas. **/ public DrawingCanvas() { // save is set to true unless the focus is lost save = true; // sets the default linewidth and the spray radius lineWidth = 1; radius = 5; amtLines = 10; // adds listeners and sets settings setSize(400,400); setBackground(Color.WHITE); this.addMouseListener(this); this.addMouseMotionListener(this); this.addFocusListener(this); } /** * This methods adjusts the screen size of the user by taking a snapshot of * the canvas and seeing if it shifts up or down and sets the pixels * accordingly. **/ public void checkScreenSize() { saveFromResize(); pixels = new int[getWidth()*getHeight()]; PixelGrabber pg = new PixelGrabber(resizeImage, 0, 0, getWidth(), getHeight(), pixels, 0, getWidth()); try { pg.grabPixels(); } catch (InterruptedException ie) {} if(pixels[0] != (Color.WHITE).getRGB()) ControlClass.extraY = 78; else ControlClass.extraY = 71; } /** Saves an image of the current screen so if the canvas resizes the image doesnt get deleted. **/ public void saveFromResize() { try{ resizeImage = new Robot().createScreenCapture( new Rectangle(ControlClass.xCoord,ControlClass.yCoord,getWidth(),getHeight())); }catch(AWTException awte){} } /** Draws the image back to the screen after the canvas is resized **/ public void pasteFromResize() { Graphics g = getBufferStrategy().getDrawGraphics(); g.drawImage(resizeImage,0,0,null); repaint(); } /** Fills anything of the same color the first pixel selected. **/ public void fillOperation(MouseEvent e) { // saves the image and then creates a pixel array saveImageForPrinting(); pixels = new int[getWidth()*getHeight()]; // grabs all the pixels from the image PixelGrabber pg = new PixelGrabber(printImage, 0, 0, getWidth(), getHeight(), pixels, 0, getWidth()); try { pg.grabPixels(); } catch (InterruptedException ie) {} // calls the start fill method, rgb is the color clicked on int rgb = pixels[e.getY()*getWidth()+e.getX()]; startFill(e.getX(),e.getY(),rgb); // creates an image from the pixel array and draws it back to the screen Image img = createImage(new MemoryImageSource(getWidth(), getHeight(), pixels, 0, getWidth())); Graphics g = getBufferStrategy().getDrawGraphics(); g.drawImage(img,0,0,null); repaint(); saveFromResize(); } /** Changes the color of the pixel at the x and y coordinate. **/ private void changePixel(int x, int y, int rgb) { pixels[y*getWidth()+x] = rgb; } /** Gets the pixel at the x and y point **/ private int getPixel(int x, int y) { return pixels[y*getWidth()+x]; } /** Helper method for fillOperation. This method does the actually filling. **/ public void startFill(int x, int y, int original) { int i = y*getWidth()+x; if(pixels[i] != original) return; // sets the pixel quete to the whole canvas int pixelQueue[] = new int[getWidth() * getHeight()]; int pixelQueueSize = 0; // sets the first pixel pixelQueue[0] = (y << 16) + x; pixelQueueSize = 1; changePixel(x,y,original); // loop to check and does a flood fill to the original color while (pixelQueueSize > 0) { x = pixelQueue[0] & 0xffff; y = (pixelQueue[0] >> 16) & 0xffff; pixelQueueSize--; pixelQueue[0] = pixelQueue[pixelQueueSize]; if (x > 0) { if (getPixel(x-1, y) == original) { changePixel(x-1, y, drawColor.getRGB()); pixelQueue[pixelQueueSize] = (y << 16) + x-1; pixelQueueSize++; } } if (y > 0) { if (getPixel(x, y-1) == original) { changePixel(x, y-1, drawColor.getRGB()); pixelQueue[pixelQueueSize] = ((y-1) << 16) + x; pixelQueueSize++; } } if (x < getWidth()-1) { if (getPixel(x+1, y) == original) { changePixel(x+1, y, drawColor.getRGB()); pixelQueue[pixelQueueSize] = (y << 16) + x+1; pixelQueueSize++; } } if (y < getHeight()-1) { if (getPixel(x, y+1) == original) { changePixel(x, y+1, drawColor.getRGB()); pixelQueue[pixelQueueSize] = ((y+1) << 16) + x; pixelQueueSize++; } } } } /** Helper method for the rotation. Sets the amount of rotation 90 degrees. **/ private AffineTransform setRotation() { AffineTransform atright = AffineTransform.getRotateInstance(Math.PI / 2, getWidth() / 2, getHeight() / 2); return atright; } /** This method actually rotates the image 90 degrees. **/ public void rotateOperation() { // saves the image and then clears it and draws it rotated 90 degrees. Graphics g = getBufferStrategy().getDrawGraphics(); Graphics2D g2 = (Graphics2D) g; saveFromResize(); clearImage(); g2.drawImage(resizeImage, setRotation(), this); repaint(); } /** Saves the image so that it can be printed. **/ public void saveImageForPrinting() { // saves the image of the screen try{ printImage = new Robot().createScreenCapture( new Rectangle(ControlClass.xCoord,ControlClass.yCoord,getWidth(),getHeight())); }catch(AWTException awte){} } /** This is a helper method for print. Draws the image to be printed. **/ public void drawImage(Graphics2D g2D) { // draws the print image out on paper g2D.drawImage(printImage,0,0,null); } /** Printing operation, it prints the image saved. **/ public int print(Graphics g, PageFormat pf, int pIndex) throws PrinterException { if (pIndex > 0) return Printable.NO_SUCH_PAGE; Graphics2D g2D = (Graphics2D)g; drawImage(g2D); return Printable.PAGE_EXISTS; } /** Updates the screen and flips the buffers around. **/ public void update(Graphics g) { getBufferStrategy().show(); } /** Paints the image onto the screen. **/ public void paint(Graphics g) { try{update(g);}catch(NullPointerException e){} } /** Opens a selected image and draws it onto the screen. **/ public void openOperation(String path) { // creates an image and draws it to the screen Graphics g = getBufferStrategy().getDrawGraphics(); ImageIcon ic = new ImageIcon(path); g.drawImage((Image)ic.getImage(),0,0,null); } /** Selects the image from the top left corner to the bottom right corner. **/ public void selectOperation(MouseEvent e) { if(mouseHasMoved(e)) { // this checks if you select off screen, if your off screen then it will // set the boundaries to the edge of the drawing canvas int tOriginX = ControlClass.xCoord+e.getX(); int tOriginY = ControlClass.yCoord+e.getY(); if(tOriginX > getWidth()+ControlClass.xCoord) tOriginX = getWidth()+ControlClass.xCoord; if(tOriginX < ControlClass.xCoord) tOriginX = ControlClass.xCoord; if(tOriginY > getHeight()+ControlClass.yCoord) tOriginY = getHeight()+ControlClass.yCoord; if(tOriginY < ControlClass.yCoord) tOriginY = ControlClass.yCoord; // calculates the width and height of the area width = tOriginX-(ControlClass.xCoord+originX); height = tOriginY-(ControlClass.yCoord+originY); if(width < 0 && height < 0) { originX+=width; originY+=height; } else if(width < 0 && height > 0) originX+=width; else if(width > 0 && height < 0) originY+=height; width = Math.abs(width); height = Math.abs(height); } } /** Copies the selected image **/ public void copyOperation() { // copies the boundaries set by the mouse try{ DrawingCanvas.selectImage = new Robot().createScreenCapture( new Rectangle(ControlClass.xCoord+originX,ControlClass.yCoord+originY, width,height)); }catch(AWTException awte){} } /** Copies the selected image and deletes the selected portion **/ public void cutOperation() { // copies the image and then draws a rectangle over the selected area copyOperation(); Graphics g = getBufferStrategy().getDrawGraphics(); g.setColor(oppositeColor); g.fillRect(originX,originY,width,height); width = height = 0; repaint(); } /** Draws the image with regards to the mouse location. **/ public void pasteOperation() { // draws the image of the selected image onto the screen Graphics g = getBufferStrategy().getDrawGraphics(); g.drawImage(DrawingCanvas.selectImage,originX,originY,null); repaint(); } /** Draws random lines of random colors on the screen. **/ public void randomDraw() { RandomPoint rPt = new RandomPoint(getWidth(),getHeight()); Graphics g = getBufferStrategy().getDrawGraphics(); int i=0; while(i< amtLines) { g.setColor(rPt.getColor()); g.drawLine((int)rPt.getX(),(int)rPt.getY(),rPt.nextX(),rPt.nextY()); i++; } repaint(); } /** Opens up a text dialog in the selected area. **/ public void textOperation(MouseEvent e) { // opens up a text dialog setCursor(new Cursor(Cursor.TEXT_CURSOR)); TextDialog tDialog = new TextDialog(e.getX(),e.getY()); } /** Prints the text onto the screen **/ public void textOperation2(String txt, int x, int y, Font f) { // draws the text onto the screen Graphics g = getBufferStrategy().getDrawGraphics(); g.setFont(f); g.setColor(drawColor); g.drawString(txt,x,y); g.setFont(new Font("Times New Roman", Font.PLAIN, 12)); repaint(); } /** An eraser that erases when the mouse is dragged. **/ public void eraserOperation(MouseEvent e) { setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); Graphics g = getBufferStrategy().getDrawGraphics(); g.setColor(ColorBox.backGround.getBackground()); if (mouseHasMoved(e)) g.fillRect(e.getX(),e.getY(),15,15); repaint(); } /** Paint brush with different brushes like a square and a circle. **/ public void brushOperation(MouseEvent e) { setCursor(new Cursor(Cursor.HAND_CURSOR)); Graphics g = getBufferStrategy().getDrawGraphics(); g.setColor(drawColor); // depending on which brush is selected it will change the brush to that shape if (mouseHasMoved(e)) if(extraOperations == OVAL) g.fillOval(e.getX(),e.getY(),radius,radius); else if(extraOperations == RECT) g.fillRect(e.getX(),e.getY(),radius,radius); repaint(); } /** Creates a pen when can be operated when mouse is dragged. **/ public void penOperation(MouseEvent e) { setCursor(new Cursor(Cursor.HAND_CURSOR)); Graphics g = getBufferStrategy().getDrawGraphics(); g.setColor(drawColor); // draws lines while your mouse is dragged if (mouseHasMoved(e)) { mouseX = e.getX(); mouseY = e.getY(); g.drawLine(prevX,prevY,mouseX,mouseY); prevX = mouseX; prevY = mouseY; } repaint(); } /** Calls the line operation first and then starts the polygon operation **/ public void prePolyOperation(MouseEvent e) { if(!polyStart) { lineOperation(e); polyStart = true; } polyOperation(e); } /** Starts a polygon shape by drawing many line. **/ public void polyOperation(MouseEvent e) { setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); Graphics g = getBufferStrategy().getDrawGraphics(); g.setColor(drawColor); // draws a line on the screen if(mouseHasMoved(e)) { mouseX = e.getX(); mouseY = e.getY(); g.drawLine(prevX, prevY, mouseX, mouseY); prevX = mouseX; prevY = mouseY; } // sets the polygon operation to false if the line is back at the origin if(isBeginning(e)) polyStart = false; repaint(); } /** Helper method for the polygon to check if the line drawn is back at the origin. **/ public boolean isBeginning(MouseEvent e) { // returns true or false if the range is five away from the beginning return (Math.abs(originX-e.getX()) <= 5 && Math.abs(originY-e.getY()) <= 5); } /** Checks if the polygon operation is deselected and stops it. **/ public void checkPolyOff() { // if the polygon operation is on and the polygon tool is not selected then // finish the line if it wasnt completed and reset the polygon operation if(polyStart && ToolBox.toolSelected != ToolBox.POLYGON) { Graphics g = getBufferStrategy().getDrawGraphics(); g.setColor(drawColor); g.drawLine(prevX,prevY,originX,originY); polyStart = false; } } /** Checks if the curve line tool is deselected. **/ public void checkCurveOff() { // if the tool is deselected then reset variables to default if(ToolBox.toolSelected != ToolBox.CURVELINE) curveMade = curveMade2 = false; } /** Starts the curve line tool. **/ public void curveLineOperation(MouseEvent e) { Graphics g = getBufferStrategy().getDrawGraphics(); g.setColor(drawColor); if(mouseHasMoved(e)) { mouseX = e.getX(); mouseY = e.getY(); Graphics2D g2 = (Graphics2D)g; // if the first and second point are not choosen then draw a straight line if(!curveMade && !curveMade2) { c = new CubicCurve2D.Float(); p1 = new Point2D.Float(); p2 = new Point2D.Float(); p3 = new Point2D.Float(); p4 = new Point2D.Float(); p1.setLocation(originX, originY); p4.setLocation(e.getX(), e.getY()); curveMade = true; g.drawLine(originX,originY,e.getX(),e.getY()); repaint(); } // once one of the curves are made then you select a point else if(curveMade && !curveMade2) { pasteFromResize(); p2.setLocation(e.getX(), e.getY()); p3.setLocation(e.getX(), e.getY()); curveMade2 = true; c.setCurve(p1, p2, p3, p4); g2.draw(c); repaint(); } // once both points are choosen then the curve is drawn onto the screen else if(curveMade2 && curveMade) { pasteFromResize(); p3.setLocation(e.getX(), e.getY()); c.setCurve(p1, p2, p3, p4); g2.draw(c); curveMade = false; curveMade2 = false; } } repaint(); } /** Changes the foreground color to the selected color. **/ public void eyeDropperOperation(MouseEvent e) { // creates a screen shot and takes the pixel color where the mouse is situated try{ Robot robot = new Robot(); ColorBox.foreGround.setBackground(robot.getPixelColor(ControlClass.xCoord+e.getX(),ControlClass.yCoord+e.getY())); }catch(AWTException awt){} } /** Creates a line from two points. **/ public void lineOperation(MouseEvent e) { setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); Graphics g = getBufferStrategy().getDrawGraphics(); g.setColor(drawColor); if (mouseHasMoved(e)) { mouseX = e.getX(); mouseY = e.getY(); g.drawLine(originX, originY, mouseX, mouseY); prevX = mouseX; prevY = mouseY; } pasteFromResize(); g.drawLine(originX, originY, mouseX, mouseY); repaint(); } /** * Draw a rectangle from two given points. Draws a fill operation, a outlined * rectangle or a outlined with fill operation. **/ public void drawRectangle(MouseEvent e) { Graphics g = getBufferStrategy().getDrawGraphics(); g.setColor(drawColor); // gets the mouse coordinate and gets the width and height mouseX = e.getX(); mouseY = e.getY(); int width = mouseX-originX; int height = mouseY-originY; // draws a filled rectangle if(extraOperations == FILL) { if(width > 0 && height > 0) g.fillRect(originX,originY,width,height); else if(width < 0 && height < 0) g.fillRect(originX+width,originY+height,Math.abs(width),Math.abs(height)); else if(width < 0 && height > 0) g.fillRect(originX+width,originY,Math.abs(width),height); else if(width > 0 && height < 0) g.fillRect(originX,originY+height,width,Math.abs(height)); } // draws a normal rectangle else if(extraOperations == NORMAL) { if(width > 0 && height > 0) for(int i=0;i 0) for(int i=0;i 0 && height < 0) for(int i=0;i 0 && height > 0) { g.fillRect(originX,originY,width,height); g.setColor(oppositeColor); g.fillRect(originX+lineWidth,originY+lineWidth,width-(lineWidth*2),height-(lineWidth*2)); } else if(width < 0 && height < 0) { g.fillRect(originX+width,originY+height,Math.abs(width),Math.abs(height)); g.setColor(oppositeColor); g.fillRect(originX+width+lineWidth,originY+height+lineWidth,Math.abs(width)-(lineWidth*2),Math.abs(height)-(lineWidth*2)); } else if(width < 0 && height > 0) { g.fillRect(originX+width,originY,Math.abs(width),height); g.setColor(oppositeColor); g.fillRect(originX+width+lineWidth,originY+lineWidth,Math.abs(width)-(lineWidth*2),height-(lineWidth*2)); } else if(width > 0 && height < 0) { g.fillRect(originX,originY+height,width,Math.abs(height)); g.setColor(oppositeColor); g.fillRect(originX+lineWidth,originY+height+lineWidth,width-(lineWidth*2),Math.abs(height)-(lineWidth*2)); } } } /** Calls the drawRectangle operation. **/ public void rectOperation(MouseEvent e) { setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); if (mouseHasMoved(e)) drawRectangle(e); pasteFromResize(); drawRectangle(e); repaint(); } /** This method draws a rectangle with rounded edges. **/ public void drawRoundRectangle(MouseEvent e) { Graphics g = getBufferStrategy().getDrawGraphics(); g.setColor(drawColor); // gets the mouse coordinate and gets the width and height mouseX = e.getX(); mouseY = e.getY(); int width = mouseX-originX; int height = mouseY-originY; // draws a filled rounded rectangle if(extraOperations == FILL) { if(width > 0 && height > 0) g.fillRoundRect(originX,originY,width,height,25,25); else if(width < 0 && height < 0) g.fillRoundRect(originX+width,originY+height,Math.abs(width),Math.abs(height),25,25); else if(width < 0 && height > 0) g.fillRoundRect(originX+width,originY,Math.abs(width),height,25,25); else if(width > 0 && height < 0) g.fillRoundRect(originX,originY+height,width,Math.abs(height),25,25); } // draws a normal rounded rectangle else if(extraOperations == NORMAL) { if(width > 0 && height > 0) for(int i=0;i 0) for(int i=0;i 0 && height < 0) for(int i=0;i 0 && height > 0) { g.fillRoundRect(originX,originY,width,height,25,25); g.setColor(oppositeColor); g.fillRoundRect(originX+lineWidth,originY+lineWidth,width-(lineWidth*2),height-(lineWidth*2),25,25); } else if(width < 0 && height < 0) { g.fillRoundRect(originX+width,originY+height,Math.abs(width),Math.abs(height),25,25); g.setColor(oppositeColor); g.fillRoundRect(originX+width+lineWidth,originY+height+lineWidth,Math.abs(width)-(lineWidth*2),Math.abs(height)-(lineWidth*2),25,25); } else if(width < 0 && height > 0) { g.fillRoundRect(originX+width,originY,Math.abs(width),height,25,25); g.setColor(oppositeColor); g.fillRoundRect(originX+width+lineWidth,originY+lineWidth,Math.abs(width)-(lineWidth*2),height-(lineWidth*2),25,25); } else if(width > 0 && height < 0) { g.fillRoundRect(originX,originY+height,width,Math.abs(height),25,25); g.setColor(oppositeColor); g.fillRoundRect(originX+lineWidth,originY+height+lineWidth,width-(lineWidth*2),Math.abs(height)-(lineWidth*2),25,25); } } } /** Calls the drawRoundRectangle operation. **/ public void roundOperation(MouseEvent e) { setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); if (mouseHasMoved(e)) drawRoundRectangle(e); pasteFromResize(); drawRoundRectangle(e); repaint(); } /** Draws an oval onto the screen. **/ public void drawOval(MouseEvent e) { Graphics g = getBufferStrategy().getDrawGraphics(); g.setColor(drawColor); // gets the mouse coordinate and gets the width and height mouseX = e.getX(); mouseY = e.getY(); int width = mouseX-originX; int height = mouseY-originY; // draws a filled oval if(extraOperations == FILL) { if(width > 0 && height > 0) g.fillOval(originX,originY,width,height); else if(width < 0 && height < 0) g.fillOval(originX+width,originY+height,Math.abs(width),Math.abs(height)); else if(width < 0 && height > 0) g.fillOval(originX+width,originY,Math.abs(width),height); else if(width > 0 && height < 0) g.fillOval(originX,originY+height,width,Math.abs(height)); } // draws a normal oval else if(extraOperations == NORMAL) { if(width > 0 && height > 0) for(int i=0;i 0) for(int i=0;i 0 && height < 0) for(int i=0;i 0 && height > 0) { g.fillOval(originX,originY,width,height); g.setColor(oppositeColor); g.fillOval(originX+lineWidth,originY+lineWidth,width-(lineWidth*2),height-(lineWidth*2)); } else if(width < 0 && height < 0) { g.fillOval(originX+width,originY+height,Math.abs(width),Math.abs(height)); g.setColor(oppositeColor); g.fillOval(originX+width+lineWidth,originY+height+lineWidth,Math.abs(width)-(lineWidth*2),Math.abs(height)-(lineWidth*2)); } else if(width < 0 && height > 0) { g.fillOval(originX+width,originY,Math.abs(width),height); g.setColor(oppositeColor); g.fillOval(originX+width+lineWidth,originY+lineWidth,Math.abs(width)-(lineWidth*2),height-(lineWidth*2)); } else if(width > 0 && height < 0) { g.fillOval(originX,originY+height,width,Math.abs(height)); g.setColor(oppositeColor); g.fillOval(originX+lineWidth,originY+height+lineWidth,width-(lineWidth*2),Math.abs(height)-(lineWidth*2)); } } } /** Calls the drawOval operation. **/ public void ovalOperation(MouseEvent e) { setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); if (mouseHasMoved(e)) drawOval(e); pasteFromResize(); drawOval(e); repaint(); } /** Drag Brush Operation. You draw a shape around as your brush. **/ public void dragOperation(MouseEvent e) { Graphics g = getBufferStrategy().getDrawGraphics(); g.setColor(drawColor); if (mouseHasMoved(e)) if(extraOperations == LINE) g.drawLine(e.getX(),e.getY(),e.getX()+radius,e.getY()-radius); else if(extraOperations == RECT) g.drawRect(e.getX(),e.getY(),radius,radius); else if(extraOperations == OVAL) g.drawOval(e.getX(),e.getY(),radius,radius); repaint(); } /** Spray brush tool. Draws many tiny dots within a set radius. **/ public void sprayOperation(MouseEvent e) { Graphics g = getBufferStrategy().getDrawGraphics(); g.setColor(drawColor); // sets random points to the origin and draws them onto the screen for(int i=0;i