OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Native Client Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be found | |
3 // in the LICENSE file. | |
4 | |
5 /** | |
6 * @fileoverview This file contains the JavaScript required for the WebGTT | |
7 * application, specifically, the implementation of the Canvas class. This | |
8 * implementation provides functions for manipulating a canvas, and | |
9 * adding/managing event handlers for a canvas. | |
10 * | |
11 * @author ragad@google.com (Raga Gopalakrishnan) | |
12 */ | |
13 | |
14 /** | |
15 * This constant holds the thickness of the canvas border. | |
16 * @type {number} | |
17 * @const | |
18 */ | |
19 var BORDER_THICKNESS = 5; | |
20 | |
21 /** | |
22 * This class is used to represent a canvas. | |
23 * | |
24 * @param drawingCanvas Handle to the DOM object representing the canvas. | |
25 * @param {Graph} graph1 Reference to the graph associated with the canvas. | |
26 * @constructor | |
27 */ | |
28 Canvas = function (drawingCanvas, graph1) { | |
29 this.drawingCanvas = drawingCanvas; | |
30 this.graph1 = graph1; | |
31 | |
32 /** | |
33 * This variable is the handle to the drawing surface of the canvas. | |
34 */ | |
35 this.drawingContext = this.drawingCanvas.getContext('2d'); | |
36 | |
37 /** | |
38 * This boolean variable indicates whether the canvas/graph is editable or | |
39 * not. | |
40 */ | |
41 this.editMode = true; | |
42 | |
43 this.redrawCanvas(); | |
44 }; | |
45 | |
46 /** | |
47 * This function (re)draws the canvas. | |
48 */ | |
49 Canvas.prototype.redrawCanvas = function () { | |
50 // The easiest way to reset the canvas is to set one of its properties. | |
51 this.drawingCanvas.width = this.drawingCanvas.width; | |
52 | |
53 this.drawingContext.lineWidth = BORDER_THICKNESS; | |
54 this.drawingContext.strokeRect(0, 0, this.drawingCanvas.width, | |
55 this.drawingCanvas.height); | |
56 this.graph1.draw(this.drawingContext); | |
57 }; | |
58 | |
59 /** | |
60 * This function sets the value of Canvas.editMode. | |
61 * | |
62 * @param {boolean} editMode The value to be assigned to Canvas.editMode. | |
63 */ | |
64 Canvas.prototype.setEditMode = function (editMode) { | |
65 this.editMode = editMode; | |
66 }; | |
67 | |
68 /** | |
69 * This function handles the click event on the canvas. | |
70 * | |
71 * When the user clicks on the canvas, there are several possibilities to be | |
72 * handled. If the user clicked sufficiently far away from any existing vertex, | |
73 * then a new vertex should be created there. If the user clicked too close to | |
74 * an existing vertex, that vertex should be selected/deselected. If at this | |
75 * point, two vertices are selected, and an edge doesn't exist between them, a | |
76 * new edge should be created. If an edge does exist, then that edge should be | |
77 * selected/deselected. Finally, the control panel (the coloring button) should | |
78 * be enabled only if there is at least one vertex on the canvas. | |
79 * | |
80 * @param {object} clickEvent The Event object containing information about the | |
81 * click event. | |
82 */ | |
83 Canvas.prototype.handleCanvasClick = function (clickEvent) { | |
84 if (this.editMode) { | |
85 // The origin of the coordinate system is at the top left. The x-coordinate | |
86 // increases while moving horizontally right, and the y-coordinate increases | |
87 // while moving vertically down. | |
88 var x; | |
89 var y; | |
90 if (clickEvent.pageX || clickEvent.pageY) { | |
91 // pageX and pageY give the coordinates relative to the document | |
92 x = clickEvent.pageX; | |
93 y = clickEvent.pageY; | |
94 } else { | |
95 // Our old friend, Internet Explorer does not support pageX and pageY | |
96 // properties, so we calculate it manually | |
97 x = clickEvent.clientX + document.body.scrollLeft + | |
98 document.documentElement.scrollLeft; | |
99 y = clickEvent.clientY + document.body.scrollTop + | |
100 document.documentElement.scrollTop; | |
101 } | |
102 x -= this.drawingCanvas.offsetLeft; | |
103 y -= this.drawingCanvas.offsetTop; | |
104 | |
105 var shouldRedraw = false; | |
106 | |
107 var closestVertex = this.graph1.getNearestVertex(x,y); | |
108 var closestDistance = undefined; | |
109 if (closestVertex != undefined) { | |
110 closestDistance = Math.sqrt(Math.pow(x-closestVertex.x,2) + | |
111 Math.pow(y-closestVertex.y,2)); | |
112 } | |
113 | |
114 if (closestVertex == undefined || closestDistance > VERTEX_SIZE * 4) { | |
115 this.graph1.addVertex(new Vertex(x, y)); | |
116 shouldRedraw = true; | |
117 } else if (closestDistance < VERTEX_SIZE+3) { | |
118 closestVertex.setSelected(!closestVertex.isSelected); | |
119 shouldRedraw = true; | |
120 if (closestVertex.isSelected) { | |
121 // Check if another vertex is selected. | |
122 for (var i = 0 ; i < this.graph1.listOfVertices.length ; i++) { | |
123 if (this.graph1.listOfVertices[i] != closestVertex && | |
124 this.graph1.listOfVertices[i].isSelected) { | |
125 var tempEdge = this.graph1.getEdge(this.graph1.listOfVertices[i], | |
126 closestVertex); | |
127 if (tempEdge != undefined) { | |
128 tempEdge.setSelected(!tempEdge.isSelected); | |
129 } else { | |
130 this.graph1.addEdge(new Edge(this.graph1.listOfVertices[i], | |
131 closestVertex)); | |
132 } | |
133 this.graph1.listOfVertices[i].setSelected(false); | |
134 closestVertex.setSelected(false); | |
135 break; | |
136 } | |
137 } | |
138 } | |
139 } | |
140 | |
141 if (shouldRedraw) { | |
142 this.redrawCanvas(); | |
143 } | |
144 | |
145 if ((this.graph1.listOfVertices.length > 0) && (naclModule1 != undefined)) { | |
146 coloringButton1.setDisabled(false); | |
147 } else { | |
148 coloringButton1.setDisabled(true); | |
149 } | |
150 } | |
151 }; | |
152 | |
153 /** | |
154 * This function handles the keydown event on the window. | |
155 * | |
156 * When the user presses any key on the keyboard, this function first checks if | |
157 * the key that was pressed was a 'Delete' key, and if the canvas/graph is | |
158 * editable. If both these conditions are satisfied, then the selected vertices | |
159 * and/or edges are deleted. Finally, the control panel (the coloring button) | |
160 * should be enabled only if there is at least one vertex on the canvas. | |
161 * | |
162 * @param {object} keydownEvent The Event object containing information about | |
163 * the keydown event. | |
164 */ | |
165 Canvas.prototype.handleCanvasKeydown = function (keydownEvent) { | |
166 if (keydownEvent.keyCode == 46 && this.editMode) { | |
167 var shouldredraw = false; | |
168 this.setEditMode(false); | |
169 | |
170 for (var i = 0 ; i < this.graph1.listOfVertices.length ; i++) { | |
171 if (this.graph1.listOfVertices[i].isSelected) { | |
172 this.graph1.deleteVertexByIndex(i); | |
173 // Deleting a vertex moves the next vertex in the array back by a | |
174 // position, so the counter has to be decremented to account for that. | |
175 i--; | |
176 shouldRedraw = true; | |
177 } | |
178 } | |
179 | |
180 for (var i = 0 ; i < this.graph1.listOfEdges.length ; i++) { | |
181 if (this.graph1.listOfEdges[i].isSelected) { | |
182 this.graph1.deleteEdgeByIndex(i); | |
183 // Deleting an edge moves the next edge in the array back by a position, | |
184 // so the counter has to be decremented to account for that. | |
185 i--; | |
186 shouldRedraw = true; | |
187 } | |
188 } | |
189 | |
190 this.setEditMode(true); | |
191 | |
192 if (shouldRedraw) { | |
193 this.redrawCanvas(); | |
194 if (this.graph1.listOfVertices.length > 0) { | |
195 coloringButton1.setDisabled(false); | |
196 } else { | |
197 coloringButton1.setDisabled(true); | |
198 } | |
199 } else { | |
200 alert("Nothing to delete!"); | |
201 } | |
202 } | |
203 }; | |
OLD | NEW |