/* This tool allows the user to choose a shape and a color and draw and place each shape using the mouse. The user can also draw curves, straight Lines and set the Backgroud to one of the colors in the popup menu. Shapes are allowed to accumulate on the applet window until the user presses the clear button (which clears the applet of all shapes) */ import java.awt.*; import java.awt.event.*; import java.applet.*; public class PaintTool extends Applet { // The main applet class simply sets up the applet. public void init() { // Background color of applet: gray. setBackground(Color.lightGray); // Layout manager for applet. setLayout(new BorderLayout(3,3)); // The drawing area. PaintToolCanvas canvas = new PaintToolCanvas(); add(canvas,BorderLayout.CENTER); // Buttons Panel (Set Backgound, Clear) Panel buttonBar = new Panel(); buttonBar.setBackground(Color.black); add(buttonBar, BorderLayout.SOUTH); // Pop-Up Menus Panel (Color, Shape) Panel choiceBar = new Panel(); choiceBar.setBackground(Color.black); add(choiceBar, BorderLayout.NORTH); // Set Backgound Button. Button fill = new Button("Set Background"); fill.addActionListener(canvas); fill.setBackground(Color.lightGray); buttonBar.add(fill); // Clear button. Button clear = new Button("Clear"); clear.addActionListener(canvas); clear.setBackground(Color.lightGray); buttonBar.add(clear); // The pop-up menu of colors. Choice choice = new Choice(); choice.addItem("Black"); choice.addItem("Red"); choice.addItem("Green"); choice.addItem("Blue"); choice.addItem("Cyan"); choice.addItem("Magenta"); choice.addItem("Yellow"); choice.addItem("White"); choice.setBackground(Color.white); choiceBar.add(choice); // The pop-up menu of shapes. Choice choice2 = new Choice(); choice2.addItem("Curve"); choice2.addItem("Straight Line"); choice2.addItem("Rectangle"); choice2.addItem("Oval"); choice2.addItem("RoundRect"); choice2.addItem("Filled Rectangle"); choice2.addItem("Filled Oval"); choice2.addItem("Filled RoundRect"); choice2.setBackground(Color.white); choiceBar.add(choice2); // Canvas access the Color and Shape Menus. canvas.colorChoice = choice; canvas.figureChoice = choice2; } // end init() public Insets getInsets() { // sets the border of the edges of the applet. return new Insets(3,3,3,3); } } // end class PaintTool class PaintToolCanvas extends Canvas implements MouseListener, MouseMotionListener, ActionListener { private final static int BLACK = 0, RED = 1, GREEN = 2, BLUE = 3, CYAN = 4, MAGENTA = 5, YELLOW = 6, WHITE = 7; // colorChoice contains the color created by the applet. Choice colorChoice; private final static int CURVE = 0, LINE = 1, RECT = 2, OVAL = 3, ROUNDRECT = 4, FILLED_RECT = 5, FILLED_OVAL = 6, FILLED_ROUNDRECT = 7; // figureChoice contains the shape created by the applet. Choice figureChoice; // The off-screen canvas (created in setupOSC()). Image OSC; // The off-screen canvas (created in setupOSC()). int widthOfOSC, heightOfOSC; // Current widht and height of OSC. These // are checked against the size of the applet, // to detect any change in the applet's size. // If the size has changed, a new OSC is created. // The picture in the off-screen canvas is lost // when that happens. // The previous location of the mouse. private int prevX, prevY; // The starting position of the mouse. private int startX, startY; // This is set to true when the user is drawing. private boolean dragging; // Shape Chosen. private int figure; // A graphics context for the applet. private Graphics graphicsForDrawing; // A graphics context for the off-screen canvas. private Graphics offscreenGraphics; PaintToolCanvas() { // Setting the MouseListener, MouseMotionListenet and the backgound. addMouseListener(this); addMouseMotionListener(this); setBackground(Color.white); } private void setupOSC() { // This method is responsible for creating the off-screen canvas. // It should be called before using the OSC. It will make a new OSC if // the size of the applet changes. if (OSC == null || widthOfOSC != getSize().width || heightOfOSC != getSize().height) { // Create the OSC, or make a new one if applet size has changed. OSC = null; // (If OSC already exists, this frees up the memory.) OSC = createImage(getSize().width, getSize().height); widthOfOSC = getSize().width; heightOfOSC = getSize().height; Graphics OSG = OSC.getGraphics(); // Graphics context for drawing to OSC. OSG.setColor(getBackground()); OSG.fillRect(0, 0, widthOfOSC, heightOfOSC); } } private Graphics getOSG() { // Return a graphics context for drawing to the off-screen canvas. // A new canvas is created if necessary. Note that the graphics // context should not be kept for any length of time, in case the // size of the canvas changes. setupOSC(); return OSC.getGraphics(); } private void clearOSC() { // Fill the off-screen canvas with the background color. Graphics OSG = OSC.getGraphics(); OSG.setColor(getBackground()); OSG.fillRect(0, 0, widthOfOSC, heightOfOSC); OSG.dispose(); } public void update(Graphics g) { // Redefine update so it doesn't clear the canvas before calling paint(). paint(g); } public void paint(Graphics g) { // Just copy the off-screen canvas to the screen. setupOSC(); g.drawImage(OSC, 0, 0, this); } public void actionPerformed(ActionEvent evt) { // Respond when the user clicks on a button. String command = evt.getActionCommand(); if (command.equals("Clear")) { // Clear the off-screen canvas to current background color, // then call repaint() so the screen is also cleared. clearOSC(); repaint(); } else if (command.equals("Set Background")) { // Set background color, then clear. setBackground(getCurrentColor()); clearOSC(); repaint(); } } private Color getCurrentColor() { // Check the colorChoice menu to find the currently // selected color, and return the appropriate color // object. int currentColor = colorChoice.getSelectedIndex(); switch (currentColor) { case BLACK: return Color.black; case RED: return Color.red; case GREEN: return Color.green; case BLUE: return Color.blue; case CYAN: return Color.cyan; case MAGENTA: return Color.magenta; case YELLOW: return Color.yellow; default: return Color.white; } } private void putFigure(Graphics g, int kind, int x1, int y1, int x2, int y2, boolean outlineOnly) { // Drawing shapes and lines. if (kind == LINE) g.drawLine(x1, y1, x2, y2); else { int x, y, w, h; // Top-left corner, width, and height. if (x2 >= x1) { // x1 is left edge x = x1; w = x2 - x1; } else { // x2 is left edge x = x2; w = x1 - x2; } if (y2 >= y1) { // y1 is top edge y = y1; h = y2 - y1; } else { // y2 is top edge. y = y2; h = y1 - y2; } switch (kind) { // Draw the appropriate figure. case RECT: g.drawRect(x, y, w, h); break; case OVAL: g.drawOval(x, y, w, h); break; case ROUNDRECT: g.drawRoundRect(x, y, w, h, 20, 20); break; case FILLED_RECT: if (outlineOnly) g.drawRect(x, y, w, h); else g.fillRect(x, y, w, h); break; case FILLED_OVAL: if (outlineOnly) g.drawOval(x, y, w, h); else g.fillOval(x, y, w, h); break; case FILLED_ROUNDRECT: if (outlineOnly) g.drawRoundRect(x, y, w, h, 20, 20); else g.fillRoundRect(x, y, w, h, 20, 20); break; } } } public void mousePressed(MouseEvent evt) { // This is called when the user presses the mouse on the canvas. if (dragging == true) // Ignore mouse presses that occur return; // when user is already drawing a curve. // (This can happen if the user presses // two mouse buttons at the same time.) prevX = startX = evt.getX(); // Save mouse coordinates. prevY = startY = evt.getY(); figure = figureChoice.getSelectedIndex(); //Type of figure beging drawn. graphicsForDrawing = getGraphics(); // For drawing on the screen. graphicsForDrawing.setColor(getCurrentColor()); offscreenGraphics = getOSG(); // For drawing on the canvas. offscreenGraphics.setColor(getCurrentColor()); if (figure != CURVE) { // Shapes are drawn in XOR mode so they can be erased by redrawing. // Curves are drawn directly to both the screen and to the OSC. graphicsForDrawing.setXORMode(getBackground()); putFigure(graphicsForDrawing, figure, startX, startY, startX, startY, true); } dragging = true; // Start drawing. } // end mousePressed() public void mouseReleased(MouseEvent evt) { // Called whenever the user releases the mouse button. if (dragging == false) return; // Nothing to do because the user isn't drawing. dragging = false; if (figure != CURVE) { // Erase the last XOR mode shape by redrawing it in XOR mode. // Then, if the mouse is not back where it started from, // Draw the final shape on both the screen and the off-screen // canvas in paintMode. putFigure(graphicsForDrawing, figure, startX, startY, prevX, prevY, true); if (startX != prevX || startY != prevY) { graphicsForDrawing.setPaintMode(); putFigure(graphicsForDrawing, figure, startX, startY, prevX, prevY, false); putFigure(offscreenGraphics, figure, startX, startY, prevX, prevY, false); } } graphicsForDrawing.dispose(); offscreenGraphics.dispose(); graphicsForDrawing = null; offscreenGraphics = null; } public void mouseDragged(MouseEvent evt) { // Called whenever the user moves the mouse while a mouse button // is down. if (dragging == false) return; // Nothing to do because the user isn't drawing. int x = evt.getX(); // x-coordinate of mouse. int y = evt.getY(); // y=coordinate of mouse. if (figure == CURVE) { // Draw the line on the applet and on the off-screen canvas. putFigure(graphicsForDrawing, LINE, prevX, prevY, x, y, false); putFigure(offscreenGraphics, LINE, prevX, prevY, x, y, false); } else { // Erase previous figure and draw a new one using the new mouse position. putFigure(graphicsForDrawing, figure, startX, startY, prevX, prevY, true); putFigure(graphicsForDrawing, figure, startX, startY, x, y, true); } prevX = x; // Save coords for the next call to mouseDragged or mouseReleased. prevY = y; } // end mouseDragged. public void mouseEntered(MouseEvent evt) { } // Some empty routines. public void mouseExited(MouseEvent evt) { } // (Required by the MouseListener public void mouseClicked(MouseEvent evt) { } // and MouseMotionListener public void mouseMoved(MouseEvent evt) { } // interfaces). } // end class PaintToolCanvas