Author: kpreisser Date: Thu Oct 10 22:20:03 2013 New Revision: 1531130 URL: http://svn.apache.org/r1531130 Log: Allow to draw other forms like line, rectangle and circle/ellipse.
Modified: tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/drawboard/DrawMessage.java tomcat/trunk/webapps/examples/websocket/drawboard.xhtml Modified: tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/drawboard/DrawMessage.java URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/drawboard/DrawMessage.java?rev=1531130&r1=1531129&r2=1531130&view=diff ============================================================================== --- tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/drawboard/DrawMessage.java (original) +++ tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/drawboard/DrawMessage.java Thu Oct 10 22:20:03 2013 @@ -34,9 +34,14 @@ public final class DrawMessage { private byte colorR, colorG, colorB, colorA; private double thickness; private int x1, y1, x2, y2; + private boolean lastInChain; /** - * The type. 1: Line. + * The type.<br> + * 1: Brush<br> + * 2: Line<br> + * 3: Rectangle<br> + * 4: Ellipse */ public int getType() { return type; @@ -102,10 +107,24 @@ public final class DrawMessage { this.y2 = y2; } + /** + * Specifies if this DrawMessage is the last one in a chain + * (e.g. a chain of brush paths).<br> + * Currently it is unused. + */ + public boolean isLastInChain() { + return lastInChain; + } + public void setLastInChain(boolean lastInChain) { + this.lastInChain = lastInChain; + } + + public DrawMessage(int type, byte colorR, byte colorG, byte colorB, - byte colorA, double thickness, int x1, int x2, int y1, int y2) { + byte colorA, double thickness, int x1, int x2, int y1, int y2, + boolean lastInChain) { this.type = type; this.colorR = colorR; @@ -117,6 +136,7 @@ public final class DrawMessage { this.x2 = x2; this.y1 = y1; this.y2 = y2; + this.lastInChain = lastInChain; } @@ -125,15 +145,37 @@ public final class DrawMessage { * @param g */ public void draw(Graphics2D g) { - switch (type) { - case 1: + + g.setStroke(new BasicStroke((float) thickness, + BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)); + g.setColor(new Color(colorR & 0xFF, colorG & 0xFF, colorB & 0xFF, + colorA & 0xFF)); + + if (type == 1 || type == 2) { // Draw a line. - g.setStroke(new BasicStroke((float) thickness, - BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)); - g.setColor(new Color(colorR & 0xFF, colorG & 0xFF, colorB & 0xFF, - colorA & 0xFF)); g.drawLine(x1, y1, x2, y2); - break; + + } else if (type == 3 || type == 4) { + int x1 = this.x1, x2 = this.x2, + y1 = this.y1, y2 = this.y2; + if (x1 > x2) { + x1 = this.x2; + x2 = this.x1; + } + if (y1 > y2) { + y1 = this.y2; + y2 = this.y1; + } + + if (type == 3) { + // Draw a rectangle. + g.drawRect(x1, y1, x2 - x1, y2 - y1); + + } else if (type == 4) { + // Draw an ellipse. + g.drawArc(x1, y1, x2 - x1, y2 - y1, 0, 360); + + } } } @@ -148,7 +190,8 @@ public final class DrawMessage { return type + "," + (colorR & 0xFF) + "," + (colorG & 0xFF) + "," + (colorB & 0xFF) + "," + (colorA & 0xFF) + "," + thickness - + "," + x1 + "," + y1 + "," + x2 + "," + y2; + + "," + x1 + "," + y1 + "," + x2 + "," + y2 + "," + + (lastInChain ? "1" : "0"); } public static DrawMessage parseFromString(String str) @@ -158,12 +201,13 @@ public final class DrawMessage { byte[] colors = new byte[4]; double thickness; int[] coords = new int[4]; + boolean last; try { String[] elements = str.split(","); type = Integer.parseInt(elements[0]); - if (type != 1) + if (!(type >= 1 && type <= 4)) throw new ParseException("Invalid type: " + type); for (int i = 0; i < colors.length; i++) { @@ -181,6 +225,7 @@ public final class DrawMessage { + coords[i]); } + last = !"0".equals(elements[10]); } catch (RuntimeException ex) { throw new ParseException(ex); @@ -188,7 +233,7 @@ public final class DrawMessage { DrawMessage m = new DrawMessage(type, colors[0], colors[1], colors[2], colors[3], thickness, coords[0], coords[2], - coords[1], coords[3]); + coords[1], coords[3], last); return m; } @@ -206,4 +251,5 @@ public final class DrawMessage { } + } Modified: tomcat/trunk/webapps/examples/websocket/drawboard.xhtml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/websocket/drawboard.xhtml?rev=1531130&r1=1531129&r2=1531130&view=diff ============================================================================== --- tomcat/trunk/webapps/examples/websocket/drawboard.xhtml (original) +++ tomcat/trunk/webapps/examples/websocket/drawboard.xhtml Thu Oct 10 22:20:03 2013 @@ -64,7 +64,6 @@ #drawContainer, #console-container { box-shadow: 0px 0px 8px 3px #bbb; border: 1px solid #CCCCCC; - } ]]></style> @@ -139,7 +138,7 @@ this.resumeProcessing = function() { pauseProcessing = false; - // Process all queued functions until some handler calls + // Process all queued functions until some handler calls // pauseProcessing() again. while (functionQueue.length > 0 && !pauseProcessing) { var func = functionQueue.pop(); @@ -180,15 +179,26 @@ var mouseInWindow = false; var mouseDown = false; var currentMouseX = 0, currentMouseY = 0; + var currentPreviewPath = null; var availableColors = []; var currentColorIndex; var colorContainers; + var previewTransparency = 0.65; var availableThicknesses = [2, 3, 6, 10, 16, 28, 50]; var currentThicknessIndex; var thicknessContainers; + var availableDrawTypes = [ + { name: "Brush", id: 1, continuous: true }, + { name: "Line", id: 2, continuous: false }, + { name: "Rectangle", id: 3, continuous: false }, + { name: "Ellipse", id: 4, continuous: false } + ]; + var currentDrawTypeIndex; + var drawTypeContainers; + var labelContainer = document.getElementById("labelContainer"); var placeholder = document.createElement("div"); @@ -208,7 +218,7 @@ this.id = id; } - function Path(type, color, thickness, x1, y1, x2, y2) { + function Path(type, color, thickness, x1, y1, x2, y2, lastInChain) { this.type = type; this.color = color; this.thickness = thickness; @@ -216,6 +226,26 @@ this.y1 = y1; this.x2 = x2; this.y2 = y2; + this.lastInChain = lastInChain; + + function ellipse(ctx, x, y, w, h) { + /* Drawing a ellipse cannot be done directly in a + * CanvasRenderingContext2D - we need to use drawArc() + * in conjunction with scaling the context so that we + * get the needed proportion. + */ + ctx.save(); + + // Translate and scale the context so that we can draw + // an arc at (0, 0) with a radius of 1. + ctx.translate(x + w / 2, y + h / 2); + ctx.scale(w / 2, h / 2); + + ctx.beginPath(); + ctx.arc(0, 0, 1, 0, Math.PI * 2, false); + + ctx.restore(); + } this.draw = function(ctx) { ctx.beginPath(); @@ -223,7 +253,7 @@ ctx.lineWidth = thickness; var style = rgb(color); ctx.strokeStyle = style; - + if (x1 == x2 && y1 == y2) { // Always draw as arc to meet the behavior // in Java2D. @@ -232,11 +262,26 @@ Math.PI * 2.0, false); ctx.fill(); } else { - if (type == 1) { + if (type == 1 || type == 2) { // Draw a line. ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke(); + } else if (type == 3) { + // Draw a rectangle. + if (x1 == x2 || y1 == y2) { + // Draw as line + ctx.moveTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.stroke(); + } else { + ctx.strokeRect(x1, y1, x2 - x1, y2 - y1); + } + } else if (type == 4) { + // Draw a ellipse. + ellipse(ctx, x1, y1, x2 - x1, y2 - y1); + ctx.closePath(); + ctx.stroke(); } } }; @@ -327,7 +372,7 @@ var url = URL.createObjectURL(blob); - var img = new Image(); + var img = new Image(); // We must wait until the onload event is // raised until we can draw the image onto @@ -401,7 +446,8 @@ parseInt(elements[7]), parseInt(elements[8]), parseInt(elements[9]), - parseInt(elements[10])); + parseInt(elements[10]), + elements[11] != "0"); // Draw the path onto the last canvas. path.draw(canvasServerImageCtx); @@ -414,7 +460,7 @@ // Now go through the pathsNotHandled array and // remove the paths that were already handled by // the server. - while (pathsNotHandled.length > 0 + while (pathsNotHandled.length > 0 && pathsNotHandled[0].id <= maxLastHandledId) pathsNotHandled.shift(); @@ -425,7 +471,7 @@ } refreshDisplayCanvas(); - } + } } } } @@ -446,22 +492,28 @@ function refreshDisplayCanvas() { canvasDisplayCtx.drawImage(canvasBackground, 0, 0); - if (mouseInWindow && !mouseDown) { + if (currentPreviewPath != null) { + // Draw the preview path. + currentPreviewPath.draw(canvasDisplayCtx); + + } else if (mouseInWindow && !mouseDown) { canvasDisplayCtx.beginPath(); var color = availableColors[currentColorIndex].slice(0); - color[3] = 0.5; + color[3] = previewTransparency; canvasDisplayCtx.fillStyle = rgb(color); - - canvasDisplayCtx.arc(currentMouseX, currentMouseY, availableThicknesses[currentThicknessIndex] / 2, 0, Math.PI * 2.0, true); - + + canvasDisplayCtx.arc(currentMouseX, currentMouseY, + availableThicknesses[currentThicknessIndex] / 2, + 0, Math.PI * 2.0, true); canvasDisplayCtx.fill(); } + } function startControls() { labelContainer.removeChild(placeholder); placeholder = undefined; - + labelContainer.appendChild( document.createTextNode("Number of Players: ")); labelContainer.appendChild(labelPlayerCount); @@ -472,58 +524,89 @@ drawContainer.appendChild(optionContainer); - canvasDisplay.onmousemove = function(e) { - mouseInWindow = true; - var oldMouseX = currentMouseX, oldMouseY = currentMouseY; - currentMouseX = e.pageX - canvasDisplay.offsetLeft; - currentMouseY = e.pageY - canvasDisplay.offsetTop; - - if (mouseDown) { - var path = new Path(1, availableColors[currentColorIndex], - availableThicknesses[currentThicknessIndex], - oldMouseX, oldMouseY, currentMouseX, - currentMouseY); - // Draw it on the background canvas. - path.draw(canvasBackgroundCtx); - - // Send it to the sever. - pushPath(path); - } - - refreshDisplayCanvas(); - }; - canvasDisplay.onmousedown = function(e) { - currentMouseX = e.pageX - canvasDisplay.offsetLeft; - currentMouseY = e.pageY - canvasDisplay.offsetTop; - if (e.button == 0) { - mouseDown = true; - - var path = new Path(1, availableColors[currentColorIndex], - availableThicknesses[currentThicknessIndex], - currentMouseX, currentMouseY, currentMouseX, - currentMouseY); - // Draw it on the background canvas. - path.draw(canvasBackgroundCtx); - - // Send it to the sever. - pushPath(path); + currentMouseX = e.pageX - canvasDisplay.offsetLeft; + currentMouseY = e.pageY - canvasDisplay.offsetTop; - refreshDisplayCanvas(); + mouseDown = true; + canvasMouseMove(e); } else if (mouseDown) { // Cancel drawing. mouseDown = false; + currentPreviewPath = null; refreshDisplayCanvas(); } } + var canvasMouseMove = canvasDisplay.onmousemove = function(e) { + mouseInWindow = true; + var mouseX = e.pageX - canvasDisplay.offsetLeft; + var mouseY = e.pageY - canvasDisplay.offsetTop; + + if (mouseDown) { + var drawType = availableDrawTypes[currentDrawTypeIndex]; + + if (drawType.continuous) { + + var path = new Path(drawType.id, + availableColors[currentColorIndex], + availableThicknesses[currentThicknessIndex], + currentMouseX, currentMouseY, mouseX, + mouseY, false); + // Draw it on the background canvas. + path.draw(canvasBackgroundCtx); + + // Send it to the sever. + pushPath(path); + + // Refresh old coordinates + currentMouseX = mouseX; + currentMouseY = mouseY; + + } else { + // Create a new preview path. + var color = availableColors[currentColorIndex].slice(0); + color[3] = previewTransparency; + currentPreviewPath = new Path(drawType.id, + color, + availableThicknesses[currentThicknessIndex], + currentMouseX, currentMouseY, mouseX, + mouseY, false); + } + } else { + currentMouseX = mouseX; + currentMouseY = mouseY; + } + + refreshDisplayCanvas(); + }; + canvasDisplay.onmouseup = function(e) { if (e.button == 0) { if (mouseDown) { mouseDown = false; + currentPreviewPath = null; + + var mouseX = e.pageX - canvasDisplay.offsetLeft; + var mouseY = e.pageY - canvasDisplay.offsetTop; + var drawType = availableDrawTypes[currentDrawTypeIndex]; + + var path = new Path(drawType.id, availableColors[currentColorIndex], + availableThicknesses[currentThicknessIndex], + currentMouseX, currentMouseY, mouseX, + mouseY, true); + // Draw it on the background canvas. + path.draw(canvasBackgroundCtx); + + // Send it to the sever. + pushPath(path); + + // Refresh old coordinates + currentMouseX = mouseX; + currentMouseY = mouseY; refreshDisplayCanvas(); } @@ -542,16 +625,15 @@ "margin: 4px; border: 1px solid #bbb; border-radius: 3px;"); optionContainer.appendChild(colorContainersBox); - colorContainers = new Array(3 * 3 * 3); for (var i = 0; i < colorContainers.length; i++) { var colorContainer = colorContainers[i] = document.createElement("div"); - var color = availableColors[i] = + var color = availableColors[i] = [ Math.floor((i % 3) * 255 / 2), Math.floor((Math.floor(i / 3) % 3) * 255 / 2), - Math.floor((Math.floor(i / (3 * 3)) % 3) * 255 / 2), + Math.floor((Math.floor(i / (3 * 3)) % 3) * 255 / 2), 1.0 ]; colorContainer.setAttribute("style", @@ -571,12 +653,37 @@ divClearLeft.setAttribute("style", "clear: left;"); colorContainersBox.appendChild(divClearLeft); + + var drawTypeContainersBox = document.createElement("div"); + drawTypeContainersBox.setAttribute("style", + "float: right; margin-right: 3px; margin-top: 1px;"); + optionContainer.appendChild(drawTypeContainersBox); + + drawTypeContainers = new Array(availableDrawTypes.length); + for (var i = 0; i < drawTypeContainers.length; i++) { + var drawTypeContainer = drawTypeContainers[i] = + document.createElement("div"); + drawTypeContainer.setAttribute("style", + "text-align: center; margin: 3px; padding: 0 3px;" + + "height: 18px; float: left;"); + drawTypeContainer.style.border = "2px solid #000"; + drawTypeContainer.appendChild(document.createTextNode( + String(availableDrawTypes[i].name))); + drawTypeContainer.onmousedown = (function(ix) { + return function() { + setDrawType(ix); + }; + })(i); + + drawTypeContainersBox.appendChild(drawTypeContainer); + } + + var thicknessContainersBox = document.createElement("div"); thicknessContainersBox.setAttribute("style", "margin: 3px; border: 1px solid #bbb; border-radius: 3px;"); optionContainer.appendChild(thicknessContainersBox); - thicknessContainers = new Array(availableThicknesses.length); for (var i = 0; i < thicknessContainers.length; i++) { var thicknessContainer = thicknessContainers[i] = @@ -596,6 +703,7 @@ thicknessContainersBox.appendChild(thicknessContainer); } + divClearLeft = document.createElement("div"); divClearLeft.setAttribute("style", "clear: left;"); thicknessContainersBox.appendChild(divClearLeft); @@ -603,6 +711,7 @@ setColor(0); setThickness(0); + setDrawType(0); } @@ -624,9 +733,10 @@ + path.color[0] + "," + path.color[1] + "," + path.color[2] + "," + Math.round(path.color[3] * 255.0) + "," - + path.thickness + "," + path.x1 + "," - + path.y1 + "," + path.x2 + "," + path.y2; - + + path.thickness + "," + path.x1 + "," + + path.y1 + "," + path.x2 + "," + path.y2 + "," + + (path.lastInChain ? "1" : "0"); + socket.send("1" + message); } @@ -638,7 +748,7 @@ thicknessContainers[currentThicknessIndex] .style.borderColor = "#d08"; } - + function setColor(colorIndex) { if (typeof currentColorIndex !== "undefined") colorContainers[currentColorIndex] @@ -648,6 +758,15 @@ .style.borderColor = "#d08"; } + function setDrawType(drawTypeIndex) { + if (typeof currentDrawTypeIndex !== "undefined") + drawTypeContainers[currentDrawTypeIndex] + .style.borderColor = "#000"; + currentDrawTypeIndex = drawTypeIndex; + drawTypeContainers[currentDrawTypeIndex] + .style.borderColor = "#d08"; + } + connect(); --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org