fork 自 sduonline/sc-resources
增加淘宝群内容,修改部分文件组织
此提交包含在:
@@ -0,0 +1,309 @@
|
||||
// Copyright 2011 David Galles, University of San Francisco. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||
// provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// The views and conclusions contained in the software and documentation are those of the
|
||||
// authors and should not be interpreted as representing official policies, either expressed
|
||||
// or implied, of the University of San Francisco
|
||||
|
||||
|
||||
function AnimatedBTreeNode(id, widthPerElem, h, numElems, fillColor, edgeColor)
|
||||
{
|
||||
fillColor = (fillColor == undefined)? "#FFFFFF" : fillColor;
|
||||
edgeColor = (edgeColor == undefined)? "#000000" : edgeColor;
|
||||
this.init(id, widthPerElem, h, numElems, fillColor, edgeColor);
|
||||
}
|
||||
|
||||
AnimatedBTreeNode.prototype = new AnimatedObject();
|
||||
AnimatedBTreeNode.prototype.constructor = AnimatedBTreeNode;
|
||||
AnimatedBTreeNode.superclass = AnimatedObject.prototype;
|
||||
|
||||
AnimatedBTreeNode.MIN_WIDTH = 10;
|
||||
AnimatedBTreeNode.EDGE_POINTER_DISPLACEMENT = 5;
|
||||
|
||||
|
||||
AnimatedBTreeNode.prototype.init = function(id, widthPerElem, h, numElems, fillColor, edgeColor)
|
||||
{
|
||||
|
||||
var MIN_WIDTH = 10;
|
||||
AnimatedBTreeNode.superclass.init.call(this);
|
||||
this.objectID = id;
|
||||
|
||||
|
||||
this.backgroundColor = fillColor;
|
||||
this.foregroundColor = edgeColor;
|
||||
|
||||
this.widthPerElement = widthPerElem;
|
||||
this.nodeHeight = h;
|
||||
this.numLabels = numElems;
|
||||
this.labels = new Array(this.numLabels);
|
||||
this.labelColors = new Array(this.numLabels);
|
||||
for (var i = 0; i < this.numLabels; i++)
|
||||
{
|
||||
this.labelColors[i] = this.foregroundColor;
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedBTreeNode.prototype.getNumElements = function()
|
||||
{
|
||||
return this.numLabels;
|
||||
}
|
||||
|
||||
AnimatedBTreeNode.prototype.getWidth = function()
|
||||
{
|
||||
if (this.numLabels > 0)
|
||||
{
|
||||
return (this.widthPerElement * this.numLabels);
|
||||
}
|
||||
else
|
||||
{
|
||||
return AnimatedBTreeNode.MIN_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedBTreeNode.prototype.setNumElements = function(newNumElements)
|
||||
{
|
||||
var i;
|
||||
if (this.numLabels < newNumElements)
|
||||
{
|
||||
for (i = this.numLabels; i < newNumElements; i++)
|
||||
{
|
||||
this.labels[i] = "";
|
||||
this.labelColors[i] = this.foregroundColor;
|
||||
}
|
||||
this.numLabels = newNumElements;
|
||||
}
|
||||
else if (this.numLabels > newNumElements)
|
||||
{
|
||||
for (i = newNumElements; i < this.numLabels; i++)
|
||||
{
|
||||
this.labels[i] = null;
|
||||
}
|
||||
this.numLabels = newNumElements;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedBTreeNode.prototype.left = function()
|
||||
{
|
||||
return this.x - this.getWidth() / 2.0;
|
||||
}
|
||||
|
||||
AnimatedBTreeNode.prototype.right = function()
|
||||
{
|
||||
return this.x + this.getWidth() / 2.0;
|
||||
}
|
||||
|
||||
AnimatedBTreeNode.prototype.top = function()
|
||||
{
|
||||
return this.y - this.nodeHeight / 2.0;
|
||||
}
|
||||
|
||||
AnimatedBTreeNode.prototype.bottom = function()
|
||||
{
|
||||
return this.y + this.nodeHeight / 2.0;
|
||||
}
|
||||
|
||||
|
||||
AnimatedBTreeNode.prototype.draw = function(context)
|
||||
{
|
||||
var startX;
|
||||
var startY;
|
||||
|
||||
startX = this.left();
|
||||
if (startX == NaN)
|
||||
{
|
||||
startX = 0;
|
||||
}
|
||||
startY = this.top();
|
||||
|
||||
if (this.highlighted)
|
||||
{
|
||||
context.strokeStyle = "#ff0000";
|
||||
context.fillStyle = "#ff0000";
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(startX - this.highlightDiff,startY- this.highlightDiff);
|
||||
context.lineTo(startX+this.getWidth() + this.highlightDiff,startY- this.highlightDiff);
|
||||
context.lineTo(startX+this.getWidth() + this.highlightDiff,startY+this.nodeHeight + this.highlightDiff);
|
||||
context.lineTo(startX - this.highlightDiff,startY+this.nodeHeight + this.highlightDiff);
|
||||
context.lineTo(startX - this.highlightDiff,startY - this.highlightDiff);
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
context.fill();
|
||||
}
|
||||
|
||||
context.strokeStyle = this.foregroundColor;
|
||||
context.fillStyle = this.backgroundColor;
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(startX ,startY);
|
||||
context.lineTo(startX + this.getWidth(), startY);
|
||||
context.lineTo(startX + this.getWidth(), startY + this.nodeHeight);
|
||||
context.lineTo(startX, startY + this.nodeHeight);
|
||||
context.lineTo(startX, startY);
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
context.fill();
|
||||
|
||||
context.textAlign = 'center';
|
||||
context.textBaseline = 'middle';
|
||||
|
||||
|
||||
for (var i = 0; i < this.numLabels; i++)
|
||||
{
|
||||
var labelx = this.x - this.widthPerElement * this.numLabels / 2 + this.widthPerElement / 2 + i * this.widthPerElement;
|
||||
var labely = this.y
|
||||
|
||||
context.fillStyle = this.labelColors[i];
|
||||
context.fillText(this.labels[i], labelx, labely);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
AnimatedBTreeNode.prototype.getHeight = function()
|
||||
{
|
||||
return this.nodeHeight;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AnimatedBTreeNode.prototype.setForegroundColor = function(newColor)
|
||||
{
|
||||
this.foregroundColor = newColor;
|
||||
for (var i = 0; i < numLabels; i++)
|
||||
{
|
||||
labelColor[i] = newColor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: Kill the magic numbers here
|
||||
AnimatedBTreeNode.prototype.getTailPointerAttachPos = function(fromX, fromY, anchor)
|
||||
{
|
||||
if (anchor == 0)
|
||||
{
|
||||
return [this.left() + AnimatedBTreeNode.EDGE_POINTER_DISPLACEMENT, this.y + this.nodeHeight * 0.5];
|
||||
}
|
||||
else if (anchor == this.numLabels)
|
||||
{
|
||||
return [this.right() - AnimatedBTreeNode.EDGE_POINTER_DISPLACEMENT, this.y + this.nodeHeight * 0.5];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [this.left() + anchor * this.widthPerElement, this.y + this.nodeHeight * 0.5]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedBTreeNode.prototype.getHeadPointerAttachPos = function(fromX, fromY)
|
||||
{
|
||||
if (fromY < this.y - this.nodeHeight / 2)
|
||||
{
|
||||
return [this.x, this.y - this.nodeHeight / 2];
|
||||
}
|
||||
else if (this.fromY > this.y + this.nodeHeight / 2)
|
||||
{
|
||||
return [this.x, this.y + this.nodeHeight / 2];
|
||||
}
|
||||
else if (fromX < this.x - this.getWidth() / 2)
|
||||
{
|
||||
return [this.x - this.getWidth() / 2, this.y];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [this.x + this.getWidth() / 2, this.y];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
AnimatedBTreeNode.prototype.createUndoDelete = function()
|
||||
{
|
||||
return new UndoDeleteBTreeNode(this.objectID, this.numLabels, this.labels, this.x, this.y, this.widthPerElement, this.nodeHeight, this.labelColors, this.backgroundColor, this.foregroundColor, this.layer, this.highlighted);
|
||||
}
|
||||
|
||||
|
||||
AnimatedBTreeNode.prototype.getTextColor = function(textIndex)
|
||||
{
|
||||
textIndex = (textIndex == undefined) ? 0 : textIndex;
|
||||
return this.labelColors[textIndex];
|
||||
}
|
||||
|
||||
AnimatedBTreeNode.prototype.getText = function(index)
|
||||
{
|
||||
index = (index == undefined) ? 0 : index;
|
||||
return this.labels[index];
|
||||
}
|
||||
|
||||
AnimatedBTreeNode.prototype.setTextColor = function(color, textIndex)
|
||||
{
|
||||
textIndex = (textIndex == undefined) ? 0 : textIndex;
|
||||
this.labelColors[textIndex] = color;
|
||||
}
|
||||
|
||||
|
||||
AnimatedBTreeNode.prototype.setText = function(newText, textIndex)
|
||||
{
|
||||
textIndex = (textIndex == undefined) ? 0 : textIndex;
|
||||
this.labels[textIndex] = newText;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function UndoDeleteBTreeNode(id, numLab, labelText, x, y, wPerElement, nHeight, lColors, bgColor, fgColor, l, highlighted)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.posX = x;
|
||||
this.posY = y;
|
||||
this.widthPerElem = wPerElement;
|
||||
this.nodeHeight = nHeight;
|
||||
this.backgroundColor= bgColor;
|
||||
this.foregroundColor = fgColor;
|
||||
this.numElems = numLab;
|
||||
this.labels = labelText;
|
||||
|
||||
this.labelColors = lColors;
|
||||
this.layer = l;
|
||||
this.highlighted = highlighted;
|
||||
}
|
||||
|
||||
UndoDeleteBTreeNode.prototype = new UndoBlock();
|
||||
UndoDeleteBTreeNode.prototype.constructor = UndoDeleteBTreeNode;
|
||||
|
||||
UndoDeleteBTreeNode.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
|
||||
world.addBTreeNode(this.objectID, this.widthPerElem, this.nodeHeight, this.numElems, this.backgroundColor, this.foregroundColor);
|
||||
world.setNodePosition(this.objectID, this.posX, this.posY);
|
||||
for (var i = 0; i < this.numElems; i++)
|
||||
{
|
||||
world.setText(this.objectID, this.labels[i], i);
|
||||
world.setTextColor(this.objectID, this.labelColors[i],i);
|
||||
}
|
||||
world.setHighlight(this.objectID, this.highlighted);
|
||||
world.setLayer(this.objectID, this.layer);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -0,0 +1,210 @@
|
||||
// Copyright 2011 David Galles, University of San Francisco. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||
// provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// The views and conclusions contained in the software and documentation are those of the
|
||||
// authors and should not be interpreted as representing official policies, either expressed
|
||||
// or implied, of the University of San Francisco
|
||||
|
||||
|
||||
var AnimatedCircle = function(objectID, objectLabel)
|
||||
{
|
||||
this.objectID = objectID;
|
||||
this.label = objectLabel;
|
||||
this.radius = 20;
|
||||
this.thickness = 3;
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
this.alpha = 1.0;
|
||||
this.addedToScene = true;
|
||||
this.highlightIndex = -1;
|
||||
/* this.foregroundColor = '#007700';
|
||||
this.backgroundColor = '#EEFFEE';
|
||||
*/
|
||||
}
|
||||
|
||||
AnimatedCircle.prototype = new AnimatedObject();
|
||||
AnimatedCircle.prototype.constructor = AnimatedCircle;
|
||||
|
||||
AnimatedCircle.prototype.getTailPointerAttachPos = function(fromX, fromY, anchorPoint)
|
||||
{
|
||||
return this.getHeadPointerAttachPos(fromX, fromY);
|
||||
}
|
||||
|
||||
|
||||
AnimatedCircle.prototype.getWidth = function()
|
||||
{
|
||||
return this.radius * 2;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.setWidth = function(newWidth)
|
||||
{
|
||||
this.radius = newWidth / 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AnimatedCircle.prototype.getHeadPointerAttachPos = function(fromX, fromY)
|
||||
{
|
||||
var xVec = fromX - this.x;
|
||||
var yVec = fromY - this.y;
|
||||
var len = Math.sqrt(xVec * xVec + yVec*yVec);
|
||||
if (len == 0)
|
||||
{
|
||||
return [this.x, this.y];
|
||||
}
|
||||
return [this.x+(xVec/len)*(this.radius), this.y +(yVec/len)*(this.radius)];
|
||||
}
|
||||
|
||||
|
||||
AnimatedCircle.prototype.setHighlightIndex = function(hlIndex)
|
||||
{
|
||||
this.highlightIndex = hlIndex;
|
||||
this.highlightIndexDirty = true;
|
||||
|
||||
}
|
||||
|
||||
AnimatedCircle.prototype.draw = function(ctx)
|
||||
{
|
||||
ctx.globalAlpha = this.alpha;
|
||||
|
||||
if (this.highlighted)
|
||||
{
|
||||
ctx.fillStyle = "#ff0000";
|
||||
ctx.beginPath();
|
||||
ctx.arc(this.x,this.y,this.radius + this.highlightDiff,0,Math.PI*2, true);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
|
||||
ctx.fillStyle = this.backgroundColor;
|
||||
ctx.strokeStyle = this.foregroundColor;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.beginPath();
|
||||
ctx.arc(this.x,this.y,this.radius,0,Math.PI*2, true);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
ctx.textAlign = 'center';
|
||||
ctx.font = '16px Consolas';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.fillStyle = this.foregroundColor;
|
||||
|
||||
var strList = this.label.split("\n");
|
||||
if (strList.length == 1)
|
||||
{
|
||||
if (this.highlightIndexDirty && this.highlightIndex != -1)
|
||||
{
|
||||
this.leftWidth = ctx.measureText(this.label.substring(0,this.highlightIndex)).width;
|
||||
this.centerWidth = ctx.measureText(this.label.substring(this.highlightIndex, this.highlightIndex+1)).width;
|
||||
this.textWidth = ctx.measureText(this.label).width;
|
||||
this.highlightIndexDirty = false;
|
||||
}
|
||||
if (this.highlightIndex != -1 && this.highlightIndex < this.label.length) //this.highlghtIndex < this.label.length)
|
||||
{
|
||||
var startingXForHighlight = this.x - this.textWidth / 2;
|
||||
ctx.textAlign = 'left';
|
||||
var leftStr = this.label.substring(0, this.highlightIndex);
|
||||
var highlightStr = this.label.substring(this.highlightIndex, this.highlightIndex + 1)
|
||||
var rightStr = this.label.substring(this.highlightIndex + 1)
|
||||
ctx.fillText(leftStr, startingXForHighlight, this.y)
|
||||
ctx.strokeStyle = "#FF0000";
|
||||
ctx.fillStyle = "#FF0000";
|
||||
ctx.fillText(highlightStr, startingXForHighlight + this.leftWidth, this.y)
|
||||
|
||||
|
||||
ctx.strokeStyle = this.labelColor;
|
||||
ctx.fillStyle = this.labelColor;
|
||||
ctx.fillText(rightStr, startingXForHighlight + this.leftWidth + this.centerWidth, this.y)
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.fillText(this.label, this.x, this.y);
|
||||
}
|
||||
}
|
||||
else if (strList.length % 2 == 0)
|
||||
{
|
||||
var i;
|
||||
var mid = strList.length / 2;
|
||||
for (i = 0; i < strList.length / 2; i++)
|
||||
{
|
||||
ctx.fillText(strList[mid - i - 1], this.x, this.y - (i + 0.5) * 12);
|
||||
ctx.fillText(strList[mid + i], this.x, this.y + (i + 0.5) * 12);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var mid = (strList.length - 1) / 2;
|
||||
var i;
|
||||
ctx.fillText(strList[mid], this.x, this.y);
|
||||
for (i = 0; i < mid; i++)
|
||||
{
|
||||
ctx.fillText(strList[mid - (i + 1)], this.x, this.y - (i + 1) * 12);
|
||||
ctx.fillText(strList[mid + (i + 1)], this.x, this.y + (i + 1) * 12);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
AnimatedCircle.prototype.createUndoDelete = function()
|
||||
{
|
||||
return new UndoDeleteCircle(this.objectID, this.label, this.x, this.y, this.foregroundColor, this.backgroundColor, this.layer, this.radius);
|
||||
}
|
||||
|
||||
|
||||
function UndoDeleteCircle(id, lab, x, y, foregroundColor, backgroundColor, l, radius)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.posX = x;
|
||||
this.posY = y;
|
||||
this.nodeLabel = lab;
|
||||
this.fgColor = foregroundColor;
|
||||
this.bgColor = backgroundColor;
|
||||
this.layer = l;
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
UndoDeleteCircle.prototype = new UndoBlock();
|
||||
UndoDeleteCircle.prototype.constructor = UndoDeleteCircle;
|
||||
|
||||
UndoDeleteCircle.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.addCircleObject(this.objectID, this.nodeLabel);
|
||||
world.setWidth(this.objectID, this.radius * 2);
|
||||
world.setNodePosition(this.objectID, this.posX, this.posY);
|
||||
world.setForegroundColor(this.objectID, this.fgColor);
|
||||
world.setBackgroundColor(this.objectID, this.bgColor);
|
||||
world.setLayer(this.objectID, this.layer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@@ -0,0 +1,420 @@
|
||||
// Copyright 2011 David Galles, University of San Francisco. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||
// provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// The views and conclusions contained in the software and documentation are those of the
|
||||
// authors and should not be interpreted as representing official policies, either expressed
|
||||
// or implied, of the University of San Francisco
|
||||
|
||||
function AnimatedLabel(id, val, center, initialWidth)
|
||||
{
|
||||
this.centering = center;
|
||||
this.label = val;
|
||||
this.highlighted = false;
|
||||
this.objectID = id;
|
||||
this.alpha = 1.0;
|
||||
this.addedToScene = true;
|
||||
this.labelColor = "#000000";
|
||||
this.textWidth = 0;
|
||||
if (initialWidth != undefined)
|
||||
{
|
||||
this.textWidth = initialWidth;
|
||||
}
|
||||
|
||||
this.leftWidth = -1;
|
||||
this.centerWidth = -1;
|
||||
this.highlightIndex = -1;
|
||||
}
|
||||
|
||||
AnimatedLabel.prototype = new AnimatedObject();
|
||||
AnimatedLabel.prototype.constructor = AnimatedLabel;
|
||||
|
||||
AnimatedLabel.prototype.alwaysOnTop = true;
|
||||
|
||||
|
||||
AnimatedLabel.prototype.centered = function()
|
||||
{
|
||||
return this.centering;
|
||||
}
|
||||
|
||||
|
||||
AnimatedLabel.prototype.draw = function(ctx)
|
||||
{
|
||||
if (!this.addedToScene)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.globalAlpha = this.alpha;
|
||||
ctx.font = '16px Consolas';
|
||||
|
||||
var startingXForHighlight = this.x;
|
||||
|
||||
if (this.highlightIndex >= this.label.length)
|
||||
{
|
||||
this.highlightIndex = -1;
|
||||
}
|
||||
if (this.highlightIndexDirty && this.highlightIndex != -1)
|
||||
{
|
||||
this.leftWidth = ctx.measureText(this.label.substring(0,this.highlightIndex)).width;
|
||||
this.centerWidth = ctx.measureText(this.label.substring(this.highlightIndex, this.highlightIndex+1)).width;
|
||||
this.highlightIndexDirty = false;
|
||||
}
|
||||
|
||||
if (this.centering)
|
||||
{
|
||||
if (this.highlightIndex != -1)
|
||||
{
|
||||
startingXForHighlight = this.x - this.width / 2;
|
||||
ctx.textAlign = 'left';
|
||||
ctx.textBaseline = 'middle';
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.textAlign = 'left';
|
||||
ctx.textBaseline = 'top';
|
||||
}
|
||||
if (this.highlighted)
|
||||
{
|
||||
ctx.strokeStyle = "#ffaaaa";
|
||||
ctx.fillStyle = "#ff0000";
|
||||
ctx.lineWidth = this.highlightDiff;
|
||||
ctx.strokeText(this.label, this.x, this.y);
|
||||
//ctx.fillText(this.label, this.x, this.y);
|
||||
}
|
||||
ctx.strokeStyle = this.labelColor;
|
||||
ctx.fillStyle = this.labelColor;
|
||||
ctx.lineWidth = 1;
|
||||
strList = this.label.split("\n");
|
||||
if (strList.length == 1)
|
||||
{
|
||||
if (this.highlightIndex == -1)
|
||||
{
|
||||
ctx.fillText(this.label, this.x, this.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
var leftStr = this.label.substring(0, this.highlightIndex);
|
||||
var highlightStr = this.label.substring(this.highlightIndex, this.highlightIndex + 1)
|
||||
var rightStr = this.label.substring(this.highlightIndex + 1)
|
||||
ctx.fillText(leftStr, startingXForHighlight, this.y)
|
||||
ctx.strokeStyle = "#FF0000";
|
||||
ctx.fillStyle = "#FF0000";
|
||||
ctx.fillText(highlightStr, startingXForHighlight + this.leftWidth, this.y)
|
||||
|
||||
|
||||
ctx.strokeStyle = this.labelColor;
|
||||
ctx.fillStyle = this.labelColor;
|
||||
ctx.fillText(rightStr, startingXForHighlight + this.leftWidth + this.centerWidth, this.y)
|
||||
|
||||
|
||||
}
|
||||
//this.textWidth = ctx.measureText(this.label).width;
|
||||
}
|
||||
else
|
||||
{
|
||||
var offset = (this.centering)? (1.0 - strList.length) / 2.0 : 0;
|
||||
for (var i = 0; i < strList.length; i++)
|
||||
{
|
||||
ctx.fillText(strList[i], this.x, this.y + offset + i * 12);
|
||||
//this.textWidth = Math.max(this.textWidth, ctx.measureText(strList[i]).width);
|
||||
}
|
||||
}
|
||||
ctx.closePath();
|
||||
}
|
||||
|
||||
|
||||
AnimatedLabel.prototype.getAlignLeftPos = function(otherObject)
|
||||
{
|
||||
if (this.centering)
|
||||
{
|
||||
return [otherObject.left() - this.textWidth / 2, this.y = otherObject.centerY()];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [otherObject.left() - this.textWidth, otherObject.centerY() - 5];
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedLabel.prototype.alignLeft = function(otherObject)
|
||||
{
|
||||
if (this.centering)
|
||||
{
|
||||
this.y = otherObject.centerY();
|
||||
this.x = otherObject.left() - this.textWidth / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.y = otherObject.centerY() - 5;
|
||||
this.x = otherObject.left() - this.textWidth;
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedLabel.prototype.alignRight = function(otherObject)
|
||||
{
|
||||
if (this.centering)
|
||||
{
|
||||
this.y = otherObject.centerY();
|
||||
this.x = otherObject.right() + this.textWidth / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.y = otherObject.centerY() - 5;
|
||||
this.x = otherObject.right();
|
||||
}
|
||||
}
|
||||
AnimatedLabel.prototype.getAlignRightPos = function(otherObject)
|
||||
{
|
||||
if (this.centering)
|
||||
{
|
||||
return [otherObject.right() + this.textWidth / 2, otherObject.centerY()];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [otherObject.right(), otherObject.centerY() - 5];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedLabel.prototype.alignTop = function(otherObject)
|
||||
{
|
||||
if (this.centering)
|
||||
{
|
||||
this.y = otherObject.top() - 5;
|
||||
this.x = otherObject.centerX();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.y = otherObject.top() - 10;
|
||||
this.x = otherObject.centerX() -this.textWidth / 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedLabel.prototype.getAlignTopPos = function(otherObject)
|
||||
{
|
||||
if (this.centering)
|
||||
{
|
||||
return [otherObject.centerX(), otherObject.top() - 5];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [otherObject.centerX() -this.textWidth / 2, otherObject.top() - 10];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedLabel.prototype.alignBottom = function(otherObject)
|
||||
{
|
||||
if (this.centering)
|
||||
{
|
||||
this.y = otherObject.bottom() + 5;
|
||||
this.x = otherObject.centerX();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.y = otherObject.bottom();
|
||||
this.x = otherObject.centerX() - this.textWidth / 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedLabel.prototype.getAlignBottomPos = function(otherObject)
|
||||
{
|
||||
if (this.centering)
|
||||
{
|
||||
return [otherObject.centerX(), otherObject.bottom() + 5];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [otherObject.centerX() - this.textWidth / 2, otherObject.bottom()];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
AnimatedLabel.prototype.getWidth = function()
|
||||
{
|
||||
return this.textWidth;
|
||||
}
|
||||
|
||||
AnimatedLabel.prototype.getHeight = function()
|
||||
{
|
||||
return 10; // HACK! HACK! HACK! HACK!
|
||||
}
|
||||
|
||||
|
||||
AnimatedLabel.prototype.setHighlight = function(value)
|
||||
{
|
||||
this.highlighted = value;
|
||||
}
|
||||
|
||||
AnimatedLabel.prototype.createUndoDelete = function()
|
||||
{
|
||||
return new UndoDeleteLabel(this.objectID, this.label, this.x, this.y, this.centering, this.labelColor, this.layer, this.highlightIndex);
|
||||
}
|
||||
|
||||
|
||||
AnimatedLabel.prototype.centerX = function()
|
||||
{
|
||||
if (this.centering)
|
||||
{
|
||||
return this.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.x + this.textWidth;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AnimatedLabel.prototype.centerY = function()
|
||||
{
|
||||
if (this.centering)
|
||||
{
|
||||
return this.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.y + 5; //
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AnimatedLabel.prototype.top = function()
|
||||
{
|
||||
if (this.centering)
|
||||
{
|
||||
return this.y - 5; //TODO: Un-Hardwire
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedLabel.prototype.bottom = function()
|
||||
{
|
||||
if (this.centering)
|
||||
{
|
||||
return this.y + 5; // TODO: + height / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.y + 10; // TODO: + hieght;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedLabel.prototype.right = function()
|
||||
{
|
||||
if (this.centering)
|
||||
{
|
||||
return this.x + this.textWidth / 2; // TODO: + width / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.x + this.textWidth; // TODO: + width;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedLabel.prototype.left = function()
|
||||
{
|
||||
if (this.centering)
|
||||
{
|
||||
return this. x - this.textWidth / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.x; // TODO: - a little?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedLabel.prototype.setHighlightIndex = function(hlIndex)
|
||||
{
|
||||
// Only allow highlight index for labels that don't have End-Of-Line
|
||||
if (this.label.indexOf("\n") == -1 && this.label.length > hlIndex)
|
||||
{
|
||||
this.highlightIndex = hlIndex;
|
||||
this.highlightIndexDirty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.highlightIndex = -1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedLabel.prototype.getTailPointerAttachPos = function(fromX, fromY, anchorPoint)
|
||||
{
|
||||
return this.getClosestCardinalPoint(fromX, fromY);
|
||||
}
|
||||
|
||||
AnimatedLabel.prototype.getHeadPointerAttachPos = function (fromX, fromY)
|
||||
{
|
||||
return this.getClosestCardinalPoint(fromX, fromY);
|
||||
}
|
||||
|
||||
AnimatedLabel.prototype.setText = function(newText, textIndex, initialWidth)
|
||||
{
|
||||
this.label = newText;
|
||||
if (initialWidth != undefined)
|
||||
{
|
||||
this.textWidth = initialWidth;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function UndoDeleteLabel(id, lab, x, y, centered, color, l, hli)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.posX = x;
|
||||
this.posY = y;
|
||||
this.nodeLabel = lab;
|
||||
this.labCentered = centered;
|
||||
this.labelColor = color;
|
||||
this.layer = l;
|
||||
this.highlightIndex = hli;
|
||||
this.dirty = true;
|
||||
}
|
||||
|
||||
UndoDeleteLabel.prototype = new UndoBlock();
|
||||
UndoDeleteLabel.prototype.constructor = UndoDeleteLabel;
|
||||
|
||||
UndoDeleteLabel.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.addLabelObject(this.objectID, this.nodeLabel, this.labCentered);
|
||||
world.setNodePosition(this.objectID, this.posX, this.posY);
|
||||
world.setForegroundColor(this.objectID, this.labelColor);
|
||||
world.setLayer(this.objectID, this.layer);
|
||||
}
|
||||
|
@@ -0,0 +1,473 @@
|
||||
// Copyright 2011 David Galles, University of San Francisco. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||
// provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// The views and conclusions contained in the software and documentation are those of the
|
||||
// authors and should not be interpreted as representing official policies, either expressed
|
||||
// or implied, of the University of San Francisco
|
||||
|
||||
function AnimatedLinkedList(id, val, wth, hgt, linkPer, verticalOrientation, linkPosEnd, numLab, fillColor, edgeColor)
|
||||
{
|
||||
this.init(id, val, wth, hgt, linkPer, verticalOrientation, linkPosEnd, numLab, fillColor, edgeColor);
|
||||
}
|
||||
|
||||
AnimatedLinkedList.prototype = new AnimatedObject();
|
||||
AnimatedLinkedList.prototype.constructor = AnimatedLinkedList;
|
||||
AnimatedLinkedList.superclass = AnimatedObject.prototype;
|
||||
|
||||
|
||||
AnimatedLinkedList.prototype.init = function(id, val, wth, hgt, linkPer, verticalOrientation, linkPosEnd, numLab, fillColor, edgeColor)
|
||||
{
|
||||
|
||||
AnimatedLinkedList.superclass.init.call(this);
|
||||
|
||||
this.w = wth;
|
||||
this.h = hgt;
|
||||
this.backgroundColor = fillColor;
|
||||
this.foregroundColor = edgeColor;
|
||||
|
||||
this.vertical = verticalOrientation;
|
||||
this.linkPositionEnd = linkPosEnd;
|
||||
this.linkPercent = linkPer;
|
||||
|
||||
this.numLabels = numLab;
|
||||
|
||||
this.labels = [];
|
||||
this.labelPosX = [];
|
||||
this.labelPosY = [];
|
||||
this.labelColors = [];
|
||||
this.nullPointer = false;
|
||||
|
||||
this.currentHeightDif = 6;
|
||||
this.maxHeightDiff = 5;
|
||||
this.minHeightDiff = 3;
|
||||
|
||||
|
||||
|
||||
for (var i = 0; i < this.numLabels; i++)
|
||||
{
|
||||
this.labels[i] = "";
|
||||
this.labelPosX[i] = 0;
|
||||
this.labelPosY[i] = 0;
|
||||
this.labelColors[i] = this.foregroundColor;
|
||||
}
|
||||
|
||||
this.labels[0] = val;
|
||||
this.highlighted = false;
|
||||
this.objectID = id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AnimatedLinkedList.prototype.left = function()
|
||||
{
|
||||
if (this.vertical)
|
||||
{
|
||||
return this.x - this.w / 2.0;
|
||||
}
|
||||
else if (this.linkPositionEnd)
|
||||
{
|
||||
return this.x - ((this.w * (1 - this.linkPercent)) / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.x - (this.w * (this.linkPercent + 1)) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedLinkedList.prototype.setNull = function(np)
|
||||
{
|
||||
if (this.nullPointer != np)
|
||||
{
|
||||
this.nullPointer = np;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AnimatedLinkedList.prototype.getNull = function()
|
||||
{
|
||||
return this.nullPointer;
|
||||
}
|
||||
|
||||
AnimatedLinkedList.prototype.right = function()
|
||||
{
|
||||
if (this.vertical)
|
||||
{
|
||||
return this.x + this.w / 2.0;
|
||||
}
|
||||
else if (this.linkPositionEnd)
|
||||
{
|
||||
return this.x + ((this.w * (this.linkPercent + 1)) / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.x + (this.w * (1 - this.linkPercent)) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedLinkedList.prototype.top = function()
|
||||
{
|
||||
if (!this.vertical)
|
||||
{
|
||||
return this.y - this.h / 2.0;
|
||||
}
|
||||
else if (this.linkPositionEnd)
|
||||
{
|
||||
return this.y - (this.h * (1 -this.linkPercent)) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.y - (this.h * (1 + this.linkPercent)) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedLinkedList.prototype.bottom = function()
|
||||
{
|
||||
if (!this.vertical)
|
||||
{
|
||||
return this.y + this.h / 2.0;
|
||||
}
|
||||
else if (this.linkPositionEnd)
|
||||
{
|
||||
return this.y + (this.h * (1 +this.linkPercent)) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.y + (this.h * (1 - this.linkPercent)) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: Should we move this to the draw function, and save the
|
||||
// space of the arrays? Bit of a leftover from the Flash code,
|
||||
// which did drawing differently
|
||||
AnimatedLinkedList.prototype.resetTextPosition = function()
|
||||
{
|
||||
if (this.vertical)
|
||||
{
|
||||
this.labelPosX[0] = this.x;
|
||||
|
||||
this.labelPosY[0] = this.y + this.h * (1-this.linkPercent)/2 *(1/this.numLabels - 1);
|
||||
// labelPosY[0] = -height * (1-linkPercent) / 2 + height*(1-linkPercent)/2*numLabels;
|
||||
for (var i = 1; i < this.numLabels; i++)
|
||||
{
|
||||
this.labelPosY[i] = this.labelPosY[i-1] + this.h*(1-this.linkPercent)/this.numLabels;
|
||||
this.labelPosX[i] = this.x;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.labelPosY[0] = this.y;
|
||||
this.labelPosX[0] = this.x + this.w * (1-this.linkPercent)/2*(1/this.numLabels - 1);
|
||||
for (var i = 1; i < this.numLabels; i++)
|
||||
{
|
||||
this.labelPosY[i] = this.y;
|
||||
this.labelPosX[i] = this.labelPosX[i-1] + this.w*(1-this.linkPercent)/this.numLabels;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
AnimatedLinkedList.prototype.getTailPointerAttachPos = function(fromX, fromY, anchor)
|
||||
{
|
||||
if (this.vertical && this.linkPositionEnd)
|
||||
{
|
||||
return [this.x, this.y + this.h / 2.0];
|
||||
}
|
||||
else if (this.vertical && !this.linkPositionEnd)
|
||||
{
|
||||
return [this.x, this.y - this.h / 2.0];
|
||||
}
|
||||
else if (!this.vertical && this.linkPositionEnd)
|
||||
{
|
||||
return [this.x + this.w / 2.0, this.y];
|
||||
}
|
||||
else // (!this.vertical && !this.linkPositionEnd)
|
||||
{
|
||||
return [this.x - this.w / 2.0, this.y];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedLinkedList.prototype.getHeadPointerAttachPos = function(fromX, fromY)
|
||||
{
|
||||
return this.getClosestCardinalPoint(fromX, fromY);
|
||||
}
|
||||
|
||||
|
||||
AnimatedLinkedList.prototype.setWidth = function(wdth)
|
||||
{
|
||||
this.w = wdth;
|
||||
this.resetTextPosition();
|
||||
}
|
||||
|
||||
|
||||
AnimatedLinkedList.prototype.setHeight = function(hght)
|
||||
{
|
||||
this.h = hght;
|
||||
this.resetTextPosition();
|
||||
}
|
||||
|
||||
AnimatedLinkedList.prototype.getWidth = function()
|
||||
{
|
||||
return this.w;
|
||||
}
|
||||
|
||||
AnimatedLinkedList.prototype.getHeight = function()
|
||||
{
|
||||
return this.h;
|
||||
}
|
||||
|
||||
AnimatedLinkedList.prototype.draw = function(context)
|
||||
{
|
||||
var startX;
|
||||
var startY;
|
||||
|
||||
startX = this.left();
|
||||
startY = this.top();
|
||||
|
||||
if (this.highlighted)
|
||||
{
|
||||
context.strokeStyle = "#ff0000";
|
||||
context.fillStyle = "#ff0000";
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(startX - this.highlightDiff,startY- this.highlightDiff);
|
||||
context.lineTo(startX+this.w + this.highlightDiff,startY- this.highlightDiff);
|
||||
context.lineTo(startX+this.w+ this.highlightDiff,startY+this.h + this.highlightDiff);
|
||||
context.lineTo(startX - this.highlightDiff,startY+this.h + this.highlightDiff);
|
||||
context.lineTo(startX - this.highlightDiff,startY - this.highlightDiff);
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
context.fill();
|
||||
}
|
||||
context.strokeStyle = this.foregroundColor;
|
||||
context.fillStyle = this.backgroundColor;
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(startX ,startY);
|
||||
context.lineTo(startX + this.w, startY);
|
||||
context.lineTo(startX + this.w, startY + this.h);
|
||||
context.lineTo(startX, startY + this.h);
|
||||
context.lineTo(startX, startY);
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
context.fill();
|
||||
|
||||
var i;
|
||||
if (this.vertical)
|
||||
{
|
||||
startX = this.left();
|
||||
for (i= 1; i < this.numLabels; i++)
|
||||
{
|
||||
//TODO: this doesn't look right ...
|
||||
startY = this.y + this.h*(1-this.linkPercent)*(i / this.numLabels - 1/2);
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(startX ,startY);
|
||||
context.lineTo(startX + this.w, startY);
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
startY = this.top();
|
||||
for (i = 1; i < this.numLabels; i++)
|
||||
{
|
||||
startX = this.x + this.w*(1-this.linkPercent)*(i / this.numLabels - 1/2);
|
||||
context.beginPath();
|
||||
context.moveTo(startX ,startY);
|
||||
context.lineTo(startX, startY + this.h);
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.vertical && this.linkPositionEnd)
|
||||
{
|
||||
startX = this.left();
|
||||
startY = this.bottom() - this.h * this.linkPercent;
|
||||
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(startX + this.w ,startY);
|
||||
context.lineTo(startX, startY);
|
||||
if (this.nullPointer)
|
||||
{
|
||||
context.lineTo(this.startX + this.w, this.bottom());
|
||||
}
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
}
|
||||
else if (this.vertical && !this.linkPositionEnd)
|
||||
{
|
||||
startX = this.left();
|
||||
startY = this.top() + this.h * this.linkPercent;
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(startX + this.w ,startY);
|
||||
context.lineTo(startX, startY);
|
||||
if (this.nullPointer)
|
||||
{
|
||||
context.lineTo(startX + this.w, this.top());
|
||||
}
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
|
||||
}
|
||||
else if (!this.vertical && this.linkPositionEnd)
|
||||
{
|
||||
startX = this.right() - this.w * this.linkPercent;
|
||||
startY = this.top();
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(startX, startY + this.h);
|
||||
context.lineTo(startX, startY);
|
||||
if (this.nullPointer)
|
||||
{
|
||||
context.lineTo(this.right(), startY + this.h);
|
||||
}
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
|
||||
}
|
||||
else // (!vertical && !linkPositionEnd)
|
||||
{
|
||||
startX = this.left() + this.w * this.linkPercent;
|
||||
startY = this.top() ;
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(startX, startY + this.h);
|
||||
context.lineTo(startX, startY);
|
||||
if (this.nullPointer)
|
||||
{
|
||||
context.lineTo(this.left(), startY);
|
||||
}
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
}
|
||||
|
||||
|
||||
context.textAlign = 'center';
|
||||
context.font = '16px Consolas';
|
||||
context.textBaseline = 'middle';
|
||||
context.lineWidth = 1;
|
||||
|
||||
|
||||
this.resetTextPosition();
|
||||
for (i = 0; i < this.numLabels; i++)
|
||||
{
|
||||
context.fillStyle = this.labelColors[i];
|
||||
context.fillText(this.labels[i], this.labelPosX[i], this.labelPosY[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
AnimatedLinkedList.prototype.setTextColor = function(color, textIndex)
|
||||
{
|
||||
|
||||
this.labelColors[textIndex] = color;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AnimatedLinkedList.prototype.getTextColor = function(textIndex)
|
||||
{
|
||||
return this.labelColors[textIndex];
|
||||
}
|
||||
|
||||
|
||||
|
||||
AnimatedLinkedList.prototype.getText = function(index)
|
||||
{
|
||||
return this.labels[index];
|
||||
}
|
||||
|
||||
AnimatedLinkedList.prototype.setText = function(newText, textIndex)
|
||||
{
|
||||
this.labels[textIndex] = newText;
|
||||
this.resetTextPosition();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AnimatedLinkedList.prototype.createUndoDelete = function()
|
||||
{
|
||||
return new UndoDeleteLinkedList(this.objectID, this.numLabels, this.labels, this.x, this.y, this.w, this.h, this.linkPercent,
|
||||
this.linkPositionEnd, this.vertical, this.labelColors, this.backgroundColor, this.foregroundColor,
|
||||
this.layer, this.nullPointer);
|
||||
}
|
||||
|
||||
AnimatedLinkedList.prototype.setHighlight = function(value)
|
||||
{
|
||||
if (value != this.highlighted)
|
||||
{
|
||||
this.highlighted = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function UndoDeleteLinkedList(id, numlab, lab, x, y, w, h, linkper, posEnd, vert, labColors, bgColor, fgColor, l, np)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.posX = x;
|
||||
this.posY = y;
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
this.backgroundColor= bgColor;
|
||||
this.foregroundColor = fgColor;
|
||||
this.labels = lab;
|
||||
this.linkPercent = linkper;
|
||||
this.verticalOrentation = vert;
|
||||
this.linkAtEnd = posEnd;
|
||||
this.labelColors = labColors
|
||||
this.layer = l;
|
||||
this.numLabels = numlab;
|
||||
this.nullPointer = np;
|
||||
}
|
||||
|
||||
UndoDeleteLinkedList.prototype = new UndoBlock();
|
||||
UndoDeleteLinkedList.prototype.constructor = UndoDeleteLinkedList;
|
||||
|
||||
|
||||
|
||||
UndoDeleteLinkedList.prototype.undoInitialStep =function(world)
|
||||
{
|
||||
world.addLinkedListObject(this.objectID,this.labels[0], this.width, this.height, this.linkPercent, this.verticalOrentation, this.linkAtEnd, this.numLabels, this.backgroundColor, this.foregroundColor);
|
||||
world.setNodePosition(this.objectID, this.posX, this.posY);
|
||||
world.setLayer(this.objectID, this.layer);
|
||||
world.setNull(this.objectID, this.nullPointer);
|
||||
for (var i = 0; i < this.numLabels; i++)
|
||||
{
|
||||
world.setText(this.objectID, this.labels[i], i);
|
||||
world.setTextColor(this.objectID, this.labelColors[i], i);
|
||||
}
|
||||
}
|
@@ -0,0 +1,343 @@
|
||||
// Copyright 2011 David Galles, University of San Francisco. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||
// provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// The views and conclusions contained in the software and documentation are those of the
|
||||
// authors and should not be interpreted as representing official policies, either expressed
|
||||
// or implied, of the University of San Francisco
|
||||
|
||||
function AnimatedObject()
|
||||
{
|
||||
this.init();
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.init = function()
|
||||
{
|
||||
this.backgroundColor = "#FFFFFF";
|
||||
this.foregroundColor = "#000000";
|
||||
this.highlighted = false;
|
||||
this.objectID = -1;
|
||||
this.layer = 0;
|
||||
this.addedToScene = true;
|
||||
this.label = "";
|
||||
this.labelColor = "#000000";
|
||||
this.alpha = 1.0;
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
this.minHeightDiff = 3;
|
||||
this.range = 5;
|
||||
this.highlightIndex = -1;
|
||||
this.highlightIndexDirty = true;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.alwaysOnTop = false;
|
||||
|
||||
AnimatedObject.prototype.setBackgroundColor = function(newColor)
|
||||
{
|
||||
this.backgroundColor = newColor;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.setForegroundColor = function(newColor)
|
||||
{
|
||||
this.foregroundColor = newColor;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.setNull = function()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.getNull = function()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.setAlpha = function(newAlpha)
|
||||
{
|
||||
this.alpha = newAlpha;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.getAlpha = function()
|
||||
{
|
||||
return this.alpha;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.setForegroundColor = function(newColor)
|
||||
{
|
||||
this.foregroundColor = newColor;
|
||||
this.labelColor = newColor;
|
||||
}
|
||||
|
||||
|
||||
AnimatedObject.prototype.getHighlight = function()
|
||||
{
|
||||
return this.highlighted;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.getWidth = function()
|
||||
{
|
||||
// TODO: Do we want to throw here? Should always override this ...
|
||||
return 0;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.getHeight = function()
|
||||
{
|
||||
// TODO: Do we want to throw here? Should always override this ...
|
||||
return 0;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.setHighlight = function(value)
|
||||
{
|
||||
this.highlighted = value;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.centerX = function()
|
||||
{
|
||||
return this.x;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.setWidth = function(newWidth)
|
||||
{
|
||||
// TODO: Do we want to throw here? Should always override this ...
|
||||
}
|
||||
|
||||
|
||||
|
||||
AnimatedObject.prototype.centerY = function()
|
||||
{
|
||||
return this.y;
|
||||
}
|
||||
|
||||
|
||||
AnimatedObject.prototype.getAlignLeftPos = function(otherObject)
|
||||
{
|
||||
return [otherObject.right()+ this.getWidth() / 2, otherObject.centerY()];
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.getAlignRightPos = function(otherObject)
|
||||
{
|
||||
|
||||
return [otherObject.left() - this.getWidth() / 2, otherObject.centerY()];
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.getAlignTopPos = function(otherObject)
|
||||
{
|
||||
|
||||
return [otherObject.centerX(), otherObject.top() - this.getHeight() / 2];
|
||||
}
|
||||
AnimatedObject.prototype.getAlignBottomPos = function(otherObject)
|
||||
{
|
||||
return [otherObject.centerX(), otherObject.bottom() + this.getHeight() / 2];
|
||||
}
|
||||
|
||||
|
||||
AnimatedObject.prototype.alignLeft = function(otherObject)
|
||||
{
|
||||
// Assuming centering. Overridden method could modify if not centered
|
||||
// (See AnimatedLabel, for instance)
|
||||
this.y = otherObject.centerY();
|
||||
this.x = otherObject.right() + this.getWidth() / 2;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.alignRight = function(otherObject)
|
||||
{
|
||||
// Assuming centering. Overridden method could modify if not centered
|
||||
// (See AnimatedLabel, for instance)
|
||||
this.y = otherObject.centerY();
|
||||
this.x = otherObject.left() - this.getWidth() / 2;
|
||||
}
|
||||
|
||||
|
||||
AnimatedObject.prototype.alignTop = function(otherObject)
|
||||
{
|
||||
// Assuming centering. Overridden method could modify if not centered
|
||||
|
||||
this.x = otherObject.centerX();
|
||||
this.y = otherObject.top() - this.getHeight() / 2;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
AnimatedObject.prototype.alignBottom = function(otherObject)
|
||||
{
|
||||
this.x = otherObject.centerX();
|
||||
this.y = otherObject.bottom() + this.getHeight() / 2;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* TODO: Do we need these in the base?
|
||||
function left(): Number
|
||||
{
|
||||
return x - getWidth() / 2;
|
||||
}
|
||||
|
||||
function right():Number
|
||||
{
|
||||
return x + getWidth() / 2;
|
||||
}
|
||||
|
||||
function top():Number
|
||||
{
|
||||
return y - getHeight() / 2;
|
||||
}
|
||||
|
||||
function bottom():Number
|
||||
{
|
||||
return y + getHeight() / 2;
|
||||
}
|
||||
|
||||
function centerX():Number
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
function centerY():Number
|
||||
{
|
||||
return y;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
AnimatedObject.prototype.getClosestCardinalPoint = function(fromX, fromY)
|
||||
{
|
||||
var xDelta;
|
||||
var yDelta;
|
||||
var xPos;
|
||||
var yPos;
|
||||
|
||||
if (fromX < this.left())
|
||||
{
|
||||
xDelta = this.left() - fromX;
|
||||
xPos = this.left();
|
||||
}
|
||||
else if (fromX > this.right())
|
||||
{
|
||||
xDelta = fromX - this.right();
|
||||
xPos = this.right();
|
||||
}
|
||||
else
|
||||
{
|
||||
xDelta = 0;
|
||||
xPos = this.centerX();
|
||||
}
|
||||
|
||||
if (fromY < this.top())
|
||||
{
|
||||
yDelta = this.top() - fromY;
|
||||
yPos = this.top();
|
||||
}
|
||||
else if (fromY > this.bottom())
|
||||
{
|
||||
yDelta = fromY - this.bottom();
|
||||
yPos = this.bottom();
|
||||
}
|
||||
else
|
||||
{
|
||||
yDelta = 0;
|
||||
yPos = this.centerY();
|
||||
}
|
||||
|
||||
if (yDelta > xDelta)
|
||||
{
|
||||
xPos = this.centerX();
|
||||
}
|
||||
else
|
||||
{
|
||||
yPos = this.centerY();
|
||||
}
|
||||
|
||||
return [xPos, yPos];
|
||||
}
|
||||
|
||||
|
||||
AnimatedObject.prototype.centered = function()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
AnimatedObject.prototype.pulseHighlight = function(frameNum)
|
||||
{
|
||||
if (this.highlighted)
|
||||
{
|
||||
var frameMod = frameNum / 7.0;
|
||||
var delta = Math.abs((frameMod) % (2 * this.range - 2) - this.range + 1)
|
||||
this.highlightDiff = delta + this.minHeightDiff;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.getTailPointerAttachPos = function(fromX, fromY, anchorPoint)
|
||||
{
|
||||
return [this.x, this.y];
|
||||
}
|
||||
|
||||
|
||||
AnimatedObject.prototype.getHeadPointerAttachPos = function(fromX, fromY)
|
||||
{
|
||||
return [this.x, this.y];
|
||||
}
|
||||
|
||||
/*public function createUndoDelete() : UndoBlock
|
||||
{
|
||||
// Must be overriden!
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
AnimatedObject.prototype.identifier = function()
|
||||
{
|
||||
return this.objectID;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.getText = function(index)
|
||||
{
|
||||
return this.label;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.getTextColor = function(textIndex)
|
||||
{
|
||||
return this.labelColor
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.setTextColor = function(color, textIndex)
|
||||
{
|
||||
this.labelColor = color;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.setText = function(newText, textIndex)
|
||||
{
|
||||
this.label = newText;
|
||||
}
|
||||
|
||||
AnimatedObject.prototype.setHighlightIndex = function(hlIndex)
|
||||
{
|
||||
this.highlightIndex = hlIndex;
|
||||
this.highlightIndexDirty = true;
|
||||
}
|
||||
|
||||
|
||||
AnimatedObject.prototype.getHighlightIndex = function()
|
||||
{
|
||||
return this.highlightIndex;
|
||||
}
|
@@ -0,0 +1,340 @@
|
||||
// Copyright 2011 David Galles, University of San Francisco. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||
// provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// The views and conclusions contained in the software and documentation are those of the
|
||||
// authors and should not be interpreted as representing official policies, either expressed
|
||||
// or implied, of the University of San Francisco
|
||||
|
||||
// Values for xJust / yJust: "center", "left", "right", "top", "bottom"
|
||||
|
||||
AnimatedRectangle = function(id, val, wth, hgt, xJust, yJust, fillColor, edgeColor)
|
||||
{
|
||||
this.w = wth;
|
||||
this.h = hgt;
|
||||
this.xJustify = xJust;
|
||||
this.yJustify = yJust;
|
||||
this.label = val;
|
||||
this.labelColor = edgeColor
|
||||
|
||||
this.backgroundColor = fillColor;
|
||||
this.foregroundColor = edgeColor;
|
||||
this.labelColor = this.foregroundColor;
|
||||
this.highlighted = false;
|
||||
this.objectID = id;
|
||||
this.nullPointer = false;
|
||||
this.alpha = 1.0;
|
||||
this.addedToScene = true;
|
||||
|
||||
}
|
||||
|
||||
AnimatedRectangle.prototype = new AnimatedObject();
|
||||
AnimatedRectangle.prototype.constructor = AnimatedRectangle;
|
||||
|
||||
AnimatedRectangle.prototype.setNull = function(np)
|
||||
{
|
||||
this.nullPointer = np;
|
||||
}
|
||||
|
||||
AnimatedRectangle.prototype.getNull = function()
|
||||
{
|
||||
return this.nullPointer;
|
||||
}
|
||||
|
||||
|
||||
AnimatedRectangle.prototype.left = function()
|
||||
{
|
||||
if (this.xJustify == "left")
|
||||
{
|
||||
return this.x;
|
||||
}
|
||||
else if (this.xJustify == "center")
|
||||
{
|
||||
return this.x - this.w / 2.0;
|
||||
}
|
||||
else // (this.xJustify == "right")
|
||||
{
|
||||
return this.x - this.w;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AnimatedRectangle.prototype.centerX = function()
|
||||
{
|
||||
if (this.xJustify == "center")
|
||||
{
|
||||
return this.x;
|
||||
}
|
||||
else if (this.xJustify == "left")
|
||||
{
|
||||
return this.x + this.w / 2.0;
|
||||
}
|
||||
else // (this.xJustify == "right")
|
||||
{
|
||||
return this.x - this.w / 2.0;
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedRectangle.prototype.centerY = function()
|
||||
{
|
||||
if (this.yJustify == "center")
|
||||
{
|
||||
return this.y;
|
||||
}
|
||||
else if (this.yJustify == "top")
|
||||
{
|
||||
return this.y + this.h / 2.0;
|
||||
}
|
||||
else // (this.xJustify == "bottom")
|
||||
{
|
||||
return this.y - this.w / 2.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AnimatedRectangle.prototype.top = function()
|
||||
{
|
||||
if (this.yJustify == "top")
|
||||
{
|
||||
return this.y;
|
||||
}
|
||||
else if (this.yJustify == "center")
|
||||
{
|
||||
return this.y - this.h / 2.0;
|
||||
}
|
||||
else //(this.xJustify == "bottom")
|
||||
{
|
||||
return this.y - this.h;
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedRectangle.prototype.bottom = function()
|
||||
{
|
||||
if (this.yJustify == "top")
|
||||
{
|
||||
return this.y + this.h;
|
||||
}
|
||||
else if (this.yJustify == "center")
|
||||
{
|
||||
return this.y + this.h / 2.0;
|
||||
}
|
||||
else //(this.xJustify == "bottom")
|
||||
{
|
||||
return this.y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedRectangle.prototype.right = function()
|
||||
{
|
||||
if (this.xJustify == "left")
|
||||
{
|
||||
return this.x + this.w;
|
||||
}
|
||||
else if (this.xJustify == "center")
|
||||
{
|
||||
return this.x + this.w / 2.0;
|
||||
}
|
||||
else // (this.xJustify == "right")
|
||||
{
|
||||
return this.x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AnimatedRectangle.prototype.getHeadPointerAttachPos = function(fromX, fromY)
|
||||
{
|
||||
return this.getClosestCardinalPoint(fromX, fromY);
|
||||
}
|
||||
|
||||
|
||||
AnimatedRectangle.prototype.setWidth = function(wdth)
|
||||
{
|
||||
this.w = wdth;
|
||||
}
|
||||
|
||||
|
||||
AnimatedRectangle.prototype.setHeight = function(hght)
|
||||
{
|
||||
this.h = hght;
|
||||
}
|
||||
|
||||
AnimatedRectangle.prototype.getWidth = function()
|
||||
{
|
||||
return this.w;
|
||||
}
|
||||
|
||||
AnimatedRectangle.prototype.getHeight = function()
|
||||
{
|
||||
return this.h;
|
||||
}
|
||||
|
||||
|
||||
// TODO: Fix me!
|
||||
AnimatedRectangle.prototype.draw = function(context)
|
||||
{
|
||||
if (!this.addedToScene)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var startX;
|
||||
var startY;
|
||||
var labelPosX;
|
||||
var labelPosY;
|
||||
|
||||
context.globalAlpha = this.alpha;
|
||||
|
||||
if (this.xJustify == "left")
|
||||
{
|
||||
startX = this.x;
|
||||
labelPosX = this.x + this.w / 2.0;
|
||||
}
|
||||
else if (this.xJustify == "center")
|
||||
{
|
||||
startX = this.x-this.w / 2.0;
|
||||
labelPosX = this.x;
|
||||
|
||||
}
|
||||
else if (this.xJustify == "right")
|
||||
{
|
||||
startX = this.x-this.w;
|
||||
labelPosX = this.x - this.w / 2.0
|
||||
}
|
||||
if (this.yJustify == "top")
|
||||
{
|
||||
startY = this.y;
|
||||
labelPosY = this.y + this.h / 2.0;
|
||||
}
|
||||
else if (this.yJustify == "center")
|
||||
{
|
||||
startY = this.y - this.h / 2.0;
|
||||
labelPosY = this.y;
|
||||
|
||||
}
|
||||
else if (this.yJustify == "bottom")
|
||||
{
|
||||
startY = this.y - this.h;
|
||||
labelPosY = this.y - this.h / 2.0;
|
||||
}
|
||||
|
||||
context.lineWidth = 1;
|
||||
|
||||
if (this.highlighted)
|
||||
{
|
||||
context.strokeStyle = "#ff0000";
|
||||
context.fillStyle = "#ff0000";
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(startX - this.highlightDiff,startY- this.highlightDiff);
|
||||
context.lineTo(startX+this.w + this.highlightDiff,startY- this.highlightDiff);
|
||||
context.lineTo(startX+this.w+ this.highlightDiff,startY+this.h + this.highlightDiff);
|
||||
context.lineTo(startX - this.highlightDiff,startY+this.h + this.highlightDiff);
|
||||
context.lineTo(startX - this.highlightDiff,startY - this.highlightDiff);
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
context.fill();
|
||||
|
||||
}
|
||||
context.strokeStyle = this.foregroundColor;
|
||||
context.fillStyle = this.backgroundColor;
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(startX ,startY);
|
||||
context.lineTo(startX + this.w, startY);
|
||||
context.lineTo(startX + this.w, startY + this.h);
|
||||
context.lineTo(startX, startY + this.h);
|
||||
context.lineTo(startX, startY);
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
context.fill();
|
||||
|
||||
if (this.nullPointer)
|
||||
{
|
||||
context.beginPath();
|
||||
context.moveTo(startX ,startY);
|
||||
context.lineTo(startX + this.w, startY + this.h);
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
}
|
||||
|
||||
context.fillStyle = this.labelColor;
|
||||
|
||||
context.textAlign = 'center';
|
||||
context.font = '16px Consolas';
|
||||
context.textBaseline = 'middle';
|
||||
context.lineWidth = 1;
|
||||
context.fillText(this.label, this.x, this.y);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
AnimatedRectangle.prototype.setText = function(newText, textIndex)
|
||||
{
|
||||
this.label = newText;
|
||||
// TODO: setting text position?
|
||||
}
|
||||
|
||||
|
||||
AnimatedRectangle.prototype.createUndoDelete = function()
|
||||
{
|
||||
// TODO: Add color?
|
||||
return new UndoDeleteRectangle(this.objectID, this.label, this.x, this.y, this.w, this.h, this.xJustify, this.yJustify, this.backgroundColor, this.foregroundColor, this.highlighted, this.layer);
|
||||
}
|
||||
|
||||
AnimatedRectangle.prototype.setHighlight = function(value)
|
||||
{
|
||||
this.highlighted = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function UndoDeleteRectangle(id, lab, x, y, w, h, xJust, yJust, bgColor, fgColor, highlight, lay)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.posX = x;
|
||||
this.posY = y;
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
this.xJustify = xJust;
|
||||
this.yJustify = yJust;
|
||||
this.backgroundColor= bgColor;
|
||||
this.foregroundColor = fgColor;
|
||||
this.nodeLabel = lab;
|
||||
this.layer = lay;
|
||||
this.highlighted = highlight;
|
||||
}
|
||||
|
||||
UndoDeleteRectangle.prototype = new UndoBlock();
|
||||
UndoDeleteRectangle.prototype.constructor = UndoDeleteRectangle;
|
||||
|
||||
|
||||
UndoDeleteRectangle.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.addRectangleObject(this.objectID, this.nodeLabel, this.width, this.height, this.xJustify, this.yJustify, this.backgroundColor, this.foregroundColor);
|
||||
world.setNodePosition(this.objectID, this.posX, this.posY);
|
||||
world.setLayer(this.objectID, this.layer);
|
||||
world.setHighlight(this.objectID, this.highlighted);
|
||||
}
|
||||
|
||||
|
||||
|
檔案差異因為檔案過大而無法顯示
載入差異
@@ -0,0 +1,176 @@
|
||||
// Copyright 2011 David Galles, University of San Francisco. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||
// provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// The views and conclusions contained in the software and documentation are those of the
|
||||
// authors and should not be interpreted as representing official policies, either expressed
|
||||
// or implied, of the University of San Francisco
|
||||
|
||||
|
||||
Function.prototype.bind = function() {
|
||||
var _function = this;
|
||||
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var scope = args.shift()
|
||||
return function() {
|
||||
for (var i = 0; i < arguments.length; i++)
|
||||
{
|
||||
args.push(arguments[i]);
|
||||
}
|
||||
return _function.apply(scope, args);
|
||||
}
|
||||
}
|
||||
|
||||
function EventListener()
|
||||
{
|
||||
this.events = [];
|
||||
}
|
||||
|
||||
|
||||
EventListener.prototype.removeListener = function(kind, scope, func)
|
||||
{
|
||||
if (this.events[kind] == undefined)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var scopeFunctions = null;
|
||||
var i;
|
||||
for (i = 0; i < this.events[kind].length; i++)
|
||||
{
|
||||
if (this.events[kind][i].scope == scope)
|
||||
{
|
||||
scopeFunctions = this.events[kind][i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (scopeFunctions == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < scopeFunctions.functions.length; i++)
|
||||
{
|
||||
if (scopeFunctions.functions[i] == func)
|
||||
{
|
||||
scopeFunctions.functions.splice(i,1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EventListener.prototype.addListener = function(kind, scope, func)
|
||||
{
|
||||
if (this.events[kind] === undefined)
|
||||
{
|
||||
this.events[kind] = [];
|
||||
}
|
||||
var i;
|
||||
var scopeFunctions = null;
|
||||
for (i = 0; i < this.events[kind].length; i++)
|
||||
{
|
||||
if (this.events[kind][i].scope == scope)
|
||||
{
|
||||
scopeFunctions = this.events[kind][i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (scopeFunctions === null)
|
||||
{
|
||||
this.events[kind].push({scope:scope, functions:[] });
|
||||
scopeFunctions = this.events[kind][this.events[kind].length - 1];
|
||||
}
|
||||
for (i = 0; i < scopeFunctions.functions.length; i++)
|
||||
{
|
||||
if (scopeFunctions.functions[i] == func)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
scopeFunctions.functions.push(func);
|
||||
}
|
||||
|
||||
EventListener.prototype.fireEvent = function(kind, event)
|
||||
{
|
||||
// TODO: Should add a deep clone here ...
|
||||
if (this.events[kind] !== undefined)
|
||||
{
|
||||
for (var i = 0; i < this.events[kind].length; i++)
|
||||
{
|
||||
var objects = this.events[kind][i];
|
||||
var functs = objects.functions;
|
||||
var scope = objects.scope
|
||||
for (var j = 0; j <functs.length; j++)
|
||||
{
|
||||
var func = functs[j];
|
||||
func.call(scope,event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
function Source()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Source.prototype = new EventListener();
|
||||
Source.prototype.constructor = Source;
|
||||
Source.prototype.testFire = function()
|
||||
{
|
||||
this.fireEvent("test","testcontents");
|
||||
this.fireEvent("test2","test2contents");
|
||||
}
|
||||
|
||||
|
||||
|
||||
function Client(eventSource)
|
||||
{
|
||||
|
||||
this.first = function(blah)
|
||||
{
|
||||
alert("first:" + blah);
|
||||
}
|
||||
|
||||
this.second = function(blah)
|
||||
{
|
||||
alert("second:" + blah);
|
||||
}
|
||||
eventSource.addListener("test", this, this.first);
|
||||
eventSource.addListener("test", this, this.first);
|
||||
eventSource.addListener("test", this, this.second);
|
||||
eventSource.removeListener("test", this, this.first);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function init()
|
||||
{
|
||||
var src = new Source;
|
||||
var c = new Client(src);
|
||||
src.testFire();
|
||||
}
|
||||
|
||||
*/
|
||||
|
@@ -0,0 +1,87 @@
|
||||
// Copyright 2011 David Galles, University of San Francisco. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||
// provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// The views and conclusions contained in the software and documentation are those of the
|
||||
// authors and should not be interpreted as representing official policies, either expressed
|
||||
// or implied, of the University of San Francisco
|
||||
|
||||
// "Class" animatedCircle
|
||||
|
||||
|
||||
var HighlightCircle = function(objectID, color, radius)
|
||||
{
|
||||
this.objectID = objectID;
|
||||
this.radius = radius;
|
||||
this.thickness = 4;
|
||||
this.foregroundColor = color;
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
this.alpha = 1;
|
||||
}
|
||||
|
||||
HighlightCircle.prototype = new AnimatedObject();
|
||||
HighlightCircle.prototype.constructor = HighlightCircle;
|
||||
|
||||
|
||||
HighlightCircle.prototype.draw = function(ctx)
|
||||
{
|
||||
ctx.globalAlpha = this.alpha;
|
||||
ctx.strokeStyle = this.foregroundColor;
|
||||
ctx.lineWidth = this.thickness;
|
||||
ctx.beginPath();
|
||||
ctx.arc(this.x,this.y,this.radius,0,Math.PI*2, true);
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
|
||||
HighlightCircle.prototype.createUndoDelete = function()
|
||||
{
|
||||
return new UndoDeleteHighlightCircle(this.objectID, this.x, this.y, this.foregroundColor, this.radius, this.layer, this.alpha);
|
||||
}
|
||||
|
||||
|
||||
function UndoDeleteHighlightCircle(objectID, x, y, circleColor, r, layer, alpha)
|
||||
{
|
||||
this.objectID = objectID;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.color = circleColor;
|
||||
this.r = r;
|
||||
this.layer = layer;
|
||||
this.alpha = alpha
|
||||
}
|
||||
|
||||
UndoDeleteHighlightCircle.prototype = new UndoBlock();
|
||||
UndoDeleteHighlightCircle.prototype.constructor = UndoDeleteHighlightCircle;
|
||||
|
||||
UndoDeleteHighlightCircle.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.addHighlightCircleObject(this.objectID, this.color, this.r);
|
||||
world.setLayer(this.objectID, this.layer)
|
||||
world.setNodePosition(this.objectID, this.x, this.y);
|
||||
world.setAlpha(this.objectID, this.alpha)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@@ -0,0 +1,229 @@
|
||||
// Copyright 2011 David Galles, University of San Francisco. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||
// provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// The views and conclusions contained in the software and documentation are those of the
|
||||
// authors and should not be interpreted as representing official policies, either expressed
|
||||
// or implied, of the University of San Francisco
|
||||
|
||||
|
||||
// This class is somewhat poorly named -- it handles links between vertices in graphs,
|
||||
// pointers in linked lists, and so on.
|
||||
|
||||
|
||||
var LINE_maxHeightDiff = 5;
|
||||
var LINE_minHeightDiff = 3;
|
||||
var LINE_range= LINE_maxHeightDiff - LINE_minHeightDiff + 1;
|
||||
var LINE_highlightDiff = 3;
|
||||
|
||||
|
||||
function Line(n1, n2, color, cv, d, weight, anchorIndex)
|
||||
{
|
||||
this.arrowHeight = 8;
|
||||
this.arrowWidth = 4;
|
||||
|
||||
this.Node1 = n1;
|
||||
this.Node2 = n2;
|
||||
this.Dirty = false;
|
||||
this.directed = d;
|
||||
this.edgeColor = color;
|
||||
this.edgeLabel = weight;
|
||||
this.highlighted = false;
|
||||
this.addedToScene = true;
|
||||
this.anchorPoint = anchorIndex;
|
||||
this.highlightDiff = 0;
|
||||
this.curve = cv;
|
||||
|
||||
this.alpha = 1.0;
|
||||
this.color = function color()
|
||||
{
|
||||
return this.edgeColor;
|
||||
}
|
||||
|
||||
this.setColor = function(newColor)
|
||||
{
|
||||
this.edgeColor = newColor;
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
this.setHighlight = function(highlightVal)
|
||||
{
|
||||
this.highlighted = highlightVal;
|
||||
}
|
||||
|
||||
this.pulseHighlight = function(frameNum)
|
||||
{
|
||||
if (this.highlighted)
|
||||
{
|
||||
var frameMod = frameNum / 14.0;
|
||||
var delta = Math.abs((frameMod) % (2 * LINE_range - 2) - LINE_range + 1)
|
||||
this.highlightDiff = delta + LINE_minHeightDiff;
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.hasNode = function(n)
|
||||
{
|
||||
return ((this.Node1 == n) || (this.Node2 == n));
|
||||
}
|
||||
|
||||
|
||||
this.createUndoDisconnect = function()
|
||||
{
|
||||
return new UndoConnect(this.Node1.objectID, this.Node2.objectID, true, this.edgeColor, this.directed, this.curve, this.edgeLabel, this.anchorPoint);
|
||||
}
|
||||
|
||||
|
||||
this.sign = function(n)
|
||||
{
|
||||
if (n > 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.drawArrow = function(pensize, color, context)
|
||||
{
|
||||
context.strokeStyle = color;
|
||||
context.fillStyle = color;
|
||||
context.lineWidth = pensize;
|
||||
// var fromPos = this.Node1.getTailPointerAttachPos(this.Node2.x, this.Node2.y, this.anchorPoint);
|
||||
// var toPos = this.Node2.getHeadPointerAttachPos(this.Node1.x, this.Node1.y);
|
||||
|
||||
var fromPos = this.Node1.getTailPointerAttachPos(this.Node2.x, this.Node2.y, this.anchorPoint);
|
||||
var toPos = this.Node2.getHeadPointerAttachPos(this.Node1.x, this.Node1.y);
|
||||
|
||||
var deltaX = toPos[0] - fromPos[0];
|
||||
var deltaY = toPos[1] - fromPos[1];
|
||||
var midX = (deltaX) / 2.0 + fromPos[0];
|
||||
var midY = (deltaY) / 2.0 + fromPos[1];
|
||||
var controlX = midX - deltaY * this.curve;
|
||||
|
||||
var controlY = midY + deltaX * this.curve;
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(fromPos[0], fromPos[1]);
|
||||
context.quadraticCurveTo(controlX, controlY, toPos[0], toPos[1]);
|
||||
context.stroke();
|
||||
//context.closePath();
|
||||
|
||||
// Position of the edge label: First, we will place it right along the
|
||||
// middle of the curve (or the middle of the line, for curve == 0)
|
||||
var labelPosX = 0.25* fromPos[0] + 0.5*controlX + 0.25*toPos[0];
|
||||
var labelPosY = 0.25* fromPos[1] + 0.5*controlY + 0.25*toPos[1];
|
||||
|
||||
// Next, we push the edge position label out just a little in the direction of
|
||||
// the curve, so that the label doesn't intersect the cuve (as long as the label
|
||||
// is only a few characters, that is)
|
||||
var midLen = Math.sqrt(deltaY*deltaY + deltaX*deltaX);
|
||||
if (midLen != 0)
|
||||
{
|
||||
labelPosX += (- deltaY * this.sign(this.curve)) / midLen * 10
|
||||
labelPosY += ( deltaX * this.sign(this.curve)) / midLen * 10
|
||||
}
|
||||
|
||||
|
||||
|
||||
context.textAlign = 'center';
|
||||
context.font = '16px Consolas';
|
||||
context.textBaseline = 'middle';
|
||||
context.fillText(this.edgeLabel, labelPosX, labelPosY);
|
||||
|
||||
if (this.directed)
|
||||
{
|
||||
var xVec = controlX - toPos[0];
|
||||
var yVec = controlY - toPos[1];
|
||||
var len = Math.sqrt(xVec * xVec + yVec*yVec);
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
xVec = xVec / len
|
||||
yVec = yVec / len;
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(toPos[0], toPos[1]);
|
||||
context.lineTo(toPos[0] + xVec*this.arrowHeight - yVec*this.arrowWidth, toPos[1] + yVec*this.arrowHeight + xVec*this.arrowWidth);
|
||||
context.lineTo(toPos[0] + xVec*this.arrowHeight + yVec*this.arrowWidth, toPos[1] + yVec*this.arrowHeight - xVec*this.arrowWidth);
|
||||
context.lineTo(toPos[0], toPos[1]);
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
context.fill();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
this.draw = function(ctx)
|
||||
{
|
||||
if (!this.addedToScene)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ctx.globalAlpha = this.alpha;
|
||||
|
||||
if (this.highlighted)
|
||||
this.drawArrow(this.highlightDiff, "#FF0000", ctx);
|
||||
this.drawArrow(1, this.edgeColor, ctx);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function UndoConnect(from, to, createConnection, edgeColor, isDirected, cv, lab, anch)
|
||||
{
|
||||
this.fromID = from;
|
||||
this.toID = to;
|
||||
this.connect = createConnection;
|
||||
this.color = edgeColor;
|
||||
this.directed = isDirected;
|
||||
this.curve = cv;
|
||||
this.edgeLabel = lab;
|
||||
this.anchorPoint = anch;
|
||||
}
|
||||
|
||||
|
||||
UndoConnect.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
if (this.connect)
|
||||
{
|
||||
world.connectEdge(this.fromID, this.toID, this.color, this.curve, this.directed, this.edgeLabel,this.anchorPoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
world.disconnect(this.fromID,this.toID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UndoConnect.prototype.addUndoAnimation = function(animationList)
|
||||
{
|
||||
return false;
|
||||
}
|
@@ -0,0 +1,858 @@
|
||||
// Copyright 2011 David Galles, University of San Francisco. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||
// provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// The views and conclusions contained in the software and documentation are those of the
|
||||
// authors and should not be interpreted as representing official policies, either expressed
|
||||
// or implied, of the University of San Francisco
|
||||
|
||||
|
||||
// Object Manager
|
||||
//
|
||||
// Manage all of our animated objects. Control any animated object should occur through
|
||||
// this interface (not language enforced, because enforcing such things in Javascript is
|
||||
// problematic.)
|
||||
//
|
||||
// This class is only accessed through:
|
||||
//
|
||||
// AnimationMain
|
||||
// Undo objects (which are themselves controlled by AnimationMain
|
||||
|
||||
|
||||
// TODO:
|
||||
// 1. Add proper throws for all error conditions (perhaps guarded by
|
||||
// an assert-like structure that can be turned off for production?)
|
||||
// 2. Refactor this code so that it uses the same object syntax (with
|
||||
// prototypes) as te rest of the code. (low priority)
|
||||
function ObjectManager()
|
||||
{
|
||||
this.Nodes = [];
|
||||
this.Edges = [];
|
||||
this.BackEdges = [];
|
||||
this.activeLayers = [];
|
||||
this.activeLayers[0] = true;
|
||||
this.ctx = document.getElementById('canvas').getContext('2d');
|
||||
this.framenum = 0;
|
||||
this.width = 0;
|
||||
this.height = 0;
|
||||
this.statusReport = new AnimatedLabel(-1, "XXX", false, 30);
|
||||
this.statusReport.x = 30;
|
||||
|
||||
this.draw = function()
|
||||
{
|
||||
this.framenum++;
|
||||
if (this.framenum > 1000)
|
||||
this.framenum = 0;
|
||||
|
||||
this.ctx.clearRect(0,0,this.width,this.height); // clear canvas
|
||||
this.statusReport.y = this.height - 15;
|
||||
|
||||
var i;
|
||||
var j;
|
||||
for (i = 0; i < this.Nodes.length; i++)
|
||||
{
|
||||
if (this.Nodes[i] != null && !this.Nodes[i].highlighted && this.Nodes[i].addedToScene && !this.Nodes[i].alwaysOnTop)
|
||||
{
|
||||
this.Nodes[i].draw(this.ctx);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < this.Nodes.length; i++)
|
||||
{
|
||||
if (this.Nodes[i] != null && (this.Nodes[i].highlighted && !this.Nodes[i].alwaysOnTop) && this.Nodes[i].addedToScene)
|
||||
{
|
||||
this.Nodes[i].pulseHighlight(this.framenum);
|
||||
this.Nodes[i].draw(this.ctx);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < this.Nodes.length; i++)
|
||||
{
|
||||
if (this.Nodes[i] != null && this.Nodes[i].alwaysOnTop && this.Nodes[i].addedToScene)
|
||||
{
|
||||
this.Nodes[i].pulseHighlight(this.framenum);
|
||||
this.Nodes[i].draw(this.ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < this.Edges.length; i++)
|
||||
{
|
||||
if (this.Edges[i] != null)
|
||||
{
|
||||
for (j = 0; j < this.Edges[i].length; j++)
|
||||
{
|
||||
if (this.Edges[i][j].addedToScene)
|
||||
{
|
||||
this.Edges[i][j].pulseHighlight(this.framenum);
|
||||
this.Edges[i][j].draw(this.ctx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
this.statusReport.draw(this.ctx);
|
||||
|
||||
}
|
||||
|
||||
this.update = function ()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
this.setLayers = function(shown,layers)
|
||||
{
|
||||
for (var i = 0; i < layers.length; i++)
|
||||
{
|
||||
this.activeLayers[layers[i]] = shown;
|
||||
}
|
||||
this.resetLayers();
|
||||
|
||||
}
|
||||
|
||||
|
||||
this.addHighlightCircleObject = function(objectID, objectColor, radius)
|
||||
{
|
||||
if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined)
|
||||
{
|
||||
throw "addHighlightCircleObject:Object with same ID (" + String(objectID) + ") already Exists!"
|
||||
}
|
||||
var newNode = new HighlightCircle(objectID, objectColor, radius)
|
||||
this.Nodes[objectID] = newNode;
|
||||
}
|
||||
|
||||
this.setEdgeAlpha = function(fromID, toID, alphaVal)
|
||||
{
|
||||
var oldAlpha = 1.0;
|
||||
if (this.Edges[fromID] != null &&
|
||||
this.Edges[fromID] != undefined)
|
||||
{
|
||||
var len = this.Edges[fromID].length;
|
||||
for (var i = len - 1; i >= 0; i--)
|
||||
{
|
||||
if (this.Edges[fromID][i] != null &&
|
||||
this.Edges[fromID][i] != undefined &&
|
||||
this.Edges[fromID][i].Node2 == this.Nodes[toID])
|
||||
{
|
||||
oldAlpha = this.Edges[fromID][i].alpha
|
||||
this.Edges[fromID][i].alpha = alphaVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
return oldAlpha;
|
||||
|
||||
}
|
||||
|
||||
this.setAlpha = function(nodeID, alphaVal)
|
||||
{
|
||||
if (this.Nodes[nodeID] != null && this.Nodes[nodeID] != undefined)
|
||||
{
|
||||
this.Nodes[nodeID].setAlpha(alphaVal);
|
||||
}
|
||||
}
|
||||
|
||||
this.getAlpha = function(nodeID)
|
||||
{
|
||||
if (this.Nodes[nodeID] != null && this.Nodes[nodeID] != undefined)
|
||||
{
|
||||
return this.Nodes[nodeID].getAlpha();
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
this.getTextColor = function(nodeID, index)
|
||||
{
|
||||
if (this.Nodes[nodeID] != null && this.Nodes[nodeID] != undefined)
|
||||
{
|
||||
return this.Nodes[nodeID].getTextColor(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "#000000";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.setTextColor = function(nodeID, color, index)
|
||||
{
|
||||
if (this.Nodes[nodeID] != null && this.Nodes[nodeID] != undefined)
|
||||
{
|
||||
this.Nodes[nodeID].setTextColor(color, index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.setHighlightIndex = function(nodeID, index)
|
||||
{
|
||||
if (this.Nodes[nodeID] != null && this.Nodes[nodeID] != undefined)
|
||||
{
|
||||
this.Nodes[nodeID].setHighlightIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
this.setAllLayers = function(layers)
|
||||
{
|
||||
this.activeLayers = [];
|
||||
for(var i = 0; i < layers.length; i++)
|
||||
{
|
||||
this.activeLayers[layers[i]] = true;
|
||||
}
|
||||
this.resetLayers();
|
||||
}
|
||||
|
||||
this.resetLayers = function()
|
||||
{
|
||||
var i
|
||||
for (i = 0; i <this.Nodes.length; i++)
|
||||
{
|
||||
if (this.Nodes[i] != null && this.Nodes[i] != undefined)
|
||||
{
|
||||
this.Nodes[i].addedToScene = this.activeLayers[this.Nodes[i].layer] == true;
|
||||
}
|
||||
}
|
||||
for (i = this.Edges.length - 1; i >= 0; i--)
|
||||
{
|
||||
if (this.Edges[i] != null && this.Edges[i] != undefined)
|
||||
{
|
||||
for (var j = 0; j < this.Edges[i].length; j++)
|
||||
{
|
||||
if (this.Edges[i][j] != null && this.Edges[i][j] != undefined)
|
||||
{
|
||||
this.Edges[i][j].addedToScene =
|
||||
this.activeLayers[this.Edges[i][j].Node1.layer] == true &&
|
||||
this.activeLayers[this.Edges[i][j].Node2.layer] == true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.setLayer = function(objectID, layer)
|
||||
{
|
||||
if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined)
|
||||
{
|
||||
this.Nodes[objectID].layer = layer;
|
||||
if (this.activeLayers[layer])
|
||||
{
|
||||
this.Nodes[objectID].addedToScene = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Nodes[objectID].addedToScene = false;
|
||||
}
|
||||
if (this.Edges[objectID] != null && this.Edges[objectID] != undefined)
|
||||
{
|
||||
for (var i = 0; i < this.Edges[objectID].length; i++)
|
||||
{
|
||||
var nextEdge = this.Edges[objectID][i];
|
||||
if (nextEdge != null && nextEdge != undefined)
|
||||
{
|
||||
nextEdge.addedToScene = ((nextEdge.Node1.addedToScene) &&
|
||||
(nextEdge.Node2.addedToScene));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.BackEdges[objectID] != null && this.BackEdges[objectID] != undefined)
|
||||
{
|
||||
for (var i = 0; i < this.BackEdges[objectID].length; i++)
|
||||
{
|
||||
var nextEdge = this.BackEdges[objectID][i];
|
||||
if (nextEdge != null && nextEdge != undefined)
|
||||
{
|
||||
nextEdge.addedToScene = ((nextEdge.Node1.addedToScene) &&
|
||||
(nextEdge.Node2.addedToScene));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.clearAllObjects = function()
|
||||
{
|
||||
this.Nodes = [];
|
||||
this.Edges = [];
|
||||
this.BackEdges = [];
|
||||
}
|
||||
|
||||
|
||||
this.setForegroundColor = function(objectID, color)
|
||||
{
|
||||
if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined)
|
||||
{
|
||||
this.Nodes[objectID].setForegroundColor(color);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.setBackgroundColor = function(objectID, color)
|
||||
{
|
||||
if (this.Nodes[objectID] != null)
|
||||
{
|
||||
this.Nodes[objectID].setBackgroundColor(color);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.setHighlight = function(nodeID, val)
|
||||
{
|
||||
if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined)
|
||||
{
|
||||
// TODO: Error here?
|
||||
return;
|
||||
}
|
||||
this.Nodes[nodeID].setHighlight(val);
|
||||
}
|
||||
|
||||
|
||||
this.getHighlight = function(nodeID)
|
||||
{
|
||||
if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined)
|
||||
{
|
||||
// TODO: Error here?
|
||||
return false;
|
||||
}
|
||||
return this.Nodes[nodeID].getHighlight();
|
||||
}
|
||||
|
||||
|
||||
this.getHighlightIndex = function(nodeID)
|
||||
{
|
||||
if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined)
|
||||
{
|
||||
// TODO: Error here?
|
||||
return false;
|
||||
}
|
||||
return this.Nodes[nodeID].getHighlightIndex();
|
||||
}
|
||||
|
||||
this.setWidth = function(nodeID, val)
|
||||
{
|
||||
if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined)
|
||||
{
|
||||
// TODO: Error here?
|
||||
return;
|
||||
}
|
||||
this.Nodes[nodeID].setWidth(val);
|
||||
}
|
||||
|
||||
this.setHeight = function(nodeID, val)
|
||||
{
|
||||
if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined)
|
||||
{
|
||||
// TODO: Error here?
|
||||
return;
|
||||
}
|
||||
this.Nodes[nodeID].setHeight(val);
|
||||
}
|
||||
|
||||
|
||||
this.getHeight = function(nodeID)
|
||||
{
|
||||
if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined)
|
||||
{
|
||||
// TODO: Error here?
|
||||
return -1;
|
||||
}
|
||||
return this.Nodes[nodeID].getHeight();
|
||||
}
|
||||
|
||||
this.getWidth = function(nodeID)
|
||||
{
|
||||
if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined)
|
||||
{
|
||||
// TODO: Error here?
|
||||
return -1;
|
||||
}
|
||||
return this.Nodes[nodeID].getWidth();
|
||||
}
|
||||
|
||||
this.backgroundColor = function(objectID)
|
||||
{
|
||||
if (this.Nodes[objectID] != null)
|
||||
{
|
||||
return this.Nodes[objectID].backgroundColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
return '#000000';
|
||||
}
|
||||
}
|
||||
|
||||
this.foregroundColor = function(objectID)
|
||||
{
|
||||
if (this.Nodes[objectID] != null)
|
||||
{
|
||||
return this.Nodes[objectID].foregroundColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
return '#000000';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.disconnect = function(objectIDfrom,objectIDto)
|
||||
{
|
||||
var undo = null;
|
||||
var i;
|
||||
if (this.Edges[objectIDfrom] != null)
|
||||
{
|
||||
var len = this.Edges[objectIDfrom].length;
|
||||
for (i = len - 1; i >= 0; i--)
|
||||
{
|
||||
if (this.Edges[objectIDfrom][i] != null && this.Edges[objectIDfrom][i].Node2 == this.Nodes[objectIDto])
|
||||
{
|
||||
var deleted = this.Edges[objectIDfrom][i];
|
||||
undo = deleted.createUndoDisconnect();
|
||||
this.Edges[objectIDfrom][i] = this.Edges[objectIDfrom][len - 1];
|
||||
len -= 1;
|
||||
this.Edges[objectIDfrom].pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.BackEdges[objectIDto] != null)
|
||||
{
|
||||
len = this.BackEdges[objectIDto].length;
|
||||
for (i = len - 1; i >= 0; i--)
|
||||
{
|
||||
if (this.BackEdges[objectIDto][i] != null && this.BackEdges[objectIDto][i].Node1 == this.Nodes[objectIDfrom])
|
||||
{
|
||||
deleted = this.BackEdges[objectIDto][i];
|
||||
// Note: Don't need to remove this child, did it above on the regular edge
|
||||
this.BackEdges[objectIDto][i] = this.BackEdges[objectIDto][len - 1];
|
||||
len -= 1;
|
||||
this.BackEdges[objectIDto].pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
return undo;
|
||||
}
|
||||
|
||||
this.deleteIncident = function(objectID)
|
||||
{
|
||||
var undoStack = [];
|
||||
|
||||
if (this.Edges[objectID] != null)
|
||||
{
|
||||
var len = this.Edges[objectID].length;
|
||||
for (var i = len - 1; i >= 0; i--)
|
||||
{
|
||||
var deleted = this.Edges[objectID][i];
|
||||
var node2ID = deleted.Node2.identifier();
|
||||
undoStack.push(deleted.createUndoDisconnect());
|
||||
|
||||
var len2 = this.BackEdges[node2ID].length;
|
||||
for (var j = len2 - 1; j >=0; j--)
|
||||
{
|
||||
if (this.BackEdges[node2ID][j] == deleted)
|
||||
{
|
||||
this.BackEdges[node2ID][j] = this.BackEdges[node2ID][len2 - 1];
|
||||
len2 -= 1;
|
||||
this.BackEdges[node2ID].pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Edges[objectID] = null;
|
||||
}
|
||||
if (this.BackEdges[objectID] != null)
|
||||
{
|
||||
len = this.BackEdges[objectID].length;
|
||||
for (i = len - 1; i >= 0; i--)
|
||||
{
|
||||
deleted = this.BackEdges[objectID][i];
|
||||
var node1ID = deleted.Node1.identifier();
|
||||
undoStack.push(deleted.createUndoDisconnect());
|
||||
|
||||
len2 = this.Edges[node1ID].length;
|
||||
for (j = len2 - 1; j >=0; j--)
|
||||
{
|
||||
if (this.Edges[node1ID][j] == deleted)
|
||||
{
|
||||
this.Edges[node1ID][j] = this.Edges[node1ID][len2 - 1];
|
||||
len2 -= 1;
|
||||
this.Edges[node1ID].pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
this.BackEdges[objectID] = null;
|
||||
}
|
||||
return undoStack;
|
||||
}
|
||||
|
||||
|
||||
this.removeObject = function(ObjectID)
|
||||
{
|
||||
var OldObject = this.Nodes[ObjectID];
|
||||
if (ObjectID == this.Nodes.length - 1)
|
||||
{
|
||||
this.Nodes.pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Nodes[ObjectID] = null;
|
||||
}
|
||||
}
|
||||
|
||||
this.getObject = function(objectID)
|
||||
{
|
||||
if (this.Nodes[objectID] == null || this.Nodes[objectID] == undefined)
|
||||
{
|
||||
throw "getObject:Object with ID (" + String(objectID) + ") does not exist"
|
||||
}
|
||||
return this.Nodes[objectID];
|
||||
|
||||
}
|
||||
|
||||
|
||||
this.addCircleObject = function (objectID, objectLabel)
|
||||
{
|
||||
if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined)
|
||||
{
|
||||
throw "addCircleObject:Object with same ID (" + String(objectID) + ") already Exists!"
|
||||
}
|
||||
var newNode = new AnimatedCircle(objectID, objectLabel);
|
||||
this.Nodes[objectID] = newNode;
|
||||
}
|
||||
|
||||
this.getNodeX = function(nodeID)
|
||||
{
|
||||
if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined)
|
||||
{
|
||||
throw "getting x position of an object that does not exit";
|
||||
}
|
||||
return this.Nodes[nodeID].x;
|
||||
}
|
||||
|
||||
this.getTextWidth = function(text)
|
||||
{
|
||||
// TODO: Need to make fonts more flexible, and less hardwired.
|
||||
this.ctx.font = '16px Consolas';
|
||||
if (text==undefined)
|
||||
{
|
||||
w = 3;
|
||||
}
|
||||
var strList = text.split("\n");
|
||||
var width = 0;
|
||||
if (strList.length == 1)
|
||||
{
|
||||
width = this.ctx.measureText(text).width;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < strList.length; i++)
|
||||
{
|
||||
width = Math.max(width, this.ctx.measureText(strList[i]).width);
|
||||
}
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
this.setText = function(nodeID, text, index)
|
||||
{
|
||||
if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined)
|
||||
{
|
||||
return;
|
||||
throw "setting text of an object that does not exit";
|
||||
}
|
||||
this.Nodes[nodeID].setText(text, index, this.getTextWidth(text));
|
||||
|
||||
}
|
||||
|
||||
this.getText = function(nodeID, index)
|
||||
{
|
||||
if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined)
|
||||
{
|
||||
throw "getting text of an object that does not exit";
|
||||
}
|
||||
return this.Nodes[nodeID].getText(index);
|
||||
|
||||
}
|
||||
|
||||
this.getNodeY = function(nodeID)
|
||||
{
|
||||
if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined)
|
||||
{
|
||||
throw "getting y position of an object that does not exit";
|
||||
}
|
||||
return this.Nodes[nodeID].y;
|
||||
}
|
||||
|
||||
|
||||
this.connectEdge = function(objectIDfrom, objectIDto, color, curve, directed, lab, connectionPoint)
|
||||
{
|
||||
var fromObj = this.Nodes[objectIDfrom];
|
||||
var toObj = this.Nodes[objectIDto];
|
||||
if (fromObj == null || toObj == null)
|
||||
{
|
||||
throw "Tried to connect two nodes, one didn't exist!";
|
||||
}
|
||||
var l = new Line(fromObj,toObj, color, curve, directed, lab, connectionPoint);
|
||||
if (this.Edges[objectIDfrom] == null || this.Edges[objectIDfrom] == undefined)
|
||||
{
|
||||
this.Edges[objectIDfrom] = [];
|
||||
}
|
||||
if (this.BackEdges[objectIDto] == null || this.BackEdges[objectIDto] == undefined)
|
||||
{
|
||||
this.BackEdges[objectIDto] = [];
|
||||
}
|
||||
l.addedToScene = fromObj.addedToScene && toObj.addedToScene;
|
||||
this.Edges[objectIDfrom].push(l);
|
||||
this.BackEdges[objectIDto].push(l);
|
||||
|
||||
}
|
||||
|
||||
|
||||
this.setNull = function(objectID, nullVal)
|
||||
{
|
||||
if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined)
|
||||
{
|
||||
this.Nodes[objectID].setNull(nullVal);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.getNull = function(objectID)
|
||||
{
|
||||
if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined)
|
||||
{
|
||||
return this.Nodes[objectID].getNull();
|
||||
}
|
||||
return false; // TODO: Error here?
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.setEdgeColor = function(fromID, toID, color) // returns old color
|
||||
{
|
||||
var oldColor ="#000000";
|
||||
if (this.Edges[fromID] != null &&
|
||||
this.Edges[fromID] != undefined)
|
||||
{
|
||||
var len = this.Edges[fromID].length;
|
||||
for (var i = len - 1; i >= 0; i--)
|
||||
{
|
||||
if (this.Edges[fromID][i] != null &&
|
||||
this.Edges[fromID][i] != undefined &&
|
||||
this.Edges[fromID][i].Node2 == this.Nodes[toID])
|
||||
{
|
||||
oldColor = this.Edges[fromID][i].color();
|
||||
this.Edges[fromID][i].setColor(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
return oldColor;
|
||||
}
|
||||
|
||||
this.alignTop = function(id1, id2)
|
||||
{
|
||||
if (this.Nodes[id1] == null || this.Nodes[id1] == undefined ||
|
||||
this.Nodes[id2] == null || this.Nodes[id2] == undefined)
|
||||
{
|
||||
throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2);
|
||||
}
|
||||
this.Nodes[id1].alignTop(this.Nodes[id2]);
|
||||
}
|
||||
|
||||
this.alignLeft = function(id1, id2)
|
||||
{
|
||||
if (this.Nodes[id1] == null || this.Nodes[id1] == undefined ||
|
||||
this.Nodes[id2] == null || this.Nodes[id2] == undefined)
|
||||
{
|
||||
throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2);
|
||||
}
|
||||
this.Nodes[id1].alignLeft(this.Nodes[id2]);
|
||||
}
|
||||
|
||||
this.alignRight = function(id1, id2)
|
||||
{
|
||||
if (this.Nodes[id1] == null || this.Nodes[id1] == undefined ||
|
||||
this.Nodes[id2] == null || this.Nodes[id2] == undefined)
|
||||
{
|
||||
throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2);
|
||||
}
|
||||
this.Nodes[id1].alignRight(this.Nodes[id2]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.getAlignRightPos = function(id1, id2)
|
||||
{
|
||||
if (this.Nodes[id1] == null || this.Nodes[id1] == undefined ||
|
||||
this.Nodes[id2] == null || this.Nodes[id2] == undefined)
|
||||
{
|
||||
throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2);
|
||||
}
|
||||
return this.Nodes[id1].getAlignRightPos(this.Nodes[id2]);
|
||||
}
|
||||
|
||||
this.getAlignLeftPos = function(id1, id2)
|
||||
{
|
||||
if (this.Nodes[id1] == null || this.Nodes[id1] == undefined ||
|
||||
this.Nodes[id2] == null || this.Nodes[id2] == undefined)
|
||||
{
|
||||
throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2);
|
||||
}
|
||||
return this.Nodes[id1].getAlignLeftPos(this.Nodes[id2]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.alignBottom = function(id1, id2)
|
||||
{
|
||||
if (this.Nodes[id1] == null || this.Nodes[id1] == undefined ||
|
||||
this.Nodes[id2] == null || this.Nodes[id2] == undefined)
|
||||
{
|
||||
throw "Tring to align two nodes, one doesn't exist: " + String(id1) + "," + String(id2);
|
||||
}
|
||||
this.Nodes[id1].alignBottom(this.Nodes[id2]);
|
||||
}
|
||||
|
||||
|
||||
this.setEdgeHighlight = function(fromID, toID, val) // returns old color
|
||||
{
|
||||
var oldHighlight = false;
|
||||
if (this.Edges[fromID] != null &&
|
||||
this.Edges[fromID] != undefined)
|
||||
{
|
||||
var len = this.Edges[fromID].length;
|
||||
for (var i = len - 1; i >= 0; i--)
|
||||
{
|
||||
if (this.Edges[fromID][i] != null &&
|
||||
this.Edges[fromID][i] != undefined &&
|
||||
this.Edges[fromID][i].Node2 == this.Nodes[toID])
|
||||
{
|
||||
oldHighlight = this.Edges[fromID][i].highlighted;
|
||||
this.Edges[fromID][i].setHighlight(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
return oldHighlight;
|
||||
}
|
||||
this.addLabelObject = function(objectID, objectLabel, centering)
|
||||
{
|
||||
if (this.Nodes[objectID] != null && this.Nodes[objectID] != undefined)
|
||||
{
|
||||
throw new Error("addLabelObject: Object Already Exists!");
|
||||
}
|
||||
|
||||
var newLabel = new AnimatedLabel(objectID, objectLabel, centering, this.getTextWidth(objectLabel));
|
||||
this.Nodes[objectID] = newLabel;
|
||||
}
|
||||
|
||||
|
||||
this.addLinkedListObject = function(objectID, nodeLabel, width, height, linkPer, verticalOrientation, linkPosEnd, numLabels, backgroundColor, foregroundColor)
|
||||
{
|
||||
if (this.Nodes[objectID] != null)
|
||||
{
|
||||
throw new Error("addLinkedListObject:Object with same ID already Exists!");
|
||||
return;
|
||||
}
|
||||
var newNode = new AnimatedLinkedList(objectID, nodeLabel, width, height, linkPer, verticalOrientation, linkPosEnd, numLabels, backgroundColor, foregroundColor);
|
||||
this.Nodes[objectID] = newNode;
|
||||
}
|
||||
|
||||
|
||||
this.getNumElements = function(objectID)
|
||||
{
|
||||
return this.Nodes[objectID].getNumElements();
|
||||
}
|
||||
|
||||
|
||||
this.setNumElements = function(objectID, numElems)
|
||||
{
|
||||
this.Nodes[objectID].setNumElements(numElems);
|
||||
}
|
||||
this.addBTreeNode = function(objectID, widthPerElem, height, numElems, backgroundColor, foregroundColor)
|
||||
{
|
||||
backgroundColor = (backgroundColor == undefined) ? "#FFFFFF" : backgroundColor;
|
||||
foregroundColor = (foregroundColor == undefined) ? "#FFFFFF" : foregroundColor;
|
||||
|
||||
if (this.Nodes[objectID] != null && Nodes[objectID] != undefined)
|
||||
{
|
||||
throw "addBTreeNode:Object with same ID already Exists!";
|
||||
}
|
||||
|
||||
var newNode = new AnimatedBTreeNode(objectID,widthPerElem, height, numElems, backgroundColor, foregroundColor);
|
||||
this.Nodes[objectID] = newNode;
|
||||
}
|
||||
|
||||
this.addRectangleObject = function(objectID,nodeLabel, width, height, xJustify , yJustify , backgroundColor, foregroundColor)
|
||||
{
|
||||
if (this.Nodes[objectID] != null || this.Nodes[objectID] != undefined)
|
||||
{
|
||||
throw new Error("addRectangleObject:Object with same ID already Exists!");
|
||||
}
|
||||
var newNode = new AnimatedRectangle(objectID, nodeLabel, width, height, xJustify, yJustify, backgroundColor, foregroundColor);
|
||||
this.Nodes[objectID] = newNode;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
this.setNodePosition = function(nodeID, newX, newY)
|
||||
{
|
||||
if (this.Nodes[nodeID] == null || this.Nodes[nodeID] == undefined)
|
||||
{
|
||||
// TODO: Error here?
|
||||
return;
|
||||
}
|
||||
if (newX == undefined || newY == undefined)
|
||||
{
|
||||
|
||||
return;
|
||||
}
|
||||
this.Nodes[nodeID].x = newX;
|
||||
this.Nodes[nodeID].y = newY;
|
||||
/* Don't need to dirty anything, since we repaint everything every frame
|
||||
(TODO: Revisit if we do conditional redraws)
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -0,0 +1,398 @@
|
||||
// Copyright 2011 David Galles, University of San Francisco. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||
// provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// The views and conclusions contained in the software and documentation are those of the
|
||||
// authors and should not be interpreted as representing official policies, either expressed
|
||||
// or implied, of the University of San Francisco
|
||||
|
||||
|
||||
// Base "class": UndoBlock
|
||||
|
||||
function UndoBlock()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
UndoBlock.prototype.addUndoAnimation = function(animationList)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UndoBlock.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoMove
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
function UndoMove(id, fmX, fmy, tx, ty)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.fromX = fmX;
|
||||
this.fromY = fmy;
|
||||
this.toX = tx;
|
||||
this.toY = ty;
|
||||
}
|
||||
|
||||
|
||||
UndoMove.prototype = new UndoBlock();
|
||||
UndoMove.prototype.constructor = UndoMove;
|
||||
|
||||
UndoMove.prototype.addUndoAnimation = function (animationList)
|
||||
{
|
||||
var nextAnim = new SingleAnimation(this.objectID, this.fromX, this.fromY, this.toX, this.toY);
|
||||
animationList.push(nextAnim);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoCreate
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
function UndoCreate(id)
|
||||
{
|
||||
this.objectID = id;
|
||||
}
|
||||
|
||||
UndoCreate.prototype = new UndoBlock();
|
||||
UndoCreate.prototype.constructor = UndoCreate;
|
||||
|
||||
|
||||
UndoCreate.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.removeObject(this.objectID);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoHighlight
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
function UndoHighlight(id, val)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.highlightValue = val;
|
||||
}
|
||||
|
||||
UndoHighlight.prototype = new UndoBlock();
|
||||
UndoHighlight.prototype.constructor = UndoHighlight;
|
||||
|
||||
UndoHighlight.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.setHighlight(this.objectID, this.highlightValue);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoSetHeight
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
function UndoSetHeight(id, val)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.height = val;
|
||||
}
|
||||
|
||||
UndoSetHeight.prototype = new UndoBlock();
|
||||
UndoSetHeight.prototype.constructor = UndoSetHeight;
|
||||
|
||||
UndoSetHeight.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.setHeight(this.objectID, this.height);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoSetWidth
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
function UndoSetWidth(id, val)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.width = val;
|
||||
}
|
||||
|
||||
UndoSetWidth.prototype = new UndoBlock();
|
||||
UndoSetWidth.prototype.constructor = UndoSetWidth;
|
||||
|
||||
UndoSetWidth.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.setWidth(this.objectID, this.width);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoSetNumElements
|
||||
////////////////////////////////////////////////////////////
|
||||
function UndoSetNumElements(obj, newNumElems)
|
||||
{
|
||||
this.objectID = obj.objectID;
|
||||
this.sizeBeforeChange = obj.getNumElements();
|
||||
this.sizeAfterChange = newNumElems;
|
||||
if (this.sizeBeforeChange > this.sizeAfterChange)
|
||||
{
|
||||
this.labels = new Array(this.sizeBeforeChange - this.sizeAfterChange);
|
||||
this.colors = new Array(this.sizeBeforeChange - this.sizeAfterChange);
|
||||
for (var i = 0; i < this.sizeBeforeChange - this.sizeAfterChange; i++)
|
||||
{
|
||||
this.labels[i] = obj.getText(i+this.sizeAfterChange);
|
||||
this.colors[i] = obj.getTextColor(i+this.sizeAfterChange);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
UndoSetNumElements.prototype = new UndoBlock();
|
||||
UndoSetNumElements.prototype.constructor = UndoSetNumElements;
|
||||
|
||||
|
||||
UndoSetNumElements.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.setNumElements(this.objectID, this.sizeBeforeChange);
|
||||
if (this.sizeBeforeChange > this.sizeAfterChange)
|
||||
{
|
||||
for (var i = 0; i < this.sizeBeforeChange - this.sizeAfterChange; i++)
|
||||
{
|
||||
world.setText(this.objectID, this.labels[i], i+this.sizeAfterChange);
|
||||
world.setTextColor(this.objectID, this.colors[i], i+this.sizeAfterChange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoSetAlpha
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
function UndoSetAlpha(id, alph)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.alphaVal = alph;
|
||||
}
|
||||
|
||||
UndoSetAlpha.prototype = new UndoBlock();
|
||||
UndoSetAlpha.prototype.constructor = UndoSetAlpha;
|
||||
|
||||
UndoSetAlpha.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.setAlpha(this.objectID, this.alphaVal);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoSetNull
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
function UndoSetNull(id, nv)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.nullVal = nv;
|
||||
}
|
||||
|
||||
UndoSetNull.prototype = new UndoBlock();
|
||||
UndoSetNull.prototype.constructor = UndoSetNull;
|
||||
|
||||
UndoSetNull.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.setNull(this.objectID, this.nullVal);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoSetForegroundColor
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
function UndoSetForegroundColor(id, color)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
UndoSetForegroundColor.prototype = new UndoBlock();
|
||||
UndoSetForegroundColor.prototype.constructor = UndoSetForegroundColor;
|
||||
|
||||
UndoSetForegroundColor.prototype.undoInitialStep = function (world)
|
||||
{
|
||||
world.setForegroundColor(this.objectID, this.color);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoSetBackgroundColor
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
function UndoSetBackgroundColor(id, color)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
UndoSetBackgroundColor.prototype = new UndoBlock();
|
||||
UndoSetBackgroundColor.prototype.constructor = UndoSetBackgroundColor;
|
||||
|
||||
UndoSetBackgroundColor.prototype.undoInitialStep = function (world)
|
||||
{
|
||||
world.setBackgroundColor(this.objectID, this.color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoSetHighlightIndex
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
function UndoSetHighlightIndex(id, index)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
UndoSetHighlightIndex.prototype = new UndoBlock();
|
||||
UndoSetHighlightIndex.prototype.constructor = UndoSetHighlightIndex;
|
||||
|
||||
UndoSetHighlightIndex.prototype.undoInitialStep = function (world)
|
||||
{
|
||||
world.setHighlightIndex(this.objectID, this.index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoSetText
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
function UndoSetText(id, str, index)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.newText = str;
|
||||
this.labelIndex = index;
|
||||
}
|
||||
|
||||
UndoSetText.prototype = new UndoBlock();
|
||||
UndoSetText.prototype.constructor = UndoSetText;
|
||||
|
||||
UndoSetText.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.setText(this.objectID, this.newText, this.labelIndex);
|
||||
}
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoSetTextColor
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
function UndoSetTextColor(id, color, index)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.color = color;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
UndoSetTextColor.prototype = new UndoBlock();
|
||||
UndoSetTextColor.prototype.constructor = UndoSetTextColor;
|
||||
|
||||
UndoSetTextColor.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.setTextColor(this.objectID, this.color, this.index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoHighlightEdge
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
function UndoHighlightEdge(from, to, val)
|
||||
{
|
||||
this.fromID = from;
|
||||
this.toID = to;
|
||||
this.highlightValue = val;
|
||||
}
|
||||
|
||||
UndoHighlightEdge.prototype = new UndoBlock();
|
||||
UndoHighlightEdge.prototype.constructor = UndoHighlightEdge;
|
||||
|
||||
UndoHighlightEdge.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.setEdgeHighlight(this.fromID, this.toID, this.highlightValue);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoSetEdgeColor
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
function UndoSetEdgeColor(from, to, oldColor)
|
||||
{
|
||||
this.fromID = from;
|
||||
this.toID = to;
|
||||
this.color = oldColor;
|
||||
}
|
||||
|
||||
UndoSetEdgeColor.prototype = new UndoBlock();
|
||||
UndoSetEdgeColor.prototype.constructor = UndoSetEdgeColor;
|
||||
|
||||
UndoSetEdgeColor.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.setEdgeColor(this.fromID, this.toID, this.color);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoSetEdgeAlpha
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
function UndoSetEdgeAlpha(from, to, oldAplha)
|
||||
{
|
||||
this.fromID = from;
|
||||
this.toID = to;
|
||||
this.alpha = oldAplha;
|
||||
}
|
||||
|
||||
UndoSetEdgeAlpha.prototype = new UndoBlock();
|
||||
UndoSetEdgeAlpha.prototype.constructor = UndoSetEdgeAlpha;
|
||||
|
||||
UndoSetEdgeAlpha.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.setEdgeAlpha(this.fromID, this.toID, this.alpha);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// UndoSetPosition
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
function UndoSetPosition(id, x, y)
|
||||
{
|
||||
this.objectID = id;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
UndoSetPosition.prototype = new UndoBlock();
|
||||
UndoSetPosition.prototype.constructor = UndoSetPosition;
|
||||
|
||||
|
||||
UndoSetPosition.prototype.undoInitialStep = function(world)
|
||||
{
|
||||
world.setNodePosition(this.objectID, this.x, this.y);
|
||||
}
|
||||
|
||||
|
新增問題並參考
封鎖使用者