474 行
12 KiB
JavaScript

// 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);
}
}