// Surkits - Main Code
var Surkit = function( cv ) {
this.mx = 0;
this.my = 0;
this.ctx = document.getElementById( cv ).getContext( '2d' );
this.comps = [ ];
}
Surkit.prototype.ComponentSize = 20;
Surkit.prototype.SetMousePosition = function( x , y ) {
this.mx = x - 0;
this.my = y - 0;
}
Surkit.prototype.AddComponent = function( com ) {
this.comps[ this.comps.length ] = com;
}
Surkit.prototype.MouseDown = function( ) {
for ( com in this.comps ) {
if ( Math.abs( this.mx - this.comps[ com ].x ) < ( this.ComponentSize / 2 ) & Math.abs( this.my - this.comps[ com ].y ) < ( this.ComponentSize / 2 ) & typeof this.comps[ com ].MouseDown != "undefined" ) {
this.comps[ com ].MouseDown( this );
}
}
}
Surkit.prototype.DrawWire = function( active , sx , sy , ex , ey ) {
var c = this.ctx;
var len = Math.sqrt( Math.pow( ex - sx , 2 ) + Math.pow( ey - sy , 2 ) );
var tx = ( ey - sy ) / len;
var ty = -( ex - sx ) / len;
var gradient = c.createLinearGradient( sx , sy , ex , ey );
gradient.addColorStop( 0 , ( ( active ) ? "#900" : "#000" ) );
gradient.addColorStop( 1 , ( ( active ) ? "#f00" : "#200" ) );
c.fillStyle = gradient;
c.beginPath( );
c.moveTo( sx + tx * 1 , sy + ty * 1 );
c.lineTo( sx - tx * 1 , sy - ty * 1 );
c.lineTo( ex - tx * 1 , ey - ty * 1 );
c.lineTo( ex + tx * 1 , ey + ty * 1 );
c.fill( );
}
Surkit.prototype.DrawComponent = function( com , color , icon ) {
var c = this.ctx;
var tlx = com.x - this.ComponentSize / 2, tly = com.y - this.ComponentSize / 2;
c.fillStyle = color;
c.fillRect( tlx , tly , this.ComponentSize , this.ComponentSize );
c.fillStyle = "rgb(0,0,0)";
c.textAlign = "center";
c.font = "normal 16px Tahoma";
c.fillText( icon , com.x , tly - 5 + this.ComponentSize );
if ( Math.abs( this.mx - com.x ) < ( this.ComponentSize / 2 ) & Math.abs( this.my - com.y ) < ( this.ComponentSize / 2 ) ) {
this.MouseLabel = com.Name;
}
}
Surkit.prototype.Draw = function( ) {
this.ctx.clearRect( 0 , 0 , screen.width , screen.height );
this.MouseLabel = "";
for ( com in this.comps ) {
for ( input in this.comps[ com ].input ) {
var inp = this.comps[ com ].input[ input ][ 0 ];
var active = inp.output[ this.comps[ com ].input[ input ][ 1 ] ];
this.DrawWire( active , inp.x + this.ComponentSize / 2 , inp.y , this.comps[ com ].x - this.ComponentSize / 2 , this.comps[ com ].y );
}
}
for ( com in this.comps ) {
var col = ( this.comps[ com ].Color ) ? ( ( typeof this.comps[ com ].Color == "string" ) ? this.comps[ com ].Color : this.comps[ com ].Color( this ) ) : "rgb(0,200,0)";
var icon = ( this.comps[ com ].Icon ) ? this.comps[ com ].Icon : "?";
this.DrawComponent( this.comps[ com ] , col , icon );
}
if ( this.MouseLabel != "" ) {
this.ctx.font = "italic 12px Tahoma";
this.ctx.textAlign = "start";
this.ctx.fillStyle = "rgb(100,100,100)";
this.ctx.fillText( this.MouseLabel , this.mx + 5 , this.my - 5 );
}
this.ctx.textAlign = "start";
this.ctx.font = "normal 10px Tahoma";
this.ctx.fillStyle = "rgb(150,150,150)";
this.ctx.fillText( this.mx + ", " + this.my , 15 , 15 );
}
Surkit.prototype.LoadSurkit = function( text ) {
this.comps = [ ];
lines = text.split( "\n" );
for ( line in lines ) {
if ( lines[ line ].length == 0 ) continue;
var dat = lines[ line ].split( " " );
if ( dat[ 0 ] == "wire" ) {
this.comps[ parseInt( dat[ 1 ] , 10 ) ].SetInput( parseInt( dat[ 2 ] , 10 ) , this.comps[ parseInt( dat[ 3 ] , 10 ) ] , parseInt( dat[ 4 ] , 10 ) );
} else if ( dat[ 0 ].substr( 0 , 2 ) != "--" ) {
this.comps[ parseInt( dat[ 0 ] , 10 ) ] = eval( "new " + dat[ 1 ] + "(" + dat[ 2 ] + "," + dat[ 3 ] + ")" );
}
}
for ( com in this.comps ) {
if ( typeof this.comps[ com ].Trigger != "undefined" ) {
this.comps[ com ].Trigger( );
}
}
}
// Logic Gate - AND
var Gate_And = function( x , y ) {
this.x = x;
this.y = y;
this.input = [ ];
this.output = [ ];
this.gates = [ ];
}
Gate_And.prototype.Name = "AND Gate";
Gate_And.prototype.Icon = "&";
Gate_And.prototype.Hook = function( conn ) {
this.gates[ this.gates.length ] = conn;
}
Gate_And.prototype.SetInput = function( id , in_gate , out_id ) {
this.input[ id ] = [ in_gate , out_id ];
in_gate.Hook( this );
}
Gate_And.prototype.Trigger = function( ) {
var out = ( this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ] & this.input[ 1 ][ 0 ].output[ this.input[ 1 ][ 1 ] ] );
if ( out != this.output[ 0 ] ) {
this.output[ 0 ] = out;
for ( conn in this.gates ) {
this.gates[ conn ].Trigger( );
}
}
}
// Logic Gate - NAND
var Gate_Nand = function( x , y ) {
this.x = x;
this.y = y;
this.input = [ ];
this.output = [ ];
this.gates = [ ];
}
Gate_Nand.prototype.Name = "NAND Gate";
Gate_Nand.prototype.Icon = "!&";
Gate_Nand.prototype.Hook = function( conn ) {
this.gates[ this.gates.length ] = conn;
}
Gate_Nand.prototype.SetInput = function( id , in_gate , out_id ) {
this.input[ id ] = [ in_gate , out_id ];
in_gate.Hook( this );
}
Gate_Nand.prototype.Trigger = function( ) {
var out = !( this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ] & this.input[ 1 ][ 0 ].output[ this.input[ 1 ][ 1 ] ] );
if ( out != this.output[ 0 ] ) {
this.output[ 0 ] = out;
for ( conn in this.gates ) {
this.gates[ conn ].Trigger( );
}
}
}
// Logic Gate - OR
var Gate_Or = function( x , y ) {
this.x = x;
this.y = y;
this.input = [ ];
this.output = [ ];
this.gates = [ ];
}
Gate_Or.prototype.Name = "OR Gate";
Gate_Or.prototype.Icon = "|";
Gate_Or.prototype.Hook = function( conn ) {
this.gates[ this.gates.length ] = conn;
}
Gate_Or.prototype.SetInput = function( id , in_gate , out_id ) {
this.input[ id ] = [ in_gate , out_id ];
in_gate.Hook( this );
}
Gate_Or.prototype.Trigger = function( ) {
var out = ( this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ] | this.input[ 1 ][ 0 ].output[ this.input[ 1 ][ 1 ] ] )
if ( out != this.output[ 0 ] ) {
this.output[ 0 ] = out;
for ( conn in this.gates ) {
this.gates[ conn ].Trigger( );
}
}
}
// Logic Gate - NOR
var Gate_Nor = function( x , y ) {
this.x = x;
this.y = y;
this.input = [ ];
this.output = [ ];
this.gates = [ ];
}
Gate_Nor.prototype.Name = "NOR Gate";
Gate_Nor.prototype.Icon = "!|";
Gate_Nor.prototype.Hook = function( conn ) {
this.gates[ this.gates.length ] = conn;
}
Gate_Nor.prototype.SetInput = function( id , in_gate , out_id ) {
this.input[ id ] = [ in_gate , out_id ];
in_gate.Hook( this );
}
Gate_Nor.prototype.Trigger = function( ) {
var out = !( this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ] | this.input[ 1 ][ 0 ].output[ this.input[ 1 ][ 1 ] ] )
if ( out != this.output[ 0 ] ) {
this.output[ 0 ] = out;
for ( conn in this.gates ) {
this.gates[ conn ].Trigger( );
}
}
}
// Logic Gate - XOR
var Gate_Xor = function( x , y ) {
this.x = x;
this.y = y;
this.input = [ ];
this.output = [ ];
this.gates = [ ];
}
Gate_Xor.prototype.Name = "XOR Gate";
Gate_Xor.prototype.Icon = "x|";
Gate_Xor.prototype.Hook = function( conn ) {
this.gates[ this.gates.length ] = conn;
}
Gate_Xor.prototype.SetInput = function( id , in_gate , out_id ) {
this.input[ id ] = [ in_gate , out_id ];
in_gate.Hook( this );
}
Gate_Xor.prototype.Trigger = function( ) {
var out = ( this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ] ^ this.input[ 1 ][ 0 ].output[ this.input[ 1 ][ 1 ] ] )
if ( out != this.output[ 0 ] ) {
this.output[ 0 ] = out;
for ( conn in this.gates ) {
this.gates[ conn ].Trigger( );
}
}
}
// Logic Gate - XNOR
var Gate_Xnor = function( x , y ) {
this.x = x;
this.y = y;
this.input = [ ];
this.output = [ ];
this.gates = [ ];
}
Gate_Xnor.prototype.Name = "XNOR Gate";
Gate_Xnor.prototype.Icon = "x!|";
Gate_Xnor.prototype.Hook = function( conn ) {
this.gates[ this.gates.length ] = conn;
}
Gate_Xnor.prototype.SetInput = function( id , in_gate , out_id ) {
this.input[ id ] = [ in_gate , out_id ];
in_gate.Hook( this );
}
Gate_Xnor.prototype.Trigger = function( ) {
var out = !( this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ] ^ this.input[ 1 ][ 0 ].output[ this.input[ 1 ][ 1 ] ] )
if ( out != this.output[ 0 ] ) {
this.output[ 0 ] = out;
for ( conn in this.gates ) {
this.gates[ conn ].Trigger( );
}
}
}
// Logic Gate - Inverter
var Gate_Inv = function( x , y ) {
this.x = x;
this.y = y;
this.input = [ ];
this.output = [ ];
this.gates = [ ];
}
Gate_Inv.prototype.Name = "Inverter Gate";
Gate_Inv.prototype.Icon = "!";
Gate_Inv.prototype.Hook = function( conn ) {
this.gates[ this.gates.length ] = conn;
}
Gate_Inv.prototype.SetInput = function( id , in_gate , out_id ) {
this.input[ id ] = [ in_gate , out_id ];
in_gate.Hook( this );
}
Gate_Inv.prototype.Trigger = function( ) {
var out = !this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ];
if ( out != this.output[ 0 ] ) {
this.output[ 0 ] = out;
for ( conn in this.gates ) {
this.gates[ conn ].Trigger( );
}
}
}
// Input - Logic Input
var Input = function( x , y ) {
this.x = x;
this.y = y;
this.input = [ ];
this.output = [ ];
this.gates = [ ];
this.Icon = "0";
}
Input.prototype.Name = "Logic Input";
Input.prototype.Hook = function( conn ) {
this.gates[ this.gates.length ] = conn;
}
Input.prototype.SetInput = function( ) { }
Input.prototype.MouseDown = function( parent ) {
this.output[ 0 ] = ( this.output[ 0 ] ) ? false : true;
this.Icon = ( this.output[ 0 ] ) ? "1" : "0";
for ( conn in this.gates ) {
this.gates[ conn ].Trigger( );
}
}
Input.prototype.Color = function( parent ) {
return ( this.output[ 0 ] ) ? "rgb(150,150,150)" : "rgb(75,75,75)";
}
// Input - Logic Output
var Output = function( x , y ) {
this.x = x;
this.y = y;
this.input = [ ];
this.output = [ ];
this.gates = [ ];
this.Icon = "0";
}
Output.prototype.Name = "Logic Output";
Output.prototype.Hook = function( conn ) {
this.gates[ this.gates.length ] = conn;
}
Output.prototype.SetInput = function( id , in_gate , out_id ) {
this.input[ id ] = [ in_gate , out_id ];
in_gate.Hook( this );
}
Output.prototype.Color = function( parent ) {
return ( this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ] ) ? "rgb(0,200,0)" : "rgb(150,0,0)";
}
Output.prototype.Trigger = function( parent ) {
var out = this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ];
if ( out != this.output[ 0 ] ) {
this.output[ 0 ] = out;
this.Icon = ( this.output[ 0 ] ) ? "1" : "0";
for ( conn in this.gates ) {
this.gates[ conn ].Trigger( );
}
}
}
// Initialization Code Here
var circuit;
var myComponent;
window.onload = function( ) {
circuit = new Surkit( "cvs" );
setInterval( "circuit.Draw( )" , 50 );
document.getElementById( "cvs" ).onmousemove = function( e ) {
var cv = document.getElementById( "cvs" );
var x = 0;
var y = 0;
e = ( window.event ) ? window.event : e;
if ( e.pageX || e.pageY ) {
x = e.pageX;
y = e.pageY;
}
else if ( e.clientX || e.clientY ) {
x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
circuit.SetMousePosition( x - parseInt( cv.style.left , 10 ) , y - parseInt( cv.style.top , 10 ) );
}
document.getElementById( "cvs" ).onmousedown = function( e ) {
circuit.MouseDown( );
return false;
}
}
</script>
</head>
<canvas id="cvs" style="position:absolute;top:10px;left:10px;border:1px solid" width="800" height="500"></canvas><br /> <textarea id="input" style="position:absolute;top:520px;left:10px;width:700px;height:100px"></textarea> <input type="button" style="position:absolute;top:520px;left:712px;width:100px;height:100px" onclick="circuit.LoadSurkit( document.getElementById('input').value )" value="Load" /> </body>
</html>