📄 whiteboard.java
字号:
/* * Title: Whiteboard * Applet * * Description: * Multiuser paint application, with tools for lines, boxes, ovals, pencil, text, * set line width, set color, and set font. Accepts user input, as well as * command packets via TCP connection. Intended for use as a "shared canvas", * in which multiple users can draw simultaneously on separate workstations, * and a server broadcasts their operations to all other users. Not implemented * yet: text protocol. * * */import java.awt.*;import java.applet.*;import java.net.*;import java.io.*;class TestData{ public final static boolean TESTMODE = true; public final static boolean LOCALMODE = false; public final static String testString = "04" // tool id (3=lineTool, 4=boxTool, 5=ovalTool) + "04" // line width + "255" // red + "000" // green + "000" // blue + "0100" // startX + "0050" // startY + "0200" // endX + "0030" // endY + "\n";}/** * Configuration Data */class ConfigData{ // Initial frame dimensions (these are overridden by the browser) static final int FRAME_INITIAL_WIDTH = 600; static final int FRAME_INITIAL_HEIGHT = 200; // Default paint chat server static final String DEFAULT_HOST_NAME = "211.71.73.191"; static final int DEFAULT_PORT_NUMBER = 6002;}/** * Helper methods */class Helper{ /** * Construct a rectangle with positive width and height from the pair of * opposing corner points. */ public static void makeRect(int x1, int y1, int x2, int y2, Rectangle r) { int xa = Math.min(x1, x2); int ya = Math.min(y1, y2); int xb = Math.max(x1, x2); int yb = Math.max(y1, y2); r.x = xa; r.y = ya; r.width = xb - xa + 1; r.height = yb - ya + 1; } /** * Pad the string with the specified leading character, until the string is * the specified length. */ public static String prePad(String s, char c, int len) { int i; StringBuffer sbuf = new StringBuffer(len); for (i = 0; i < (len - s.length()); i++) { sbuf.insert(i, c); } sbuf.insert(i, s); return sbuf.toString(); } /** * Create a string representation of an int value, padded with leading * zeroes; allow negative numbers. */ public static String makeSignedString(int val, int len) { String s = prePad(String.valueOf(Math.abs(val)), '0', len); StringBuffer sb = new StringBuffer(s); if (val < 0) { sb.setCharAt(0, '-'); } return sb.toString(); }}/** * A remote command, either sent to the server, or received from it. */class Command{ public int toolId; public int lineWidth; public Color color; public int startX, startY, endX, endY; /** * Construct a command with the given values. */ public Command(int id, int w, Color c, int sx, int sy, int ex, int ey) { toolId = id; lineWidth = w; color = c; startX = sx; startY = sy; endX = ex; endY = ey; } /** * Parse the command string and construct an equivalent command object. * ***MAKE MORE EFFICIENT*** */ public Command(String s) throws NumberFormatException { toolId = Integer.parseInt(s.substring(0, 2)); lineWidth = Integer.parseInt(s.substring(2, 4)); color = new Color( Integer.parseInt(s.substring(4, 7)), Integer.parseInt(s.substring(7, 10)), Integer.parseInt(s.substring(10, 13))); startX = Integer.parseInt(s.substring(13, 17)); startY = Integer.parseInt(s.substring(17, 21)); endX = Integer.parseInt(s.substring(21, 25)); endY = Integer.parseInt(s.substring(25, 29)); } /** * Create a command string that represents the command according to the * Whiteboard server protocol. ***MAKE MORE EFFICIENT*** */ public String makeCommandString() { String id = Helper.prePad(String.valueOf(toolId), '0', 2); String linew = Helper.prePad(String.valueOf(lineWidth), '0', 2); String red = Helper.prePad(String.valueOf(color.getRed()), '0', 3); String green = Helper.prePad(String.valueOf(color.getGreen()), '0', 3); String blue = Helper.prePad(String.valueOf(color.getBlue()), '0', 3); String sx = Helper.makeSignedString(startX, 4); String sy = Helper.makeSignedString(startY, 4); String ex = Helper.makeSignedString(endX, 4); String ey = Helper.makeSignedString(endY, 4); return id + linew + red + green + blue + sx + sy + ex + ey + '\n'; }}/** * A ToolCanvas is the building block of all Whiteboard tools. * Each tool is a self-contained graphic component in its own right, * which provides voluntary services to other Whiteboard components, * depending on the tool. */abstract class ToolCanvas extends Canvas{ // Define tool dimensions public static final int DEFAULT_WIDTH = 20; public static final int DEFAULT_HEIGHT = 20; public int width; public int height; // Define a reference to a class that assembles the tools Tools tools; // Focus indicates that a tool has been selected boolean focus = false; /** * This superclass constructor should be called by all subclasses. */ public ToolCanvas(Tools t) { width = DEFAULT_WIDTH; height = DEFAULT_HEIGHT; setBackground(Color.white); getToolkit().sync(); tools = t; } /** * Return the name of the tool. */ public abstract String getToolName(); /** * (Re)paint the tool icon when necessary. */ public void paint(Graphics g) { g.setColor(getBackground()); g.fill3DRect(0, 0, width-1, height-1, true); } /** * Override update() to eliminate the clear operation which we don't need */ public void update(Graphics g) { paint(g); } /** * Set the tool to be the currently selected one. */ public void setFocus() { focus = true; System.out.println(getToolName() + " has focus"); repaint(); } /** * Unset focus for a tool. */ public void clearFocus() { focus = false; repaint(); } Dimension dim = new Dimension(); abstract Dimension getDimension(); public Dimension minimumSize() { return getDimension(); } public Dimension preferredSize() { return getDimension(); } /** * Respond to tool selection events. Focus is set, and the current-tool * reference is set. */ public boolean handleEvent(Event e) { if (e.id == Event.MOUSE_DOWN) { ToolPanel toolPanel = (ToolPanel)(getParent()); Tools tools = toolPanel.tools; ToolCanvas tool = tools.getCurTool(); if (tool != null) tool.clearFocus(); toolPanel.tools.setCurTool(this); setFocus(); return true; } return super.handleEvent(e); } /** * A canvas can call this method to process a canvas event. * Assumes double-buffering. */ public void applyTool(Event e, Graphics g, Graphics bg) { return; } /** * Construct a command that encapsulates the tool operation, including the * id of the tool, tool parameters and state, and all tool settings. * * Command format (field_name:no_of_bytes): * <tool_id:2> // the unique id of the tool * <line_width:2> // line width tool setting * <red_value:3> // color selector setting, red value * <green_value:3> // " green value * <blue_value:3> // " blue value * <start_x:4> // if a tool does not have this, 0 * <start_y:4> // " * <end_x:4> // the x location at which to apply the tool * <end_y:4> // the y " * <\n> // delimits the end of the command */ public String makeCommandString(Event e) { // return "00000000000000000000000000000\n"; // 00 is the null tool - do nothing by default return null; } public void applyCommand(Command c, Graphics g, Graphics bg) { System.out.println("This operation not implemented for broadcast"); }}/** * Display a selection of line widths, and allow the user to select one. */class LineWidthTool extends ToolCanvas{ final static String toolName = "LineWidthTool"; final static int toolId = 1; // Define the tool parameters final static int MIN_LINE_WIDTH = 2; final static int MAX_LINE_WIDTH = 10; // Tool state: int lineWidth = MIN_LINE_WIDTH; int lineWidths[]; int lineX[]; /** * Construct the line width selector tool. */ public LineWidthTool(Tools t) { super(t); // // Construct a green rectangle, with vertical lines in it of successively // increasing width (the user selects one of these to choose width). // setBackground(Color.green); lineWidths = new int[MAX_LINE_WIDTH - MIN_LINE_WIDTH + 1]; lineX = new int[MAX_LINE_WIDTH - MIN_LINE_WIDTH + 1]; int lineSpacing = 2; // the space inbetween lines int xLastBottom = 3; // bottom of previous line for (int i = 0; i < lineWidths.length; i++) { lineWidths[i] = MIN_LINE_WIDTH + i; lineX[i] = xLastBottom + lineSpacing + 1; xLastBottom = lineX[i] + lineWidths[i] - 1; } resize(width = xLastBottom + 4, height); dim.width = width; dim.height = height; } Dimension getDimension() { return dim; } /** * Return the current line width - all lines (and other tools) drawn use * this width */ int curLineWidth() { return lineWidth; } /** * Return a list of the available line widths. */ public int[] getLineWidths() { return lineWidths; } /** * Set the line width to a new value. */ public void setLineWidth(int w) { if ((w < MIN_LINE_WIDTH) || (w > MAX_LINE_WIDTH)) return; lineWidth = w; repaint(); } /** * (Re)paint the line tool icon when necessary. */ public void paint(Graphics g) { super.paint(g); g.setColor(Color.black); for (int i = 0; i < lineWidths.length; i++) { // Draw each line in the icon g.fillRect(lineX[i], 3, lineWidths[i], height-5); } } /** * Respond to line width selection events. */ public boolean handleEvent(Event e) { if (e.id == Event.MOUSE_DOWN) { // Determine which line was selected Rectangle r = new Rectangle(); for (int i = 0; i < lineWidths.length; i++) { r.x = lineX[i]; r.y = 0; r.width = lineWidths[i]; r.height = height; if (r.inside(e.x, e.y)) { // This is the line width selected lineWidth = lineWidths[i]; System.out.println("Line width set to " + lineWidth); } } return true; } return super.handleEvent(e); } /** * Return the name of this tool. */ public String getToolName() { return toolName; }}/** * Display a palette of colors, and allow the user to choose one. */class ColorPaletteTool extends ToolCanvas{ final static String toolName = "ColorPaletteTool"; final static int toolId = 2; // Define the tool parameters - the range of colors final static Color colors[] = {Color.black, Color.darkGray, Color.gray, Color.lightGray, Color.white, Color.red, Color.green, Color.blue, Color.cyan, Color.magenta, Color.yellow}; // Tool state: Color color = Color.black; // Tool feature dimensions: int chipWidth; int chipHeight; int chipSpacing; /** * Compute the x-location in the tool of color chip i. */ int chipX(int i) { return i * (chipWidth + chipSpacing) + 3; } /** * Construct the color palette tool. */ public ColorPaletteTool(Tools t) { super(t); setBackground(Color.cyan); chipHeight = height - 5; chipWidth = chipHeight; chipSpacing = 2; resize(width = (chipWidth + chipSpacing) * colors.length + 3, height); dim.width = width; dim.height = height; } Dimension getDimension() { return dim; } /** * Return the current selected color. This color is used in all drawing * operations. */ public Color curColor() { return color; } /** * Return a list of the available colors. */ public Color[] getColors() { return colors; } /** * Set the current color to a new color. */ public void setColor(Color c) { color = c; repaint(); } /** * Set the color of a palette chip to a new color. */ public void setChipColor(int i, Color c) { if (i >= colors.length) return; colors[i] = c; } /** * (Re)paint the color palette tool icon. */ public void paint(Graphics g) { super.paint(g); for (int i = 0; i < colors.length; i++) { // Draw the chip g.setColor(colors[i]); g.fillRect(chipX(i), 3, chipWidth, chipHeight); } } /** * Handle color selection events. */ public boolean handleEvent(Event e) { if (e.id == Event.MOUSE_DOWN) { // Determine which color was selected Rectangle r = new Rectangle(0, 0, chipWidth, chipHeight); for (int i = 0; i < colors.length; i++) { r.x = chipX(i); if (r.inside(e.x, e.y)) { // This is the chip color selected color = colors[i]; System.out.println("color set to " + color); } } return true; } return super.handleEvent(e); } /** * Return the name of this tool. */ public String getToolName() { return toolName; }}/** * Allow the user to draw straight lines. */class LineTool extends ToolCanvas{ final static String toolName = "LineTool"; final static int toolId = 3; // Tool state: int startX; // this is where the mouse was pressed int startY; // " int endX; // this is where the mouse was released int endY; // " /** * Construct the line tool. */ public LineTool(Tools t) { super(t); setBackground(Color.magenta); resize(width, height); dim.width = width; dim.height = height; } Dimension getDimension() { return dim; } /** * (Re)paint the line tool icon. */ public void paint(Graphics g) { g.setColor(Color.white); g.fill3DRect(0, 0, width-1, height-1, true); g.setColor(Color.black); g.drawLine(2, height-3, width-3, 2); } /** * Draw a line, in the current width and color, from (x0,y0) to (x1,y1). */ public void drawLine(Graphics g, int startX, int startY, int endX, int endY, int wid, Color col) { // Make this reflect the current width and color... g.setColor(col); // // We draw a thick line by computing the four corners of an equivalent // diagonal rectangle, and filling it. // // Compute the corner points of the rectangle to fill // // The x and y deltas from the start to the end of the line... int dX = endX - startX; int dY = endY - startY; // The length of the line... double D = Math.sqrt(dX * dX + dY * dY); // The ratio of half the line thickness to the length of the line... double scale = (double)(wid) / (2 * D); // The x and y increments from an endpoint needed to create a rectangle... double ddx = -scale * (double)dY; double ddy = scale * (double)dX; if (ddx > 0) ddx += 0.5; else ddx -= 0.5; // round off if (ddy > 0) ddy += 0.5; else ddy -= 0.5; // " int dx = (int)ddx; int dy = (int)ddy; // Now we can compute the corner points... int xPoints[] = new int[4]; int yPoints[] = new int[4]; xPoints[0] = startX + dx; yPoints[0] = startY + dy; xPoints[1] = startX - dx; yPoints[1] = startY - dy; xPoints[2] = endX - dx; yPoints[2] = endY - dy; xPoints[3] = endX + dx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -