-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #93 from RAIRLab/64-rewrite-with-universal-event-l…
…isteners Homunculus Event Handlers with a splash of #48
- Loading branch information
Showing
6 changed files
with
290 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import {Point} from "./AEG/Point"; | ||
import {AtomNode} from "./AEG/AtomNode"; | ||
import {redrawCut, tree} from "./index"; | ||
import {Rectangle} from "./AEG/Rectangle"; | ||
|
||
const canvas: HTMLCanvasElement = <HTMLCanvasElement>document.getElementById("canvas"); | ||
const res: CanvasRenderingContext2D | null = canvas.getContext("2d"); | ||
if (res === null) { | ||
throw Error("2d rendering context not supported"); | ||
} | ||
const ctx: CanvasRenderingContext2D = res; | ||
let atomMetrics: TextMetrics; | ||
|
||
let hasMouseDown: Boolean = false; | ||
let hasAtom: Boolean = false; | ||
let currentAtom: AtomNode = new AtomNode(); | ||
|
||
/** | ||
* Will compare the event given with all possible events it could be. | ||
* keypress checks to see if the key was a letter and if yes sets it to that letter. | ||
* mousedown sets the atom down, calculates the bounding box, and checks for what color. | ||
* mousemove will alter the origin position and the starting vertex of the bounding box. | ||
* mouseup will add the atom to the tree if it is in a valid location. | ||
* mosueout will end drawing early. | ||
* @param event The event that will be used | ||
* @param event the event that will be used | ||
*/ | ||
export function atomHandler(event: Event) { | ||
if (event.type === "keypress") { | ||
const thisEvent: KeyboardEvent = <KeyboardEvent>event; | ||
const regex = new RegExp(/^[A-Za-z]$/); | ||
if (regex.test(thisEvent.key)) { | ||
currentAtom.identifier = thisEvent.key; | ||
hasAtom = true; | ||
} | ||
} else if (event.type === "mousedown" && hasAtom) { | ||
const thisEvent: MouseEvent = <MouseEvent>event; | ||
atomMetrics = ctx.measureText(currentAtom.identifier); | ||
const startVertex: Point = new Point( | ||
thisEvent.clientX, | ||
thisEvent.clientY - atomMetrics.actualBoundingBoxAscent | ||
); | ||
currentAtom.rect = new Rectangle( | ||
startVertex, | ||
atomMetrics.width, | ||
atomMetrics.fontBoundingBoxDescent + atomMetrics.actualBoundingBoxAscent | ||
); | ||
currentAtom.origin = new Point(thisEvent.clientX, thisEvent.clientY); | ||
|
||
ctx.clearRect(0, 0, canvas.width, canvas.height); | ||
redrawCut(tree.sheet); | ||
if (tree.canInsert(currentAtom)) { | ||
drawAtom(currentAtom, "#00FF00"); | ||
} else { | ||
drawAtom(currentAtom, "#6600ff"); | ||
} | ||
hasMouseDown = true; | ||
} else if (event.type === "mousemove" && hasMouseDown) { | ||
const thisEvent: MouseEvent = <MouseEvent>event; | ||
currentAtom.origin = new Point(thisEvent.clientX, thisEvent.clientY); | ||
currentAtom.rect.startVertex = new Point( | ||
thisEvent.clientX, | ||
thisEvent.clientY - atomMetrics.actualBoundingBoxAscent | ||
); | ||
|
||
ctx.clearRect(0, 0, canvas.width, canvas.height); | ||
redrawCut(tree.sheet); | ||
if (tree.canInsert(currentAtom)) { | ||
drawAtom(currentAtom, "#00FF00"); | ||
} else { | ||
drawAtom(currentAtom, "#FF0000"); | ||
} | ||
} else if (event.type === "mouseup" && hasMouseDown) { | ||
if (tree.canInsert(currentAtom)) { | ||
tree.insert(currentAtom); | ||
} | ||
currentAtom = new AtomNode(currentAtom.identifier); | ||
ctx.clearRect(0, 0, canvas.width, canvas.height); | ||
redrawCut(tree.sheet); | ||
hasMouseDown = false; | ||
console.log(tree.toString()); | ||
} else if (event.type === "mouseout" && hasMouseDown) { | ||
hasMouseDown = false; | ||
currentAtom = new AtomNode(currentAtom.identifier); | ||
ctx.clearRect(0, 0, canvas.width, canvas.height); | ||
redrawCut(tree.sheet); | ||
} | ||
} | ||
|
||
/** | ||
* Draws the given atomNode with the given color. | ||
* @param thisAtom the atomnode to be drawn. | ||
* @param color the color of the atom. | ||
*/ | ||
function drawAtom(thisAtom: AtomNode, color: string) { | ||
ctx.fillStyle = color; | ||
ctx.strokeStyle = color; | ||
const displayBox = thisAtom.rect; | ||
ctx.beginPath(); | ||
ctx.fillText(thisAtom.identifier, thisAtom.origin.x, thisAtom.origin.y); | ||
ctx.rect( | ||
displayBox.startVertex.x, | ||
displayBox.startVertex.y, | ||
displayBox.width, | ||
displayBox.height | ||
); | ||
ctx.stroke(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import {Point} from "./AEG/Point"; | ||
import {CutNode} from "./AEG/CutNode"; | ||
import {Ellipse} from "./AEG/Ellipse"; | ||
import {redrawCut} from "./index"; | ||
import {tree} from "./index"; | ||
|
||
const canvas: HTMLCanvasElement = <HTMLCanvasElement>document.getElementById("canvas"); | ||
const res: CanvasRenderingContext2D | null = canvas.getContext("2d"); | ||
const showRectElm: HTMLInputElement = <HTMLInputElement>document.getElementById("showRect"); | ||
const modeElm: HTMLSelectElement = <HTMLSelectElement>document.getElementById("mode"); | ||
if (res === null) { | ||
throw Error("2d rendering context not supported"); | ||
} | ||
const ctx: CanvasRenderingContext2D = res; | ||
|
||
let hasMouseDown: Boolean = false; | ||
let currentEllipse: Ellipse = new Ellipse(); | ||
let startingPoint: Point = new Point(); | ||
|
||
/** | ||
* Will compare the event given with all possible events it could be. | ||
* mousedown events will allocate the starting point and allow the later events to take place | ||
* mousemove will call createEllipse starting and current points, if invalid place will color it. | ||
* mouseup will add the cut to the tree if it is in a valid place, and set hasmousedown to false. | ||
* mosueout will end drawing early. | ||
* @param event The event that will be used | ||
*/ | ||
export function cutHandler(event: MouseEvent) { | ||
let newCut: CutNode = new CutNode(); | ||
const currentPoint: Point = new Point(); | ||
|
||
if (event.type === "mousedown") { | ||
hasMouseDown = true; | ||
startingPoint.x = event.clientX; | ||
startingPoint.y = event.clientY; | ||
} else if (event.type === "mousemove" && hasMouseDown) { | ||
currentPoint.x = event.clientX; | ||
currentPoint.y = event.clientY; | ||
ctx.clearRect(0, 0, canvas.width, canvas.height); | ||
redrawCut(tree.sheet); | ||
currentEllipse = createEllipse(startingPoint, currentPoint); | ||
newCut.ellipse = currentEllipse; | ||
|
||
if (tree.canInsert(newCut) && currentEllipse.radiusX > 15 && currentEllipse.radiusY > 15) { | ||
drawEllipse(newCut, "#00FF00"); | ||
} else { | ||
drawEllipse(newCut, "#FF0000"); | ||
} | ||
} else if (event.type === "mouseup" && hasMouseDown) { | ||
newCut = new CutNode(currentEllipse); | ||
if (tree.canInsert(newCut) && currentEllipse.radiusX > 15 && currentEllipse.radiusY > 15) { | ||
tree.insert(newCut); | ||
} | ||
hasMouseDown = false; | ||
startingPoint = new Point(); | ||
ctx.clearRect(0, 0, canvas.width, canvas.height); | ||
redrawCut(tree.sheet); | ||
console.log(tree.toString()); | ||
} else if (event.type === "mouseout" && hasMouseDown) { | ||
hasMouseDown = false; | ||
startingPoint = new Point(); | ||
ctx.clearRect(0, 0, canvas.width, canvas.height); | ||
redrawCut(tree.sheet); | ||
} | ||
} | ||
|
||
/** | ||
* A function to draw an ellipse between two points designated by the user. | ||
* @param original the point where the user originally clicked | ||
* @param current the point where the user's mouse is currently located | ||
*/ | ||
export function createEllipse(original: Point, current: Point): Ellipse { | ||
const center: Point = new Point( | ||
(current.x - original.x) / 2 + original.x, | ||
(current.y - original.y) / 2 + original.y | ||
); | ||
|
||
const sdx = original.x - current.x; | ||
const sdy = original.y - current.y; | ||
const dx = Math.abs(sdx); | ||
const dy = Math.abs(sdy); | ||
let rx, ry: number; | ||
|
||
if (modeElm.value === "circumscribed") { | ||
//This inscribed ellipse solution is inspired by the discussion of radius ratios in | ||
//https://stackoverflow.com/a/433426/6342516 | ||
const rv: number = Math.floor(center.distance(current)); | ||
ry = Math.floor(rv * (dy / dx)); | ||
rx = Math.floor(rv * (dx / dy)); | ||
} else { | ||
rx = dx / 2; | ||
ry = dy / 2; | ||
} | ||
|
||
if (showRectElm.checked) { | ||
ctx.beginPath(); | ||
ctx.rect(original.x, original.y, -sdx, -sdy); | ||
ctx.stroke(); | ||
} | ||
|
||
return new Ellipse(center, rx, ry); | ||
} | ||
|
||
/** | ||
* Draws the given cut onto the canvas. | ||
* @param thisCut The cut containing the ellipse to be drawn | ||
* @param color the line color of the ellipse | ||
*/ | ||
function drawEllipse(thisCut: CutNode, color: string) { | ||
ctx.strokeStyle = color; | ||
const ellipse: Ellipse = <Ellipse>thisCut.ellipse; | ||
const center: Point = ellipse.center; | ||
ctx.beginPath(); | ||
ctx.ellipse(center.x, center.y, ellipse.radiusX, ellipse.radiusY, 0, 0, 2 * Math.PI); | ||
ctx.stroke(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters