whiteboard.java

来自「white board」· Java 代码 · 共 2,132 行 · 第 1/3 页

JAVA
2,132
字号
		else if (e.id == Event.KEY_PRESS)		{			// Set color to the current color			g.setColor(tools.colorPaletteTool.curColor());			bg.setColor(tools.colorPaletteTool.curColor());			// Set the font to the current font			g.setFont(tools.fontSelector.curFont());			bg.setFont(tools.fontSelector.curFont());			System.out.println("Font is " + tools.fontSelector.curFont().getName());			// Draw the character			c[0] = (char)(e.key);			g.drawChars(c, 0, 1, startX, startY);			bg.drawChars(c, 0, 1, startX, startY);			// Advance the X-position			startX += g.getFontMetrics().charWidth(e.key);		}	}	/**	 * Return the name of this tool.	 */	public String getToolName()	{		return toolName;	}}/** * Allow the user to draw freehand, as with a pencil. Use the current color * and line width. */class PencilTool extends ToolCanvas{	final static String toolName = "PencilTool";	final static int toolId = 6;	// Tool state:	int curX, curY;	private int iconX[] = {4, 7, 9, 12, 16, 18};	private int iconY[] = {4, 12, 8, 14, 10, 11};	/**	 * Construct the pencil tool.	 */	public PencilTool(Tools t)	{		super(t);		setBackground(Color.yellow);		resize(width, height);		dim.width = width;		dim.height = height;	}	Dimension getDimension()	{		return dim;	}	/**	 * (Re)paint the pencil 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.drawPolygon(iconX, iconY, iconX.length);	}	/**	 * Draw an dot, using the current line tool attributes	 */	public void drawDot(Graphics g)	{		// Make this reflect the current width and color...		g.setColor(tools.colorPaletteTool.curColor());		// Draw a filled oval, of the correct thickness		int w = tools.lineWidthTool.curLineWidth();		g.fillOval(curX - w/2, curY - w/2, w, w);	}	/**	 * Apply the pencil tool to the canvas and the double buffer.	 */	public void applyTool(Event e, Graphics g, Graphics bg)	{		super.applyTool(e, g, bg);		if ((e.id == Event.MOUSE_DOWN) || (e.id == Event.MOUSE_DRAG))		{			// Set current location...			curX = e.x;			curY = e.y;			// Draw a dot at the current location			g.setPaintMode();			drawDot(g);			// Update the off-screen buffer			bg.setPaintMode();			drawDot(bg);		}	}	/**	 * Return the name of this tool.	 */	public String getToolName()	{		return toolName;	}}/** * A class for assembling the tools. Maintains the "current tool". */class Tools{	ToolCanvas curTool;				// the current tool	//	// These are all the tools...	//	LineWidthTool lineWidthTool;	ColorPaletteTool colorPaletteTool;	LineTool lineTool;	BoxTool boxTool;	OvalTool ovalTool;	FontSelector fontSelector;	TextTool textTool;	PencilTool pencilTool;	/**	 * Construct the tool assembler	 */	public Tools()	{		lineWidthTool = new LineWidthTool(this);		colorPaletteTool = new ColorPaletteTool(this);		lineTool = new LineTool(this);		boxTool = new BoxTool(this);		ovalTool = new OvalTool(this);		fontSelector = new FontSelector(this);		textTool = new TextTool(this);		pencilTool = new PencilTool(this);		setCurTool(lineTool);	}	/**	 * Return the current tool	 */	public ToolCanvas getCurTool()	{		return curTool;	}	/**	 * Set the current tool	 */	public void setCurTool(ToolCanvas t)	{		curTool = t;		System.out.println("Current tool is " + t.getToolName());	}	public ToolCanvas getTool(int id)	{		switch (id)		{		case LineWidthTool.toolId: return lineWidthTool;		case ColorPaletteTool.toolId: return colorPaletteTool;		case LineTool.toolId: return lineTool;		case BoxTool.toolId: return boxTool;		case OvalTool.toolId: return ovalTool;		case PencilTool.toolId: return pencilTool;		case FontSelector.toolId: return fontSelector;		case TextTool.toolId: return textTool;		default: return null;		}	}}/** * A panel of tools. */class ToolPanel extends Panel{	Tools tools;	/**	 * Construct the tool panel.	 */	public ToolPanel(Tools t)	{		tools = t;		setBackground(Color.blue);		// Layout the tools, individually		add(tools.lineWidthTool);		add(tools.colorPaletteTool);		add(tools.lineTool);		add(tools.boxTool);		add(tools.ovalTool);		add(tools.pencilTool);		add(tools.fontSelector);		add(tools.textTool);	}}/** * The painting canvas. */class MainCanvas extends Canvas{	Tools tools;					// the user's toolkit	Tools cmdTools;					// the paint monitor's tools	Whiteboard whiteboard;			// the owning applet	Image buffer;					// the double buffer	Graphics bg;					// the graphics context of the buffer	Color canvasBackgroundColor = Color.white;	/**	 * Construct the canvas.	 */	public MainCanvas(Tools t, Tools ct, Whiteboard p)	{		tools = t;		cmdTools = ct;		whiteboard = p;		setBackground(canvasBackgroundColor);	}	/**	 * Set up the double buffer	 */	public void setupBuffer(int w, int h)	{		System.out.println("Allocating new buffer");		buffer = createImage(w, h);		bg = buffer.getGraphics();		bg.setColor(canvasBackgroundColor);		bg.fillRect(0, 0, w, h);	}	/**	 * Receive canvas events and forward them to the current tool.	 */	public boolean handleEvent(Event e)	{		if ((e.id == Event.MOUSE_DOWN) || (e.id == Event.MOUSE_DRAG)			|| (e.id == Event.MOUSE_UP) || (e.id == Event.KEY_PRESS))		{			// Draw image			tools.getCurTool().applyTool(e, getGraphics(), bg);			// Construct an equivalent command to send to paint server			String command = tools.getCurTool().makeCommandString(e);			// Send the command to the server, for broadcast to chat clients			if (command != null)				try {whiteboard.serverConnection.write(command);}				catch (IOException ex)				{					System.out.println("Server unreachable");				}			return true;		}		return super.handleEvent(e);	}	/**	 * Apply the command to the graphics context (and buffer), without changing	 * the state of the canvas.	 */	public void applyCommand(Command cmd)	{		ToolCanvas tc = cmdTools.getTool(cmd.toolId);		if (tc == null)			System.out.println("This tool is not implemented for broadcast");		else			tc.applyCommand(cmd, getGraphics(), bg);	}	/**	 * (Re)paint the canvas when necessary.	 */	public void paint(Graphics g)	{		// Check if window was just resized		Dimension d = size();		if ((d.width != buffer.getWidth(this)) || 				(d.height != buffer.getHeight(this)))		{			{			// Save the currently displayed image			Image temp = buffer;			// Reallocate a buffer to match the new size			setupBuffer(d.width, d.height);			// Restore the image to the new buffer			bg.drawImage(temp, 0, 0, this);			}			System.gc();			// force the old buffer to be free'd		}		// Restore the image to the screen		getGraphics().drawImage(buffer, 0, 0, this);	}	/**	 * Update the canvas	 */	public void update(Graphics g)	{		paint(g);	}}/** * Helper class for managing a server connection. */class ServerConnection{	String hostname;	int port;	Socket socket;	DataInputStream dis;	DataOutputStream dos;	final static int MAXLENGTH = 5000;	protected byte inbuf[] = new byte[MAXLENGTH];	protected int nbytes = 0;	/**	 * Establish a connection with a Whiteboard server.	 */	public void makeConnection(String h, int p)	throws		java.net.UnknownHostException,		IOException	{		hostname = h;		port = p;		if (TestData.LOCALMODE) return;		socket = new Socket(hostname, port);		// Issue confirmation to user		InetAddress rina = socket.getInetAddress();		System.out.println("Connected to " + rina.toString());		InetAddress lina = rina.getLocalHost();		System.out.println("Local host designation: " + lina.toString());		// Determine the socket's input and output stream handles		dis = new DataInputStream(socket.getInputStream());		dos = new DataOutputStream(socket.getOutputStream());	}	/**	 * Send (the ascii-equivalent of) a string to the server.	 */	public void write(String s)	throws		IOException	{		// Write buffer to the socket		if (TestData.TESTMODE) System.out.println("Writing '" + s + "' to server");		if (TestData.LOCALMODE) return;		dos.writeBytes(s);									// It is peculiar, but the implementation									// of this function casts the char data to									// bytes, apparently throwing away the upper									// eight bits; so we can use it here.	}	/**	 * Read a newline-terminated ascii array from the server, and return	 * its string equivalent. Block until one is found. Throws IOException	 * if connection is broken before one is found. Uses buffering (and	 * thus it does not matter if several actual io operations are required	 * before the newline is found).	 */	public String readln()		// Reads data from the server through the next new-line.	throws		IOException	{		if (TestData.TESTMODE) System.out.println("Reading from server...");		if (TestData.LOCALMODE) return TestData.testString;		int curpos = 0;		for (;;)			// until a nl is found		{			// Check for a nl			for (; curpos < nbytes; curpos++)			{				// if nl, return thru nl, shift remainder down (consume), and return				//				if ('\n' == (char)(inbuf[curpos]))				{					//					// Consume 0 thru curpos (includes the nl)...					//					// Construct string...					String s = new String(inbuf, 0, 0, curpos+1);					// Adjust pointers...					nbytes -= (curpos+1);					// Shift remaining bytes down to start of inbuf...					for (int i = 0; i < nbytes; i++)					{						// Move nbytes-bytes curpos-positions left						inbuf[i] = inbuf[i+curpos];					}					return s;				}			}			// Out of bytes and no nl...			// Perform another read, into inbuf, starting at curpos...			int n = dis.read(inbuf, curpos, MAXLENGTH-nbytes);			if (n <= 0)			{				// No more data, and no nl found...				throw new IOException();			}			nbytes += n;		}	}}/** * Monitor the server connection for paint commands, and execute them when they * are received. */class PaintMonitor extends Thread{	Whiteboard whiteboard;	public PaintMonitor(Whiteboard p)	{		whiteboard = p;	}	public void run()	{		// Perform blocking reads on server connection		for (;;)		{			String s;			try {s = whiteboard.serverConnection.readln();}			catch (IOException ex)			{				// Connection is probably broken...				System.out.println("Unable to read from server");				return;			}			//			// Interpret the command			//			if (TestData.TESTMODE)				System.out.println("Command received: '" + s + "'");			Command cmd = null;			try {cmd = new Command(s);}			catch (Exception ex)			{				System.out.println("Invalid command received from server");				continue;			}			whiteboard.mainCanvas.applyCommand(cmd);		}	}}/** * The applet. */public class Whiteboard extends Applet{	// The main components:	LayoutManager layoutManager;	MainCanvas mainCanvas;	Panel toolPanel;	Frame mainFrame;	Tools tools;	Tools cmdTools;	ServerConnection serverConnection;	PaintMonitor paintMonitor;	/**	 * Construct the applet	 */	public Whiteboard()	{		// Call the superclass constructor (for Applet)		super();		// Instantiate the tools		tools = new Tools();		cmdTools = new Tools();		//		// Construct the canvas		//		mainCanvas = new MainCanvas(tools, cmdTools, this);		//		// Construct the tool panel		//		toolPanel = new ToolPanel(tools);    	//    	// Lay out the constructed applet components in the applet...    	//		// Create a Border Layout		setLayout(new BorderLayout());    	    	// Layout the tool panel    	add("North", toolPanel);    	// Layout the canvas    	add("Center", mainCanvas);    	mainCanvas.resize(200, 100);    	// Create the server connection object    	serverConnection = new ServerConnection();    	// Create the server monitor    	paintMonitor = new PaintMonitor(this);	}    /**     * After all objects have been constructed, and the applet context exists:     */    public void init()    {    	super.init();    	// Check our assumptions about the applet context...    	mainFrame = (Frame)(getParent());    	if (! (getParent() instanceof Frame) ) System.exit(1);    	// Set up the drawing canvas double-buffer (needs the final canvas size)    	mainCanvas.resize(    		ConfigData.FRAME_INITIAL_WIDTH, ConfigData.FRAME_INITIAL_HEIGHT);    	Dimension d = mainCanvas.size();    	mainCanvas.setupBuffer(d.width, d.height);    	// Establish connection with Whiteboard server    	try {serverConnection.makeConnection(    		ConfigData.DEFAULT_HOST_NAME, ConfigData.DEFAULT_PORT_NUMBER);}    	catch (Exception ex)    	{    		System.out.println("Unable to make connection to Paint server");    		return;    	}    	// Start the monitor    	paintMonitor.start();    }    /**     * Start or restart the applet:     */    public void start()    {    	super.start();    }    /**     * Sleep the applet:     */    public void stop()    {    	super.stop();    }    /**     * Handle applet events     */    public boolean handleEvent(Event e)    {		// The kill-window event...		if (e.id == Event.WINDOW_DESTROY)		{	    	System.exit(0);		}		return super.handleEvent(e);    }    /**     * (Re)paint the applet     */    public void paint(Graphics g)    {    	super.paint(g);    }    /**     * Main routine, for running as an application.     */    public static void main(String args[])    {		// Create a Frame		MainFrame f = new MainFrame("Whiteboard");		// Instantiate the Applet		Whiteboard applet = new Whiteboard();		// Add the Applet to the Frame (Frame's use BorderLayout)		f.add("Center", applet);		// Resize and show the Frame		f.resize(ConfigData.FRAME_INITIAL_WIDTH, ConfigData.FRAME_INITIAL_HEIGHT);		f.show();		// Init and start the Applet		applet.init();		applet.start();    }}/** * Define a frame that can be destroyed. */class MainFrame extends Frame{    public MainFrame(String s)    {    	super(s);    }    // Handle close events by simply exiting    public boolean handleEvent(Event e)    {		if (e.id == Event.WINDOW_DESTROY)		{	    	System.exit(0);		}		return false;    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?