CZ_OpenSpice/template/schematic/schematic.html

2907 lines
97 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!--
Copyright (c) 2021, Zhang Shen
CZ Open Spice Schematic .
-->
<html>
<head>
<title>CZ Open Spice Schematic </title>
<!-- Sets the basepath for the library if not in same directory -->
<script type="text/javascript">
mxBasePath = 'static/schematic/src';
</script>
<!-- Loads and initializes the library -->
<script type="text/javascript" src="static/schematic/src/js/mxClient.js"></script>
<link href="static/schematic/css/tab.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.2.3.min.js"></script>
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.2.3.min.js"></script>
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.2.3.min.js"></script>
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-api-2.2.3.min.js"></script>
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-api-2.2.3.min.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<!-- Example code -->
<script type="text/javascript">
// Program starts here. Creates a sample graph in the
// DOM node with the specified ID. This function is invoked
// from the onLoad event handler of the document (see below).
function main()
{
// Defines an icon for creating new connections in the connection handler.
// This will automatically disable the highlighting of the source vertex.
// mxConnectionHandler.prototype.connectImage = new mxImage('images/connector.gif', 16, 16);
// If connect preview is not moved away then getCellAt is used to detect the cell under
// the mouse if the mouse is over the preview shape in IE (no event transparency), ie.
// the built-in hit-detection of the HTML document will not be used in this case.
mxConnectionHandler.prototype.movePreviewAway = false;
mxConnectionHandler.prototype.waypointsEnabled = true;
mxGraph.prototype.resetEdgesOnConnect = false;
mxConstants.SHADOWCOLOR = '#C0C0C0';
// Replaces the port image
mxConstraintHandler.prototype.pointImage = new mxImage('static/schematic/images/dot.gif', 10, 10);
// Enables guides
mxGraphHandler.prototype.guidesEnabled = true;
// Alt disables guides
mxGuide.prototype.isEnabledForEvent = function(evt)
{
return !mxEvent.isAltDown(evt);
};
// Enables snapping waypoints to terminals
mxEdgeHandler.prototype.snapToTerminals = true;
// Checks if browser is supported
if (!mxClient.isBrowserSupported())
{
// Displays an error message if the browser is
// not supported.
mxUtils.error('Browser is not supported!', 200, false);
}
else
{
// Creates the div for the toolbar
var tbContainer = document.createElement('div');
tbContainer.style.position = 'absolute';
tbContainer.style.overflow = 'hidden';
tbContainer.style.padding = '2px';
tbContainer.style.left = '0px';
tbContainer.style.top = '26px';
tbContainer.style.width = '24px';
tbContainer.style.bottom = '0px';
document.body.appendChild(tbContainer);
// Creates new toolbar without event processing
var toolbar = new mxToolbar(tbContainer);
toolbar.enabled = false
// Creates the div for the graph
container = document.createElement('div');
container.style.position = 'absolute';
container.style.overflow = 'hidden';
container.style.left = '24px';
container.style.top = '26px';
container.style.right = '0px';
container.style.bottom = '0px';
container.style.background = 'url("static/schematic/images/wires-grid.gif")';
document.body.appendChild(container);
// Workaround for Internet Explorer ignoring certain styles
if (mxClient.IS_QUIRKS)
{
document.body.style.overflow = 'hidden';
new mxDivResizer(tbContainer);
new mxDivResizer(container);
}
// Creates the model and the graph inside the container
// using the fastest rendering available on the browser
var model = new mxGraphModel();
var graph = new mxGraph(container, model);
graph.setConnectable(true);
graph.setPortsEnabled(false);
graph.setTooltips(true);
graph.view.scale = 1;
graph.setPanning(true);
// graph.setConnectable(true);
graph.setConnectableEdges(true);
graph.setDisconnectOnMove(false);
graph.foldingEnabled = false;
//Maximum size
graph.maximumGraphBounds = new mxRectangle(0, 0, 800, 600)
graph.border = 50;
// Panning handler consumed right click so this must be
// disabled if right click should stop connection handler.
graph.panningHandler.isPopupTrigger = function() { return false; };
// Enables return key to stop editing (use shift-enter for newlines)
graph.setEnterStopsCellEditing(true);
// 只显示名字其他的value进行隐藏
// Overrides method to provide a cell label in the display
graph.convertValueToString = function(cell)
{
var Value_raw = cell.getValue();
var Value_att = ParseAttribute(Value_raw);
var Value_show = '';
if(Value_att['Name'] == 'unknown'){
if(Value_att['name'] != 'unknown'){
Value_show = Value_att['name'];
}
}
else{
Value_show = Value_att['Name'];
}
// var Value_show = Value_att['name'] == 'unknown' ? '' : Value_att['name'];
return Value_show;
};
// 暂时不允许在此进行修改
var cellLabelChanged = graph.cellLabelChanged;
graph.cellLabelChanged = function(cell, new_value, autoSize)
{
// // Clones the value for correct undo/redo
// var elt = cell.value.cloneNode(true);
// newValue = elt;
// autoSize = false;
// cellLabelChanged.apply(this, arguments);
};
graph.getTooltipForCell = function(cell)
{
return 'Doubleclick and right- or shiftclick';
}
// Installs a popupmenu handler using local function (see below).
graph.popupMenuHandler.factoryMethod = function(menu, cell, evt)
{
return createPopupMenu(graph, menu, cell, evt);
};
// Stops editing on enter or escape keypress
// var keyHandler = new mxKeyHandler(graph);
var rubberband = new mxRubberband(graph);
// Add Vertex
// var addVertex = function(icon, w, h, style)
// {
// var vertex = new mxCell(null, new mxGeometry(0, 0, w, h), style);
// vertex.setVertex(true);
// addToolbarItem(graph, toolbar, vertex, icon);
// };
var addVertex_2 = function(icon, w, h, style,value)
{
var vertex = new mxCell(null, new mxGeometry(0, 0, w, h), style);
vertex.setVertex(true);
vertex.setValue(value);
addToolbarItem(graph, toolbar, vertex, icon);
};
addVertex_2('static/schematic/icon_ee/res.ico', 80, 30, 'shape=resistor;verticalLabelPosition=top;verticalAlign=bottom','Name=R;Value=10 Ohm;');
addVertex_2('static/schematic/icon_ee/cap.ico', 40, 30, 'shape=capacitor;verticalLabelPosition=top;verticalAlign=bottom','Name=C;Value=10 pF;');
addVertex_2('static/schematic/icon_ee/nmos.ico', 60, 60, 'shape=n_mosfet;verticalLabelPosition=top;verticalAlign=bottom','Name=M_NMOS;Model=NMOS;Length=1um;Width=20um;');
addVertex_2('static/schematic/icon_ee/pmos.ico', 60, 60, 'shape=p_mosfet;verticalLabelPosition=top;verticalAlign=bottom','Name=M_PMOS;Model=PMOS;Length=1um;Width=20um;');
addVertex_2('static/schematic/icon_ee/vdd.ico', 40, 30, 'shape=vdd;verticalLabelPosition=top;verticalAlign=bottom','Name=Vdd;');
addVertex_2('static/schematic/icon_ee/gnd.ico', 40, 40, 'shape=gnd;verticalLabelPosition=bottom;verticalAlign=top','Name=Gnd;');
addVertex_2('static/schematic/icon_ee/pin.ico', 40, 40, 'shape=pin;verticalLabelPosition=top;verticalAlign=bottom','Name=Pin;');
addVertex_2('static/schematic/icon_ee/pout.ico', 40, 40, 'shape=pout;verticalLabelPosition=top;verticalAlign=bottom','Name=Pout;');
addVertex_2('static/schematic/icon_ee/vdc.ico', 40, 40, 'shape=vdc;labelPosition=left;align=right','Name=Vdc;DC=1 V;');
addVertex_2('static/schematic/icon_ee/vac.ico', 40, 40, 'shape=vac;labelPosition=left;align=right','Name=Vac;DC=0 V;ACMAG=1 V;ACPHASE=0 deg;');
addVertex_2('static/schematic/icon_ee/vsin.ico', 40, 40, 'shape=vsin;labelPosition=left;align=right','Name=Vsin;V0=0 V;VA=1 V;FREQ=1k Hz;TD=0 ;THEAT=0 ;PHASE=0 ;');
addVertex_2('static/schematic/icon_ee/vpulse.ico', 40, 40, 'shape=vpulse;labelPosition=left;align=right','Name=Vpulse;V1=0 V;V2=1 V;TD=0u s;TR=0u s;TF=0u s;PW=10u s;PER=20u s;');
toolbar.addLine();
click_handler(graph);
ports_handler(graph);
style_handler(graph);
Clipboard_Handler(graph);
bottom_bar(graph);
// create a window
var lorem_1 = "Welcom to use CZ_SPICE,here is the user help manual !";
var lorem_2 = "To be continued......";
var content = document.createElement('div');
mxUtils.writeln(content, lorem_1);
mxUtils.writeln(content, lorem_2);
wnd = new mxWindow('Help', content, 520, 50, 220, 200, true, true);
wnd.setMaximizable(true);
wnd.setScrollable(true);
wnd.setResizable(true);
wnd.setVisible(true);
wnd.setClosable(true);
showOutline(graph);
// mxLog.show();
}
}
</script>
<script type="text/javascript">
// 获取属性
function ParseAttribute(value)
{
value = value||"Name=unknown;" ;
// value = value.toLowerCase();
var attribute = {} ;
v = value.replace(" ","");
var v_split = v.split(";");
for(var i = 0; i<v_split.length; i++)
{
if(v_split[i].length > 0)
{
var pro = v_split[i].split("=");
attribute[pro[0]] = pro[1];
}
}
return attribute;
};
// 初步从xml中提取有用信息
function ParseSpice(circuit_xml){
var encoder = new mxCodec();
var node = encoder.encode(circuit_xml);
var content = "";
var term = "";
let reg_1 = /<mxcell.+?\/>/ig;
let reg_2 = /<mxcell.+?\/mxcell>/ig;
let reg_3 = /<mxGeometry.+?\/>/ig;
let reg_4 = /<mxGeometry.+?<\/mxGeometry>/ig;
let reg_5 = /vertex="1"/ig;
let reg_id = /id="(.*?)"/i;
let reg_value = /value="(.+?)"/i;
let reg_style = /style="(.+?)"/i;
let reg_parent = /parent="(.+?)"/i;
let reg_edge = /edge="(.+?)"/i;
let reg_source = /source="(.+?)"/i;
let reg_target = /target="(.+?)"/i;
let element_list = [];
let wires_list = [];
let element = [];
let wires = [];
let result = {};
content += mxUtils.getXml(node);
// remove heading text
term = content.match(reg_1);
content = content.replace(term[0],'');
content = content.replace(term[1],'');
// remove each element_list's geometry
term = content.match(reg_2);
for(var i=0 ; i<term.length; i++){
var geometry = term[i].match(reg_4);
if(geometry != null){
term[i] = term[i].replace(geometry,'');
}
else{
geometry = term[i].match(reg_3);
term[i] = term[i].replace(geometry,'');
}
}
// remove some text
for(var i=0; i<term.length; i++){
term[i] = term[i].replace("<mxCell","");
term[i] = term[i].replace("</mxCell>","");
term[i] = term[i].replace(">","");
}
// divide term into element_list and wires_list
for(var i=0 ; i<term.length; i++){
var vertex = term[i].match(reg_5);
if(vertex != null){
term[i] = term[i].replace(vertex,"")
element_list.push(term[i]);
}
else{
wires_list.push(term[i]);
}
}
// full elements
for(var i=0; i<element_list.length; i++){
let ele = {};
let ele_v = {};
let ele_s = {};
let temp_ele ;
// get id
ele['id'] = element_list[i].match(reg_id)[1] ;
// get value
temp_ele = element_list[i].match(reg_value)[1] ;
temp_ele = temp_ele.split(";");
for(var j=0; j<temp_ele.length ;j++){
let tem = temp_ele[j].split("=");
ele_v[tem[0]] = tem[1];
}
ele['value'] = ele_v ;
// get style
temp_ele = element_list[i].match(reg_style)[1] ;
temp_ele = temp_ele.split(";");
for(var j=0; j<temp_ele.length; j++){
let tem = temp_ele[j].split("=");
ele_s[tem[0]] = tem[1];
}
ele['style'] = ele_s ;
// get parent
ele['parent'] = element_list[i].match(reg_parent)[1] ;
element.push(ele);
}
// full wires
for(var i=0; i<wires_list.length ; i++){
let ele = {};
let ele_s = {};
let temp_ele ;
// get id
ele['id'] = wires_list[i].match(reg_id)[1] ;
// get style
temp_ele = wires_list[i].match(reg_style)[1] ;
temp_ele = temp_ele.split(";");
for(var j=0; j<temp_ele.length; j++){
let tem = temp_ele[j].split("=");
ele_s[tem[0]] = tem[1];
}
ele['style'] = ele_s ;
// get edge
ele['edge'] = wires_list[i].match(reg_edge)[1];
// get source
ele['source'] = wires_list[i].match(reg_source)[1];
// get target
ele['target'] = wires_list[i].match(reg_target)[1];
wires.push(ele);
}
result['elements'] = element;
result['wires'] = wires;
return result ;
};
function NormalizeXML(info){
let circuit = [];
let netlist = [];
let nodes = [];
for(var i=0; i<info['elements'].length; i++)
{
let temp = {};
temp['id'] = info['elements'][i]['id'];
temp['name'] = info['elements'][i]['value']['Name'];
temp['type'] = info['elements'][i]['style']['shape'];
if(temp['type'] == 'vdd'){
temp['port'] = {'vdd': 'vdd'};
temp['port_keys'] = ['vdd'];
}
else if(temp['type'] == 'gnd'){
temp['port'] = {'gnd': 'gnd'};
temp['port_keys'] = ['gnd'];
}
else if(temp['type'] == 'n_mosfet' || temp['type'] == 'p_mosfet'){
temp['port'] = {'drain': 'd', 'gate': 'g', 'source': 's', 'bulk': 's' };
temp['port_keys'] = ['drain','gate','source','bulk'];
temp['value'] = {'model' : info['elements'][i]['value']['Model'],
'length': info['elements'][i]['value']['Length'],
'width' : info['elements'][i]['value']['Width']};
}
else if(temp['type'] == 'resistor'){
temp['port'] = {'pos':'pos', 'neg':'neg'};
temp['port_keys'] = ['pos','neg'];
temp['value'] = {'value': info['elements'][i]['value']['Value']}
}
else if(temp['type'] == 'capacitor'){
temp['port'] = {'pos':'pos', 'neg':'neg'};
temp['port_keys'] = ['pos','neg'];
temp['value'] = {'value': info['elements'][i]['value']['Value']}
}
else if(temp['type'] == 'pin'){
temp['port'] = {'pin': 'pin'};
temp['port_keys'] = ['pin'];
}
else if(temp['type'] == 'pout'){
temp['port'] = {'pout': 'pout'};
temp['port_keys'] = ['pout'];
}
else if(temp['type'] == 'vdc'){
temp['port'] = {'pos': 'pos', 'neg':'neg'};
temp['port_keys'] = ['pos','neg'];
temp['value'] = {'DC': info['elements'][i]['value']['DC'] }
}
else if(temp['type'] == 'vac'){
temp['port'] = {'pos': 'pos', 'neg':'neg'};
temp['port_keys'] = ['pos','neg'];
temp['value'] = {'ACMAG': info['elements'][i]['value']['ACMAG'],
'ACPHASE': info['elements'][i]['value']['ACPHASE'],
'DC':info['elements'][i]['value']['DC']}
}
else if(temp['type'] == 'vsin'){
temp['port'] = {'pos': 'pos', 'neg':'neg'};
temp['port_keys'] = ['pos','neg'];
temp['value'] = {'V0': info['elements'][i]['value']['V0'],
'VA': info['elements'][i]['value']['VA'],
'FREQ': info['elements'][i]['value']['FREQ'],
'TD': info['elements'][i]['value']['TD'],
'THEAT': info['elements'][i]['value']['THEAT'],
'PHASE': info['elements'][i]['value']['PHASE']
}
}
else if(temp['type'] == 'vpulse'){
temp['port'] = {'pos': 'pos', 'neg':'neg'};
temp['port_keys'] = ['pos','neg'];
temp['value'] = {'V1': info['elements'][i]['value']['V1'],
'V2': info['elements'][i]['value']['V2'],
'TD': info['elements'][i]['value']['TD'],
'TR': info['elements'][i]['value']['TR'],
'TF': info['elements'][i]['value']['TF'],
'PW': info['elements'][i]['value']['PW'],
'PER': info['elements'][i]['value']['PER']
}
}
circuit.push(temp);
}
for(var i=0; i<info['wires'].length; i++)
{
let temp = {};
temp['id'] = info['wires'][i]['id'];
temp['node_source'] = info['wires'][i]['source'] +" "+ info['wires'][i]['style']['sourcePort'];
temp['node_target'] = info['wires'][i]['target'] +" ";
if(info['wires'][i]['style']['targetPort'] != null){
temp['node_target'] += info['wires'][i]['style']['targetPort'];
}
else{
temp['node_target'] += 'null';
}
netlist.push(temp);
}
for(var i=0; i<netlist.length; i++){
let temp = [];
let index_s = 0;
let index_t = 0;
let source = netlist[i]['node_source'];
let target = netlist[i]['node_target'];
if(target.indexOf('null') != -1){
let target_id = target.split(" ")[0];
let index_id = SearchID(netlist,target_id);
index_s = SearchExit(nodes,netlist[index_id]['node_source']);
if(index_s == -1){
index_t = SearchExit(nodes,netlist[index_id]['node_target']);
if(index_t == -1){
temp.push(source);
temp.push(netlist[index_id]['node_source']);
temp.push(netlist[index_id]['node_target']);
nodes.push(temp);
}
else{
nodes[index_t].push(source);
}
}
else{
nodes[index_s].push(source);
}
}
else{
index_s = SearchExit(nodes,source);
index_t = SearchExit(nodes,target);
if(index_s == -1){
if(index_t == -1){
temp.push(source);
temp.push(target);
nodes.push(temp);
}
else{
nodes[index_t].push(source);
}
}
else{
if(index_t == -1){
nodes[index_s].push(target);
}
}
}
}
let count = 1 ;
let node_str = '';
let flag_gnd = false;
let flag_vdd = false;
for(var i=0; i<nodes.length; i++){
node_str = String(count);
for(var j=0; j<nodes[i].length; j++){
let node_info = nodes[i][j].split(" ");
let node_id = node_info[0];
let node_port = node_info[1];
let node_index = SearchID(circuit,node_id);
if(node_port == 'gnd'){
flag_gnd = true;
}
else if(node_port == 'vdd'){
flag_vdd = true ;
}
else{
if(node_index != -1){
circuit[node_index]['port'][node_port] = node_str;
if(node_port == 'source'){
circuit[node_index]['port']['bulk'] = circuit[node_index]['port']['source'];
}
}
}
}
if(flag_gnd){
flag_gnd = false;
for(var j=0; j<nodes[i].length; j++){
let node_info = nodes[i][j].split(" ");
let node_id = node_info[0];
let node_port = node_info[1];
let node_index = SearchID(circuit,node_id);
node_str = "0";
if(node_index != -1){
circuit[node_index]['port'][node_port] = node_str;
if(node_port == 'source'){
circuit[node_index]['port']['bulk'] = circuit[node_index]['port']['source'];
}
}
}
}
else if(flag_vdd){
flag_vdd = false;
for(var j=0; j<nodes[i].length; j++){
let node_info = nodes[i][j].split(" ");
let node_id = node_info[0];
let node_port = node_info[1];
let node_index = SearchID(circuit,node_id);
node_str = "vdd";
if(node_index != -1){
circuit[node_index]['port'][node_port] = node_str;
if(node_port == 'source'){
circuit[node_index]['port']['bulk'] = circuit[node_index]['port']['source'];
}
}
}
}
else{
count += 1;
}
}
return circuit;
};
function SearchID(array,id){
for(var i=0; i<array.length; i++){
if(array[i]['id'] == id){
return i;
}
}
return -1;
}
function SearchExit(array,element){
for(var i=0; i<array.length; i++){
if(array[i].includes(element)){
return i;
}
}
return -1;
};
// 根据从xml提取出来的info生成spice网表
function ExtractSpice(circuit){
let spice = "";
let key ;
for(var i=0; i<circuit.length;i++){
spice += circuit[i]['name'] + " ";
for(var j=0; j<circuit[i]['port_keys'].length; j++){
spice += circuit[i]['port'][circuit[i]['port_keys'][j]] + " ";
}
spice += circuit[i]['type'] + " ";
for(key in circuit[i]['value']){
spice += circuit[i]['value'][key] + " ";
}
spice += "\n";
}
return spice;
};
// 根据从xml提取出来的info生成spice网表
function ExtractSpice_2(circuit){
let spice = "";
let key ;
for(var i=0; i<circuit.length;i++){
if((circuit[i]['type']=='gnd') || (circuit[i]['type']=='vdd')){
continue;
}
else if((circuit[i]['type']=='pin') || (circuit[i]['type']=='pout')){
continue;
}
else if((circuit[i]['type']=='p_mosfet') || (circuit[i]['type']=='n_mosfet')){
spice += circuit[i]['name'] + " ";
for(var j=0; j<circuit[i]['port_keys'].length; j++){
spice += circuit[i]['port'][circuit[i]['port_keys'][j]] + " ";
}
spice += circuit[i]['value']['model'] + " ";
spice += 'l=' + circuit[i]['value']['length'] + " ";
spice += 'w=' + circuit[i]['value']['width'] + " ";
spice += "\n";
}
else if(circuit[i]['type']=='vdc'){
spice += circuit[i]['name'] + " ";
for(var j=0; j<circuit[i]['port_keys'].length; j++){
spice += circuit[i]['port'][circuit[i]['port_keys'][j]] + " ";
}
spice += 'DC' + " ";
spice += (circuit[i]['value']['DC'].replace(" ","")).replace("V","") + " ";
spice += "\n";
}
else if(circuit[i]['type']=='vac'){
spice += circuit[i]['name'] + " ";
for(var j=0; j<circuit[i]['port_keys'].length; j++){
spice += circuit[i]['port'][circuit[i]['port_keys'][j]] + " ";
}
spice += 'DC' + " ";
spice += (circuit[i]['value']['DC'].replace(" ","")).replace("V","") + " ";
spice += 'AC' + " ";
spice += (circuit[i]['value']['ACMAG'].replace(" ","")).replace("V","") + " ";
if(circuit[i]['value']['ACPHASE'].replace(" ","").replace("deg","") != "0"){
spice += circuit[i]['value']['ACPHASE'].replace(" ","").replace("deg","") + " ";
}
spice += "\n";
}
else if(circuit[i]['type']=='vsin'){
spice += circuit[i]['name'] + " ";
for(var j=0; j<circuit[i]['port_keys'].length; j++){
spice += circuit[i]['port'][circuit[i]['port_keys'][j]] + " ";
}
spice += "SIN(" + " ";
spice += circuit[i]['value']['V0'].replace(" ","").replace("V","") + " ";
spice += circuit[i]['value']['VA'].replace(" ","").replace("V","") + " ";
spice += circuit[i]['value']['FREQ'].replace(" ","").replace("Hz","") + " ";
spice += ")";
spice += "\n";
}
else if(circuit[i]['type']=='vpulse'){
spice += circuit[i]['name'] + " ";
for(var j=0; j<circuit[i]['port_keys'].length; j++){
spice += circuit[i]['port'][circuit[i]['port_keys'][j]] + " ";
}
spice += "PULSE(" + " ";
for(key in circuit[i]['value']){
spice += circuit[i]['value'][key].replace(" ","") + " ";
}
spice += ")";
spice += "\n";
}
else{
spice += circuit[i]['name'] + " ";
for(var j=0; j<circuit[i]['port_keys'].length; j++){
spice += circuit[i]['port'][circuit[i]['port_keys'][j]] + " ";
}
spice += circuit[i]['type'] + " ";
for(key in circuit[i]['value']){
spice += circuit[i]['value'][key] + " ";
}
spice += "\n";
}
}
return spice;
};
function get_spice(graph){
var node = ParseSpice(graph.getModel());
var circuit = NormalizeXML(node);
let spice = ExtractSpice_2(circuit);
return spice;
};
</script>
<!-- Simulator 窗口模式选择 -->
<script>
function openMode(evt, tabMode) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
document.getElementById(tabMode).style.display = "block";
evt.currentTarget.className += " active";
};
</script>
<!-- 向服务器传递数据 -->
<script type="text/javascript">
function ajax_message(data) {
var data = new Object();
data["name"] = "XerCis";
data["message"] = "This is the message from ajax(spice2) !";
$.ajax({
type: 'POST',
url: "/test",
data: data,
success: function (response) {
alert(response);
}
});
}
// 由于ajax传递参数时无法直接进行List的传递故将属性List转换为了string然后进行传递
function Simulator(sim_type, spice){
// var properties = [];
var properties_send = "";
var sel = $("#"+sim_type+" input");
// alert(sim_type);
sel.each(function(){
var new_element = {};
var n = $(this)[0].name;
var v = $(this)[0].value;
properties_send += n + "=" + v + ";";
// new_element[n] = v ;
// properties.push(new_element);
});
var data = new Object();
data["sim_type"] = sim_type;
data["properties"] = properties_send;
data['spice'] = spice;
// alert(spice);
// for(var i=0; i<properties.length; i++){
// var key = Object.keys(properties[i])[0];
// var val = Object.values(properties[i])[0];
// alert(key + " "+ val);
// }
$.ajax({
type: 'POST',
url: "/simulation",
data: data,
success: function (response) {
alert(response);
}
});
};
</script>
<script type="text/javascript">
function showProperties(graph,cell)
{
cell = cell || graph.getSelectionCell();
// Uses the root node for the properties dialog
// if not cell was passed in and no cell is
// selected
if (cell == null)
{
cell = graph.getCurrentRoot();
if (cell == null)
{
cell = graph.getModel().getRoot();
}
}
if (cell != null)
{
// Makes sure there is no in-place editor in the
// graph and computes the location of the dialog
graph.stopEditing(true);
var form = new mxForm('properties');
var id = form.addText('ID', cell.getId());
id.setAttribute('readonly', 'true');
var value = cell.getValue();
var attribute = ParseAttribute(value);
var Text_attribute = {};
for(x in attribute){
Text_attribute[x] = form.addText(x, attribute[x]);
}
// var value_cell = form.addText('value', cell.getValue());
function AssembleAttribute(){
var Str_attribute = '';
for(x in attribute){
Str_attribute += x + '=' + Text_attribute[x].value + ';';
}
return Str_attribute ;
}
var okFunction = mxUtils.bind(this, function(){
cell.setValue(AssembleAttribute());
// graph.cellLabelChanged(cell,AssembleAttribute(),false);
wnd.destroy();
// cell.value = value ;
});
var cancelFunction = mxUtils.bind(this, function()
{
// Hides the dialog
wnd.destroy();
});
form.addButtons(okFunction, cancelFunction);
var wnd = new mxWindow(
'Properties',
form.table, 800, 320, 200, 150, true,true);
wnd.setMaximizable(true);
wnd.setScrollable(true);
wnd.setResizable(true);
wnd.setVisible(true);
wnd.setClosable(true);
}
};
</script>
<script type="text/javascript">
function showOutline(graph)
{
var create = true;
if (create)
{
var div = document.createElement('div');
div.style.overflow = 'hidden';
div.style.position = 'relative';
div.style.width = '100%';
div.style.height = '100%';
div.style.background = 'white';
div.style.cursor = 'move';
if (document.documentMode == 8)
{
div.style.filter = 'progid:DXImageTransform.Microsoft.alpha(opacity=100)';
}
var wnd = new mxWindow(
'Outline',
div, 1000, 20, 200, 150, false);
// Creates the outline in the specified div
// and links it to the existing graph
var outline = new mxOutline(graph, div);
wnd.setMaximizable(true);
wnd.setScrollable(true);
wnd.setVisible(true);
wnd.setClosable(true);
wnd.setResizable(true);
wnd.destroyOnClose = false;
wnd.addListener(mxEvent.RESIZE_END, function()
{
outline.update();
});
this.outline = wnd;
this.outline.outline = outline;
}
// Finally shows the outline
this.outline.setVisible(true);
this.outline.outline.update(true);
};
</script>
<script type="text/javascript">
function addToolbarItem(graph, toolbar, prototype, image)
{
// Function that is executed when the image is dropped on
// the graph. The cell argument points to the cell under
// the mousepointer if there is one.
var funct = function(graph, evt, cell)
{
graph.stopEditing(false);
var pt = graph.getPointForEvent(evt);
var vertex = graph.getModel().cloneCell(prototype);
vertex.geometry.x = pt.x;
vertex.geometry.y = pt.y;
graph.setSelectionCells(graph.importCells([vertex], 0, 0, cell));
}
// Creates the image which is used as the drag icon (preview)
var img = toolbar.addMode(null, image, funct);
mxUtils.makeDraggable(img, graph, funct);
}
</script>
<script type="text/javascript">
// Function to create the entries in the popupmenu
function createPopupMenu(graph, menu, cell, evt)
{
if (cell != null)
{
menu.addItem('Properities', 'static/schematic/editors/images/image.gif', function()
{
showProperties(graph,cell);
});
}
else
{
menu.addItem('No-Cell Item', 'static/schematic/editors/images/image.gif', function()
{
mxUtils.alert('MenuItem2');
});
}
menu.addSeparator();
menu.addItem('MenuItem3', 'static/schematic/src/images/warning.gif', function()
{
mxUtils.alert('MenuItem3: '+graph.getSelectionCount()+' selected');
});
};
</script>
<!-- click listener -->
<script type="text/javascript">
function click_handler(graph){
// Installs a handler for click events in the graph
// that toggles the overlay for the respective cell
graph.addListener(mxEvent.CLICK, function(sender, evt)
{
// var cell = evt.getProperty('cell');
// if (cell != null)
// {
// var overlays = graph.getCellOverlays(cell);
// if (overlays == null)
// {
// // Creates a new overlay with an image and a tooltip
// var overlay = new mxCellOverlay(
// new mxImage('editors/images/overlays/check.png', 16, 16),
// 'Overlay tooltip');
// // Installs a handler for clicks on the overlay
// overlay.addListener(mxEvent.CLICK, function(sender, evt2)
// {
// mxUtils.alert('Overlay clicked');
// });
// // Sets the overlay for the cell in the graph
// graph.addCellOverlay(cell, overlay);
// }
// else
// {
// graph.removeCellOverlays(cell);
// }
// }
});
// Installs a handler for double click events in the graph
// that shows an alert box
graph.addListener(mxEvent.DOUBLE_CLICK, function(sender, evt)
{
var cell = evt.getProperty('cell');
showProperties(graph,cell);
// var cell = evt.getProperty('cell');
// mxUtils.alert('Doubleclick: '+((cell != null) ? 'Cell' : 'Graph'));
// evt.consume();
});
}
</script>
<script type="text/javascript">
function bottom_bar(graph){
document.body.appendChild(mxUtils.button('Zoom In', function()
{
graph.zoomIn();
}));
document.body.appendChild(mxUtils.button('Zoom Out', function()
{
graph.zoomOut();
}));
document.body.appendChild(mxUtils.button('Zoom Actual', function()
{
graph.zoomActual();
}));
// Undo/redo
var undoManager = new mxUndoManager();
var listener = function(sender, evt)
{
undoManager.undoableEditHappened(evt.getProperty('edit'));
};
graph.getModel().addListener(mxEvent.UNDO, listener);
graph.getView().addListener(mxEvent.UNDO, listener);
document.body.appendChild(mxUtils.button('Undo', function()
{
undoManager.undo();
}));
document.body.appendChild(mxUtils.button('Redo', function()
{
undoManager.redo();
}));
document.body.appendChild(mxUtils.button('Delete', function()
{
graph.removeCells();
}));
document.body.appendChild(mxUtils.button('FlipH', function()
{
graph.toggleCellStyles(mxConstants.STYLE_FLIPH);
}));
document.body.appendChild(mxUtils.button('FlipV', function()
{
graph.toggleCellStyles(mxConstants.STYLE_FLIPV);
}));
document.body.appendChild(mxUtils.button('Rotate', function()
{
var cell = graph.getSelectionCell();
if (cell != null)
{
var geo = graph.getCellGeometry(cell);
if (geo != null)
{
graph.getModel().beginUpdate();
try
{
// Rotates the size and position in the geometry
geo = geo.clone();
geo.x += geo.width / 2 - geo.height / 2;
geo.y += geo.height / 2 - geo.width / 2;
var tmp = geo.width;
geo.width = geo.height;
geo.height = tmp;
graph.getModel().setGeometry(cell, geo);
// Reads the current direction and advances by 90 degrees
var state = graph.view.getState(cell);
if (state != null)
{
var dir = state.style[mxConstants.STYLE_DIRECTION] || 'east'/*default*/;
if (dir == 'east')
{
dir = 'south';
}
else if (dir == 'south')
{
dir = 'west';
}
else if (dir == 'west')
{
dir = 'north';
}
else if (dir == 'north')
{
dir = 'east';
}
graph.setCellStyles(mxConstants.STYLE_DIRECTION, dir, [cell]);
}
}
finally
{
graph.getModel().endUpdate();
}
}
}
}));
document.body.appendChild(mxUtils.button('Show info', function()
{
var node = ParseSpice(graph.getModel());
var circuit = NormalizeXML(node);
let spice = ExtractSpice(circuit);
mxUtils.popup(spice, true);
}));
document.body.appendChild(mxUtils.button('Show Spice', function()
{
var node = ParseSpice(graph.getModel());
var circuit = NormalizeXML(node);
let spice = ExtractSpice_2(circuit);
mxUtils.popup(spice, true);
}));
document.body.appendChild(mxUtils.button('Send Spice', function()
{
var node = ParseSpice(graph.getModel());
var circuit = NormalizeXML(node);
let spice = ExtractSpice_2(circuit);
var data = new Object();
data["name"] = "Spice";
data["spice"] = spice;
$.ajax({
type: 'POST',
url: "/spice",
data: data,
success: function (response) {
alert(response);
}
});
}));
document.body.appendChild(mxUtils.button('simulator', function(){
// let spice = get_spice(graph);
var frame = document.createElement('div');
frame.setAttribute('id','bokeh_02');
// var x = document.createElement('script');
// x.setAttribute('src','static/spice/bokeh_02.js');
// frame.appendChild(x);
var div_tab = document.createElement('div');
div_tab.setAttribute('class','tab');
var sim_mode = ['transient', 'dc', 'ac'];
var sim_mode_content = {
'transient': {
"key" :[ 'step_time', 'end_time', 'start_time','max_time','use_initial_condition'],
"value" :[ '0.1 us', '20 us', '0', 'None', 'False']
},
'dc': {
"key" :[ "src","start","stop","step"],
"value" :[ "","","",""]
},
'ac': {
"key" :[ "variation", "number_of_points", "start_frequency", "stop_frequency"],
"value" :[ "","","",""]
}
};
for(var i=0; i<sim_mode.length; i++){
var div_mode = document.createElement('button');
div_mode.setAttribute('class',"tablinks");
div_mode.setAttribute('onclick',"openMode(event, '"+ sim_mode[i] +"')");
div_mode.innerHTML = sim_mode[i] ;
div_tab.appendChild(div_mode);
}
frame.appendChild(div_tab);
for(var i=0; i<sim_mode.length; i++){
var div_mode = document.createElement('div');
div_mode.setAttribute('class',"tabcontent");
div_mode.setAttribute('id',sim_mode[i]);
var div_h3 = document.createElement('h3');
div_h3.innerHTML = sim_mode[i];
div_mode.appendChild(div_h3);
var table = document.createElement('table');
var the_mode = sim_mode_content[sim_mode[i]];
for(var j=0; j<the_mode['key'].length; j++ ){
var form_div = document.createElement('tr');
var td_name = document.createElement('td');
td_name.innerHTML = the_mode['key'][j] ;
form_div.appendChild(td_name);
var td_input = document.createElement('td');
var input = document.createElement('input');
input.setAttribute('name', the_mode['key'][j]);
input.setAttribute("class","simulator_input");
input.setAttribute('type', "text");
input.setAttribute('value', the_mode['value'][j] );
td_input.appendChild(input);
form_div.appendChild(td_input);
table.appendChild(form_div);
}
var confirm = document.createElement('button');
confirm.setAttribute("type","submit");
confirm.setAttribute("class",sim_mode[i]);
// confirm.setAttribute('onclick',"Simulator('"+sim_mode[i] +"'; ");
confirm.onclick = function(){
let spice = get_spice(graph);
Simulator(this.className,spice);
};
confirm.innerHTML = "Confirm";
table.appendChild(confirm);
div_mode.appendChild(table);
frame.appendChild(div_mode);
};
var w = document.body.clientWidth;
var h = (document.body.clientHeight || document.documentElement.clientHeight);
var wnd = new mxWindow('Title', frame, (w-200)/2, (h-200)/3, 400, 400, true, true);
wnd.setVisible(true);
wnd.setScrollable(true);
wnd.setResizable(true);
wnd.setVisible(true);
wnd.setClosable(true);
}));
document.body.appendChild(mxUtils.button('show result', function()
{
var frame = document.createElement('div');
frame.setAttribute('id','bokeh_01');
var x = document.createElement('script');
x.setAttribute('src','static/spice/show_result.js');
frame.appendChild(x);
var w = document.body.clientWidth;
var h = (document.body.clientHeight || document.documentElement.clientHeight);
var wnd = new mxWindow('Title', frame, (w-200)/2, (h-200)/3, 400, 400, true, true);
wnd.setVisible(true);
wnd.setScrollable(true);
wnd.setResizable(true);
wnd.setVisible(true);
wnd.setClosable(true);
}));
// Wire-mode
var checkbox = document.createElement('input');
checkbox.setAttribute('type', 'checkbox');
document.body.appendChild(checkbox);
mxUtils.write(document.body, 'Wire Mode');
// Starts connections on the background in wire-mode
var connectionHandlerIsStartEvent = graph.connectionHandler.isStartEvent;
graph.connectionHandler.isStartEvent = function(me)
{
return checkbox.checked || connectionHandlerIsStartEvent.apply(this, arguments);
};
// Avoids any connections for gestures within tolerance except when in wire-mode
// or when over a port
var connectionHandlerMouseUp = graph.connectionHandler.mouseUp;
graph.connectionHandler.mouseUp = function(sender, me)
{
if (this.first != null && this.previous != null)
{
var point = mxUtils.convertPoint(graph.container, me.getX(), me.getY());
var dx = Math.abs(point.x - this.first.x);
var dy = Math.abs(point.y - this.first.y);
if (dx < graph.tolerance && dy < graph.tolerance)
{
// Selects edges in non-wire mode for single clicks, but starts
// connecting for non-edges regardless of wire-mode
if (!checkbox.checked && graph.getModel().isEdge(this.previous.cell))
{
this.reset();
}
return;
}
}
connectionHandlerMouseUp.apply(this, arguments);
};
// Grid
var checkbox2 = document.createElement('input');
checkbox2.setAttribute('type', 'checkbox');
checkbox2.setAttribute('checked', 'true');
document.body.appendChild(checkbox2);
mxUtils.write(document.body, 'Grid');
mxEvent.addListener(checkbox2, 'click', function(evt)
{
if (checkbox2.checked)
{
container.style.background = 'url(\'static/schematic/images/wires-grid.gif\')';
}
else
{
container.style.background = '';
}
container.style.backgroundColor = (invert) ? 'black' : 'white';
});
mxEvent.disableContextMenu(container);
};
</script>
<script type="text/javascript">
function style_handler(graph){
// Switch for black background and bright styles
var invert = false;
if (invert)
{
container.style.backgroundColor = 'black';
// White in-place editor text color
mxCellEditorStartEditing = mxCellEditor.prototype.startEditing;
mxCellEditor.prototype.startEditing = function (cell, trigger)
{
mxCellEditorStartEditing.apply(this, arguments);
if (this.textarea != null)
{
this.textarea.style.color = '#FFFFFF';
}
};
mxGraphHandler.prototype.previewColor = 'white';
}
var joinNodeSize = 7;
var strokeWidth = 2;
var labelBackground = (invert) ? '#000000' : '#FFFFFF';
var fontColor = (invert) ? '#FFFFFF' : '#000000';
var strokeColor = (invert) ? '#C0C0C0' : '#000000';
var fillColor = (invert) ? 'none' : '#FFFFFF';
var style = graph.getStylesheet().getDefaultEdgeStyle();
delete style['endArrow'];
style['strokeColor'] = strokeColor;
style['labelBackgroundColor'] = labelBackground;
style['edgeStyle'] = 'wireEdgeStyle';
style['fontColor'] = fontColor;
style['fontSize'] = '9';
style['movable'] = '0';
style['strokeWidth'] = strokeWidth;
//style['rounded'] = '1';
// Sets join node size
style['startSize'] = joinNodeSize;
style['endSize'] = joinNodeSize;
style = graph.getStylesheet().getDefaultVertexStyle();
style['gradientDirection'] = 'south';
//style['gradientColor'] = '#909090';
style['strokeColor'] = strokeColor;
//style['fillColor'] = '#e0e0e0';
style['fillColor'] = 'none';
style['fontColor'] = fontColor;
style['fontStyle'] = '1';
style['fontSize'] = '12';
style['resizable'] = '0';
style['rounded'] = '1';
style['strokeWidth'] = strokeWidth;
}
</script>
<script type="text/javascript">
// Computes the position of edge to edge connection points.
mxGraphView.prototype.updateFixedTerminalPoint = function(edge, terminal, source, constraint)
{
var pt = null;
if (constraint != null)
{
pt = this.graph.getConnectionPoint(terminal, constraint);
}
if (source)
{
edge.sourceSegment = null;
}
else
{
edge.targetSegment = null;
}
if (pt == null)
{
var s = this.scale;
var tr = this.translate;
var orig = edge.origin;
var geo = this.graph.getCellGeometry(edge.cell);
pt = geo.getTerminalPoint(source);
// Computes edge-to-edge connection point
if (pt != null)
{
pt = new mxPoint(s * (tr.x + pt.x + orig.x),
s * (tr.y + pt.y + orig.y));
// Finds nearest segment on edge and computes intersection
if (terminal != null && terminal.absolutePoints != null)
{
var seg = mxUtils.findNearestSegment(terminal, pt.x, pt.y);
// Finds orientation of the segment
var p0 = terminal.absolutePoints[seg];
var pe = terminal.absolutePoints[seg + 1];
var horizontal = (p0.x - pe.x == 0);
// Stores the segment in the edge state
var key = (source) ? 'sourceConstraint' : 'targetConstraint';
var value = (horizontal) ? 'horizontal' : 'vertical';
edge.style[key] = value;
// Keeps the coordinate within the segment bounds
if (horizontal)
{
pt.x = p0.x;
pt.y = Math.min(pt.y, Math.max(p0.y, pe.y));
pt.y = Math.max(pt.y, Math.min(p0.y, pe.y));
}
else
{
pt.y = p0.y;
pt.x = Math.min(pt.x, Math.max(p0.x, pe.x));
pt.x = Math.max(pt.x, Math.min(p0.x, pe.x));
}
}
}
// Computes constraint connection points on vertices and ports
else if (terminal != null && terminal.cell.geometry.relative)
{
pt = new mxPoint(this.getRoutingCenterX(terminal),
this.getRoutingCenterY(terminal));
}
// Snaps point to grid
/*if (pt != null)
{
var tr = this.graph.view.translate;
var s = this.graph.view.scale;
pt.x = (this.graph.snap(pt.x / s - tr.x) + tr.x) * s;
pt.y = (this.graph.snap(pt.y / s - tr.y) + tr.y) * s;
}*/
}
edge.setAbsoluteTerminalPoint(pt, source);
};
</script>
<!--
Overrides methods to preview and create new edges.
-->
<script type="text/javascript">
// Sets source terminal point for edge-to-edge connections.
mxConnectionHandler.prototype.createEdgeState = function(me)
{
var edge = this.graph.createEdge();
if (this.sourceConstraint != null && this.previous != null)
{
edge.style = mxConstants.STYLE_EXIT_X+'='+this.sourceConstraint.point.x+';'+
mxConstants.STYLE_EXIT_Y+'='+this.sourceConstraint.point.y+';';
}
else if (this.graph.model.isEdge(me.getCell()))
{
var scale = this.graph.view.scale;
var tr = this.graph.view.translate;
var pt = new mxPoint(this.graph.snap(me.getGraphX() / scale) - tr.x,
this.graph.snap(me.getGraphY() / scale) - tr.y);
edge.geometry.setTerminalPoint(pt, true);
}
return this.graph.view.createState(edge);
};
// Uses right mouse button to create edges on background (see also: lines 67 ff)
mxConnectionHandler.prototype.isStopEvent = function(me)
{
return me.getState() != null || mxEvent.isRightMouseButton(me.getEvent());
};
// Updates target terminal point for edge-to-edge connections.
mxConnectionHandlerUpdateCurrentState = mxConnectionHandler.prototype.updateCurrentState;
mxConnectionHandler.prototype.updateCurrentState = function(me)
{
mxConnectionHandlerUpdateCurrentState.apply(this, arguments);
if (this.edgeState != null)
{
this.edgeState.cell.geometry.setTerminalPoint(null, false);
if (this.shape != null && this.currentState != null &&
this.currentState.view.graph.model.isEdge(this.currentState.cell))
{
var scale = this.graph.view.scale;
var tr = this.graph.view.translate;
var pt = new mxPoint(this.graph.snap(me.getGraphX() / scale) - tr.x,
this.graph.snap(me.getGraphY() / scale) - tr.y);
this.edgeState.cell.geometry.setTerminalPoint(pt, false);
}
}
};
// Updates the terminal and control points in the cloned preview.
mxEdgeSegmentHandler.prototype.clonePreviewState = function(point, terminal)
{
var clone = mxEdgeHandler.prototype.clonePreviewState.apply(this, arguments);
clone.cell = clone.cell.clone();
if (this.isSource || this.isTarget)
{
clone.cell.geometry = clone.cell.geometry.clone();
// Sets the terminal point of an edge if we're moving one of the endpoints
if (this.graph.getModel().isEdge(clone.cell))
{
// TODO: Only set this if the target or source terminal is an edge
clone.cell.geometry.setTerminalPoint(point, this.isSource);
}
else
{
clone.cell.geometry.setTerminalPoint(null, this.isSource);
}
}
return clone;
};
var mxEdgeHandlerConnect = mxEdgeHandler.prototype.connect;
mxEdgeHandler.prototype.connect = function(edge, terminal, isSource, isClone, me)
{
var result = null;
var model = this.graph.getModel();
var parent = model.getParent(edge);
model.beginUpdate();
try
{
result = mxEdgeHandlerConnect.apply(this, arguments);
var geo = model.getGeometry(result);
if (geo != null)
{
geo = geo.clone();
var pt = null;
if (model.isEdge(terminal))
{
pt = this.abspoints[(this.isSource) ? 0 : this.abspoints.length - 1];
pt.x = pt.x / this.graph.view.scale - this.graph.view.translate.x;
pt.y = pt.y / this.graph.view.scale - this.graph.view.translate.y;
var pstate = this.graph.getView().getState(
this.graph.getModel().getParent(edge));
if (pstate != null)
{
pt.x -= pstate.origin.x;
pt.y -= pstate.origin.y;
}
pt.x -= this.graph.panDx / this.graph.view.scale;
pt.y -= this.graph.panDy / this.graph.view.scale;
}
geo.setTerminalPoint(pt, isSource);
model.setGeometry(edge, geo);
}
}
finally
{
model.endUpdate();
}
return result;
};
</script>
<!--
Adds in-place highlighting for complete cell area (no hotspot).
-->
<script type="text/javascript">
mxConnectionHandlerCreateMarker = mxConnectionHandler.prototype.createMarker;
mxConnectionHandler.prototype.createMarker = function()
{
var marker = mxConnectionHandlerCreateMarker.apply(this, arguments);
// Uses complete area of cell for new connections (no hotspot)
marker.intersects = function(state, evt)
{
return true;
};
// Adds in-place highlighting
mxCellHighlightHighlight = mxCellHighlight.prototype.highlight;
marker.highlight.highlight = function(state)
{
if (this.state != state)
{
if (this.state != null)
{
this.state.style = this.lastStyle;
// Workaround for shape using current stroke width if no strokewidth defined
this.state.style['strokeWidth'] = this.state.style['strokeWidth'] || '1';
this.state.style['strokeColor'] = this.state.style['strokeColor'] || 'none';
if (this.state.shape != null)
{
this.state.view.graph.cellRenderer.configureShape(this.state);
this.state.shape.redraw();
}
}
if (state != null)
{
this.lastStyle = state.style;
state.style = mxUtils.clone(state.style);
state.style['strokeColor'] = '#00ff00';
state.style['strokeWidth'] = '3';
if (state.shape != null)
{
state.view.graph.cellRenderer.configureShape(state);
state.shape.redraw();
}
}
this.state = state;
}
};
return marker;
};
mxEdgeHandlerCreateMarker = mxEdgeHandler.prototype.createMarker;
mxEdgeHandler.prototype.createMarker = function()
{
var marker = mxEdgeHandlerCreateMarker.apply(this, arguments);
// Adds in-place highlighting when reconnecting existing edges
marker.highlight.highlight = this.graph.connectionHandler.marker.highlight.highlight;
return marker;
}
</script>
<!--
Adds oval markers for edge-to-edge connections.
-->
<script type="text/javascript">
mxGraphGetCellStyle = mxGraph.prototype.getCellStyle;
mxGraph.prototype.getCellStyle = function(cell)
{
var style = mxGraphGetCellStyle.apply(this, arguments);
if (style != null && this.model.isEdge(cell))
{
style = mxUtils.clone(style);
if (this.model.isEdge(this.model.getTerminal(cell, true)))
{
style['startArrow'] = 'oval';
}
if (this.model.isEdge(this.model.getTerminal(cell, false)))
{
style['endArrow'] = 'oval';
}
}
return style;
};
</script>
<script type="text/javascript">
function ports_handler(graph){
// 禁止拖拽连线
// Disables floating connections (only connections via ports allowed)
// graph.connectionHandler.isConnectableCell = function(cell)
// {
// return false;
// };
// mxEdgeHandler.prototype.isConnectableCell = function(cell)
// {
// return graph.connectionHandler.isConnectableCell(cell);
// };
// Disables existing port functionality
graph.view.getTerminalPort = function(state, terminal, source)
{
return terminal;
};
// Returns all possible ports for a given terminal
graph.getAllConnectionConstraints = function(terminal, source)
{
if (terminal != null && terminal.shape != null &&
terminal.shape.stencil != null)
{
// for stencils with existing constraints...
if (terminal.shape.stencil != null)
{
return terminal.shape.stencil.constraints;
}
}
else if (terminal != null && this.model.isVertex(terminal.cell))
{
if (terminal.shape != null)
{
var ports = terminal.shape.getPorts();
var cstrs = new Array();
for (var id in ports)
{
var port = ports[id];
var cstr = new mxConnectionConstraint(new mxPoint(port.x, port.y), port.perimeter);
cstr.id = id;
cstrs.push(cstr);
}
return cstrs;
}
}
return null;
};
// Makes sure non-relative cells can only be connected via constraints
graph.connectionHandler.isConnectableCell = function(cell)
{
if (this.graph.getModel().isEdge(cell))
{
return true;
}
else
{
var geo = (cell != null) ? this.graph.getCellGeometry(cell) : null;
return (geo != null) ? geo.relative : false;
}
};
mxEdgeHandler.prototype.isConnectableCell = function(cell)
{
return graph.connectionHandler.isConnectableCell(cell);
};
// Sets the port for the given connection
graph.setConnectionConstraint = function(edge, terminal, source, constraint)
{
if (constraint != null)
{
var key = (source) ? mxConstants.STYLE_SOURCE_PORT : mxConstants.STYLE_TARGET_PORT;
if (constraint == null || constraint.id == null)
{
this.setCellStyles(key, null, [edge]);
}
else if (constraint.id != null)
{
this.setCellStyles(key, constraint.id, [edge]);
}
}
};
// Returns the port for the given connection
graph.getConnectionConstraint = function(edge, terminal, source)
{
var key = (source) ? mxConstants.STYLE_SOURCE_PORT : mxConstants.STYLE_TARGET_PORT;
var id = edge.style[key];
if (id != null)
{
var c = new mxConnectionConstraint(null, null);
c.id = id;
return c;
}
return null;
};
// Returns the actual point for a port by redirecting the constraint to the port
graphGetConnectionPoint = graph.getConnectionPoint;
graph.getConnectionPoint = function(vertex, constraint)
{
if (constraint.id != null && vertex != null && vertex.shape != null)
{
var port = vertex.shape.getPorts()[constraint.id];
if (port != null)
{
constraint = new mxConnectionConstraint(new mxPoint(port.x, port.y), port.perimeter);
}
}
return graphGetConnectionPoint.apply(this, arguments);
};
}
</script>
<!-- 复制粘贴剪切删除 -->
<script type="text/javascript">
function Clipboard_Handler(graph){
// Public helper method for shared clipboard.
mxClipboard.cellsToString = function(cells)
{
var codec = new mxCodec();
var model = new mxGraphModel();
var parent = model.getChildAt(model.getRoot(), 0);
for (var i = 0; i < cells.length; i++)
{
model.add(parent, cells[i]);
}
return mxUtils.getXml(codec.encode(model));
};
// Focused but invisible textarea during control or meta key events
var textInput = document.createElement('textarea');
mxUtils.setOpacity(textInput, 0);
textInput.style.width = '1px';
textInput.style.height = '1px';
var restoreFocus = false;
var gs = graph.gridSize;
var lastPaste = null;
var dx = 0;
var dy = 0;
// Workaround for no copy event in IE/FF if empty
textInput.value = ' ';
// Shows a textare when control/cmd is pressed to handle native clipboard actions
mxEvent.addListener(document, 'keydown', function(evt)
{
// No dialog visible
var source = mxEvent.getSource(evt);
if (graph.isEnabled() && !graph.isMouseDown && !graph.isEditing() && source.nodeName != 'INPUT')
{
if (evt.keyCode == 224 /* FF */ || (!mxClient.IS_MAC && evt.keyCode == 17 /* Control */) ||
(mxClient.IS_MAC && (evt.keyCode == 91 || evt.keyCode == 93) /* Left/Right Meta */))
{
// Cannot use parentNode for check in IE
if (!restoreFocus)
{
// Avoid autoscroll but allow handling of events
textInput.style.position = 'absolute';
textInput.style.left = (graph.container.scrollLeft + 10) + 'px';
textInput.style.top = (graph.container.scrollTop + 10) + 'px';
graph.container.appendChild(textInput);
restoreFocus = true;
textInput.focus();
textInput.select();
}
}
}
});
// Restores focus on graph container and removes text input from DOM
mxEvent.addListener(document, 'keyup', function(evt)
{
if (restoreFocus && (evt.keyCode == 224 /* FF */ || evt.keyCode == 17 /* Control */ ||
evt.keyCode == 91 || evt.keyCode == 93 /* Meta */))
{
restoreFocus = false;
if (!graph.isEditing())
{
graph.container.focus();
}
textInput.parentNode.removeChild(textInput);
}
});
// Inserts the XML for the given cells into the text input for copy
var copyCells = function(graph, cells)
{
if (cells.length > 0)
{
var clones = graph.cloneCells(cells);
// Checks for orphaned relative children and makes absolute
for (var i = 0; i < clones.length; i++)
{
var state = graph.view.getState(cells[i]);
if (state != null)
{
var geo = graph.getCellGeometry(clones[i]);
if (geo != null && geo.relative)
{
geo.relative = false;
geo.x = state.x / state.view.scale - state.view.translate.x;
geo.y = state.y / state.view.scale - state.view.translate.y;
}
}
}
textInput.value = mxClipboard.cellsToString(clones);
}
textInput.select();
lastPaste = textInput.value;
};
// Handles copy event by putting XML for current selection into text input
mxEvent.addListener(textInput, 'copy', mxUtils.bind(this, function(evt)
{
if (graph.isEnabled() && !graph.isSelectionEmpty())
{
copyCells(graph, mxUtils.sortCells(graph.model.getTopmostCells(graph.getSelectionCells())));
dx = 0;
dy = 0;
}
}));
// Handles cut event by removing cells putting XML into text input
mxEvent.addListener(textInput, 'cut', mxUtils.bind(this, function(evt)
{
if (graph.isEnabled() && !graph.isSelectionEmpty())
{
copyCells(graph, graph.removeCells());
dx = -gs;
dy = -gs;
}
}));
// Merges XML into existing graph and layers
var importXml = function(xml, dx, dy)
{
dx = (dx != null) ? dx : 0;
dy = (dy != null) ? dy : 0;
var cells = []
try
{
var doc = mxUtils.parseXml(xml);
var node = doc.documentElement;
if (node != null)
{
var model = new mxGraphModel();
var codec = new mxCodec(node.ownerDocument);
codec.decode(node, model);
var childCount = model.getChildCount(model.getRoot());
var targetChildCount = graph.model.getChildCount(graph.model.getRoot());
// Merges existing layers and adds new layers
graph.model.beginUpdate();
try
{
for (var i = 0; i < childCount; i++)
{
var parent = model.getChildAt(model.getRoot(), i);
// Adds cells to existing layers if not locked
if (targetChildCount > i)
{
// Inserts into active layer if only one layer is being pasted
var target = (childCount == 1) ? graph.getDefaultParent() : graph.model.getChildAt(graph.model.getRoot(), i);
if (!graph.isCellLocked(target))
{
var children = model.getChildren(parent);
cells = cells.concat(graph.importCells(children, dx, dy, target));
}
}
else
{
// Delta is non cascading, needs separate move for layers
parent = graph.importCells([parent], 0, 0, graph.model.getRoot())[0];
var children = graph.model.getChildren(parent);
graph.moveCells(children, dx, dy);
cells = cells.concat(children);
}
}
}
finally
{
graph.model.endUpdate();
}
}
}
catch (e)
{
alert(e);
throw e;
}
return cells;
};
// Parses and inserts XML into graph
var pasteText = function(text)
{
var xml = mxUtils.trim(text);
var x = graph.container.scrollLeft / graph.view.scale - graph.view.translate.x;
var y = graph.container.scrollTop / graph.view.scale - graph.view.translate.y;
if (xml.length > 0)
{
if (lastPaste != xml)
{
lastPaste = xml;
dx = 0;
dy = 0;
}
else
{
dx += gs;
dy += gs;
}
// Standard paste via control-v
if (xml.substring(0, 14) == '<mxGraphModel>')
{
graph.setSelectionCells(importXml(xml, dx, dy));
graph.scrollCellToVisible(graph.getSelectionCell());
}
}
};
// Cross-browser function to fetch text from paste events
var extractGraphModelFromEvent = function(evt)
{
var data = null;
if (evt != null)
{
var provider = (evt.dataTransfer != null) ? evt.dataTransfer : evt.clipboardData;
if (provider != null)
{
if (document.documentMode == 10 || document.documentMode == 11)
{
data = provider.getData('Text');
}
else
{
data = (mxUtils.indexOf(provider.types, 'text/html') >= 0) ? provider.getData('text/html') : null;
if (mxUtils.indexOf(provider.types, 'text/plain' && (data == null || data.length == 0)))
{
data = provider.getData('text/plain');
}
}
}
}
return data;
};
// Handles paste event by parsing and inserting XML
mxEvent.addListener(textInput, 'paste', function(evt)
{
// Clears existing contents before paste - should not be needed
// because all text is selected, but doesn't hurt since the
// actual pasting of the new text is delayed in all cases.
textInput.value = '';
if (graph.isEnabled())
{
var xml = extractGraphModelFromEvent(evt);
if (xml != null && xml.length > 0)
{
pasteText(xml);
}
else
{
// Timeout for new value to appear
window.setTimeout(mxUtils.bind(this, function()
{
pasteText(textInput.value);
}), 0);
}
}
textInput.select();
});
// Removes cells when [DELETE] is pressed
var keyHandler = new mxKeyHandler(graph);
keyHandler.bindKey(46, function(evt)
{
if (graph.isEnabled())
{
graph.removeCells();
}
});
}
</script>
<script type="text/javascript">
mxEdgeStyle.WireConnector = function(state, source, target, hints, result)
{
// Creates array of all way- and terminalpoints
var pts = state.absolutePoints;
var horizontal = true;
var hint = null;
// Gets the initial connection from the source terminal or edge
if (source != null && state.view.graph.model.isEdge(source.cell))
{
horizontal = state.style['sourceConstraint'] == 'horizontal';
}
else if (source != null)
{
horizontal = source.style['portConstraint'] != 'vertical';
// Checks the direction of the shape and rotates
var direction = source.style[mxConstants.STYLE_DIRECTION];
if (direction == 'north' || direction == 'south')
{
horizontal = !horizontal;
}
}
// Adds the first point
// TODO: Should move along connected segment
var pt = pts[0];
if (pt == null && source != null)
{
pt = new mxPoint(state.view.getRoutingCenterX(source), state.view.getRoutingCenterY(source));
}
else if (pt != null)
{
pt = pt.clone();
}
var first = pt;
// Adds the waypoints
if (hints != null && hints.length > 0)
{
// FIXME: First segment not movable
/*hint = state.view.transformControlPoint(state, hints[0]);
mxLog.show();
mxLog.debug(hints.length,'hints0.y='+hint.y, pt.y)
if (horizontal && Math.floor(hint.y) != Math.floor(pt.y))
{
mxLog.show();
mxLog.debug('add waypoint');
pt = new mxPoint(pt.x, hint.y);
result.push(pt);
pt = pt.clone();
//horizontal = !horizontal;
}*/
for (var i = 0; i < hints.length; i++)
{
horizontal = !horizontal;
hint = state.view.transformControlPoint(state, hints[i]);
if (horizontal)
{
if (pt.y != hint.y)
{
pt.y = hint.y;
result.push(pt.clone());
}
}
else if (pt.x != hint.x)
{
pt.x = hint.x;
result.push(pt.clone());
}
}
}
else
{
hint = pt;
}
// Adds the last point
pt = pts[pts.length - 1];
// TODO: Should move along connected segment
if (pt == null && target != null)
{
pt = new mxPoint(state.view.getRoutingCenterX(target), state.view.getRoutingCenterY(target));
}
if (horizontal)
{
if (pt.y != hint.y && first.x != pt.x)
{
result.push(new mxPoint(pt.x, hint.y));
}
}
else if (pt.x != hint.x && first.y != pt.y)
{
result.push(new mxPoint(hint.x, pt.y));
}
};
mxStyleRegistry.putValue('wireEdgeStyle', mxEdgeStyle.WireConnector);
// This connector needs an mxEdgeSegmentHandler
mxGraphCreateHandler = mxGraph.prototype.createHandler;
mxGraph.prototype.createHandler = function(state)
{
var result = null;
if (state != null)
{
if (this.model.isEdge(state.cell))
{
var style = this.view.getEdgeStyle(state);
if (style == mxEdgeStyle.WireConnector)
{
return new mxEdgeSegmentHandler(state);
}
}
}
return mxGraphCreateHandler.apply(this, arguments);
};
</script>
<!-- 注册元件属性 -->
<!-- <script type="text/javascript">
// Note that these XML nodes will be enclosing the
// mxCell nodes for the model cells in the output
var doc = mxUtils.createXmlDocument();
var N_Mosfet = doc.createElement('N_Mos');
// N_Mosfet.prototype.vertex = ;
N_Mosfet.setAttribute('Length', '100 nm');
N_Mosfet.setAttribute('Width', '50 nm');
// var P_Mosfet = doc.createElement('P_Mos');
// P_Mosfet.setAttribute('Length', '100 nm');
// P_Mosfet.setAttribute('Width', '50 nm');
</script> -->
<!-- 添加元件图形 -->
<script type="text/javascript">
function ResistorShape() { };
ResistorShape.prototype = new mxCylinder();
ResistorShape.prototype.constructor = ResistorShape;
ResistorShape.prototype.redrawPath = function(path, x, y, w, h, isForeground)
{
var dx = w / 16;
if (isForeground)
{
path.moveTo(0, h / 2);
path.lineTo(2 * dx, h / 2);
path.lineTo(3 * dx, 0);
path.lineTo(5 * dx, h);
path.lineTo(7 * dx, 0);
path.lineTo(9 * dx, h);
path.lineTo(11 * dx, 0);
path.lineTo(13 * dx, h);
path.lineTo(14 * dx, h / 2);
path.lineTo(16 * dx, h / 2);
path.end();
}
};
function N_Mosfet_Shape() { };
N_Mosfet_Shape.prototype = new mxCylinder();
N_Mosfet_Shape.prototype.constructor = N_Mosfet_Shape;
N_Mosfet_Shape.prototype.redrawPath = function(path, x, y, w, h, isForeground)
{
if (isForeground)
{
path.moveTo(w * 0 , h * 1/2);
path.lineTo(w * 3/8, h * 1/2);
path.moveTo(w * 3/8, h * 1/4);
path.lineTo(w * 3/8, h * 3/4);
path.moveTo(w * 5/8, h * 0);
path.lineTo(w * 5/8, h * 1);
path.moveTo(w * 5/8, h * 3/4);
path.lineTo(w * 1 , h * 3/4);
path.moveTo(w * 5/8, h * 1/4);
path.lineTo(w * 1 , h * 1/4);
path.moveTo(w * 13/16, h * 5/8);
path.lineTo(w * 1 , h * 3/4);
path.moveTo(w * 13/16, h * 7/8);
path.lineTo(w * 1 , h * 3/4);
path.end();
}
};
function P_Mosfet_Shape() { };
P_Mosfet_Shape.prototype = new mxCylinder();
P_Mosfet_Shape.prototype.constructor = P_Mosfet_Shape;
P_Mosfet_Shape.prototype.redrawPath = function(path, x, y, w, h, isForeground)
{
if (isForeground)
{
path.moveTo(w * 0 , h * 1/2);
path.lineTo(w * 3/8, h * 1/2);
path.moveTo(w * 3/8, h * 1/4);
path.lineTo(w * 3/8, h * 3/4);
path.moveTo(w * 5/8, h * 0);
path.lineTo(w * 5/8, h * 1);
path.moveTo(w * 5/8, h * 3/4);
path.lineTo(w * 1 , h * 3/4);
path.moveTo(w * 5/8, h * 1/4);
path.lineTo(w * 1 , h * 1/4);
// arrow
path.moveTo(w * 6/8 , h * 3/8);
path.lineTo(w * 5/8 , h * 1/4);
path.moveTo(w * 6/8 , h * 1/8);
path.lineTo(w * 5/8 , h * 1/4);
path.end();
}
};
function Vdd_Shape() { };
Vdd_Shape.prototype = new mxCylinder();
Vdd_Shape.prototype.constructor = Vdd_Shape;
Vdd_Shape.prototype.redrawPath = function(path, x, y, w, h, isForeground)
{
if (isForeground)
{
path.moveTo(w * 0 , h * 0);
path.lineTo(w * 1 , h * 0);
path.moveTo(w * 1/4, h * 1/2);
path.lineTo(w * 3/4, h * 1/2);
path.moveTo(w * 1/2, h * 1/2);
path.lineTo(w * 1/2, h * 1);
path.end();
}
};
function Gnd_Shape() { };
Gnd_Shape.prototype = new mxCylinder();
Gnd_Shape.prototype.constructor = Gnd_Shape;
Gnd_Shape.prototype.redrawPath = function(path, x, y, w, h, isForeground)
{
if (isForeground)
{
path.moveTo(w * 1/2, h * 0);
path.lineTo(w * 1/2, h * 1/2);
path.moveTo(w * 0 , h * 1/2);
path.lineTo(w * 1 , h * 1/2);
path.lineTo(w * 1/2, h * 1);
path.lineTo(w * 0 , h * 1/2);
path.end();
}
};
function Capacitor_Shape() { };
Capacitor_Shape.prototype = new mxCylinder();
Capacitor_Shape.prototype.constructor = Capacitor_Shape;
Capacitor_Shape.prototype.redrawPath = function(path, x, y, w, h, isForeground)
{
if (isForeground)
{
path.moveTo(w * 3/8, h * 0);
path.lineTo(w * 3/8, h * 1);
path.moveTo(w * 3/8, h * 1/2);
path.lineTo(w * 0 , h * 1/2);
path.moveTo(w * 5/8, h * 0);
path.lineTo(w * 5/8, h * 1);
path.moveTo(w * 5/8, h * 1/2);
path.lineTo(w * 1 , h * 1/2);
path.end();
}
};
function Pin_Shape() { };
Pin_Shape.prototype = new mxCylinder();
Pin_Shape.prototype.constructor = Pin_Shape;
Pin_Shape.prototype.redrawPath = function(path, x, y, w, h, isForeground)
{
if (isForeground)
{
path.moveTo(w * 0 , h * 1/4);
path.lineTo(w * 3/4, h * 1/4);
path.lineTo(w * 1 , h * 1/2);
path.lineTo(w * 3/4, h * 3/4);
path.lineTo(w * 0 , h * 3/4);
path.lineTo(w * 0 , h * 1/4);
path.end();
}
};
function Pout_Shape() { };
Pout_Shape.prototype = new mxCylinder();
Pout_Shape.prototype.constructor = Pout_Shape;
Pout_Shape.prototype.redrawPath = function(path, x, y, w, h, isForeground)
{
if (isForeground)
{
path.moveTo(w * 1 , h * 1/4);
path.lineTo(w * 1/4, h * 1/4);
path.lineTo(w * 0 , h * 1/2);
path.lineTo(w * 1/4, h * 3/4);
path.lineTo(w * 1 , h * 3/4);
path.lineTo(w * 1 , h * 1/4);
path.end();
}
};
function Vdc_Shape() { };
Vdc_Shape.prototype = new mxCylinder();
Vdc_Shape.prototype.constructor = Vdc_Shape;
Vdc_Shape.prototype.redrawPath = function(path, x, y, w, h, isForeground)
{
if (isForeground)
{
path.moveTo(w * 1/2, h * 0);
path.lineTo(w * 1/2, h * 1/8);
path.moveTo(w * 1/2, h * 1);
path.lineTo(w * 1/2, h * 7/8);
// path.moveTo(w * 1/2, h * 1/8);
// path.arcTo(3/8*w,3/8*w,180,true,true,w*1/2,h*1/2);
path.moveTo(w * 1/2, h * 1/8);
path.curveTo(w * 1/2, h * 1/8,
w * 7/8, h * 1/8,
w * 7/8, h * 1/2);
path.moveTo(w * 1/2, h * 1/8);
path.curveTo(w * 1/2, h * 1/8,
w * 1/8, h * 1/8,
w * 1/8, h * 1/2);
path.moveTo(w * 1/2, h * 7/8);
path.curveTo(w * 1/2, h * 7/8,
w * 7/8, h * 7/8,
w * 7/8, h * 1/2);
path.moveTo(w * 1/2, h * 7/8);
path.curveTo(w * 1/2, h * 7/8,
w * 1/8, h * 7/8,
w * 1/8, h * 1/2);
path.moveTo(w * 1/2, h * 3/16);
path.lineTo(w * 1/2, h * 7/16);
path.moveTo(w * 3/8, h * 5/16);
path.lineTo(w * 5/8, h * 5/16);
path.moveTo(w * 3/8, h * 11/16);
path.lineTo(w * 5/8, h * 11/16);
path.end();
}
};
function Vac_Shape() { };
Vac_Shape.prototype = new mxCylinder();
Vac_Shape.prototype.constructor = Vac_Shape;
Vac_Shape.prototype.redrawPath = function(path, x, y, w, h, isForeground)
{
if (isForeground)
{
path.moveTo(w * 1/2, h * 0);
path.lineTo(w * 1/2, h * 1/8);
path.moveTo(w * 1/2, h * 1);
path.lineTo(w * 1/2, h * 7/8);
path.moveTo(w * 1/2, h * 1/8);
path.curveTo(w * 1/2, h * 1/8,
w * 7/8, h * 1/8,
w * 7/8, h * 1/2);
path.moveTo(w * 1/2, h * 1/8);
path.curveTo(w * 1/2, h * 1/8,
w * 1/8, h * 1/8,
w * 1/8, h * 1/2);
path.moveTo(w * 1/2, h * 7/8);
path.curveTo(w * 1/2, h * 7/8,
w * 7/8, h * 7/8,
w * 7/8, h * 1/2);
path.moveTo( w * 1/2, h * 7/8);
path.curveTo(w * 1/2, h * 7/8,
w * 1/8, h * 7/8,
w * 1/8, h * 1/2);
// +
path.moveTo(w * 1/2, h * 3/16);
path.lineTo(w * 1/2, h * 7/16);
path.moveTo(w * 3/8, h * 5/16);
path.lineTo(w * 5/8, h * 5/16);
// -
path.moveTo(w * 3/8, h * 11/16);
path.lineTo(w * 5/8, h * 11/16);
// ac
path.moveTo( w * 2/8, h * 9/16);
path.curveTo(w * 2/8, h * 9/16,
w * 2/8 , h * 8/16,
w * 3/8, h * 8/16);
path.moveTo( w * 3/8, h * 8/16);
path.curveTo(w * 3/8, h * 8/16,
w * 4/8 , h * 8/16,
w * 4/8 , h * 9/16);
path.moveTo( w * 4/8, h * 9/16);
path.curveTo(w * 4/8, h * 9/16,
w * 4/8 , h * 10/16,
w * 5/8 , h * 10/16);
path.moveTo( w * 5/8, h * 10/16);
path.curveTo(w * 5/8, h * 10/16,
w * 6/8 , h * 10/16,
w * 6/8 , h * 9/16);
path.end();
}
};
function Vsin_Shape() { };
Vsin_Shape.prototype = new mxCylinder();
Vsin_Shape.prototype.constructor = Vsin_Shape;
Vsin_Shape.prototype.redrawPath = function(path, x, y, w, h, isForeground)
{
if (isForeground)
{
path.moveTo(w * 1/2, h * 0);
path.lineTo(w * 1/2, h * 1/8);
path.moveTo(w * 1/2, h * 1);
path.lineTo(w * 1/2, h * 7/8);
path.moveTo(w * 1/2, h * 1/8);
path.curveTo(w * 1/2, h * 1/8,
w * 7/8, h * 1/8,
w * 7/8, h * 1/2);
path.moveTo(w * 1/2, h * 1/8);
path.curveTo(w * 1/2, h * 1/8,
w * 1/8, h * 1/8,
w * 1/8, h * 1/2);
path.moveTo(w * 1/2, h * 7/8);
path.curveTo(w * 1/2, h * 7/8,
w * 7/8, h * 7/8,
w * 7/8, h * 1/2);
path.moveTo( w * 1/2, h * 7/8);
path.curveTo(w * 1/2, h * 7/8,
w * 1/8, h * 7/8,
w * 1/8, h * 1/2);
// ac
path.moveTo( w * 2/8, h * 9/16);
path.curveTo(w * 2/8, h * 9/16,
w * 2/8 , h * 8/16,
w * 3/8, h * 8/16);
path.moveTo( w * 3/8, h * 8/16);
path.curveTo(w * 3/8, h * 8/16,
w * 4/8 , h * 8/16,
w * 4/8 , h * 9/16);
path.moveTo( w * 4/8, h * 9/16);
path.curveTo(w * 4/8, h * 9/16,
w * 4/8 , h * 10/16,
w * 5/8 , h * 10/16);
path.moveTo( w * 5/8, h * 10/16);
path.curveTo(w * 5/8, h * 10/16,
w * 6/8 , h * 10/16,
w * 6/8 , h * 9/16);
path.end();
}
};
function Vpulse_Shape() { };
Vpulse_Shape.prototype = new mxCylinder();
Vpulse_Shape.prototype.constructor = Vpulse_Shape;
Vpulse_Shape.prototype.redrawPath = function(path, x, y, w, h, isForeground)
{
if (isForeground)
{
path.moveTo(w * 1/2, h * 0);
path.lineTo(w * 1/2, h * 1/8);
path.moveTo(w * 1/2, h * 1);
path.lineTo(w * 1/2, h * 7/8);
path.moveTo(w * 1/2, h * 1/8);
path.curveTo(w * 1/2, h * 1/8,
w * 7/8, h * 1/8,
w * 7/8, h * 1/2);
path.moveTo(w * 1/2, h * 1/8);
path.curveTo(w * 1/2, h * 1/8,
w * 1/8, h * 1/8,
w * 1/8, h * 1/2);
path.moveTo(w * 1/2, h * 7/8);
path.curveTo(w * 1/2, h * 7/8,
w * 7/8, h * 7/8,
w * 7/8, h * 1/2);
path.moveTo( w * 1/2, h * 7/8);
path.curveTo(w * 1/2, h * 7/8,
w * 1/8, h * 7/8,
w * 1/8, h * 1/2);
// pulse
path.moveTo(w * 2/8 , h * 5/8 );
path.lineTo(w * 2/8 , h * 3/8 );
path.lineTo(w * 1/2 , h * 3/8 );
path.lineTo(w * 1/2 , h * 5/8 );
path.lineTo(w * 6/8 , h * 5/8 );
path.lineTo(w * 6/8 , h * 3/8 );
path.end();
}
};
mxCellRenderer.registerShape('resistor' , ResistorShape);
mxCellRenderer.registerShape('n_mosfet' , N_Mosfet_Shape);
mxCellRenderer.registerShape('p_mosfet' , P_Mosfet_Shape);
mxCellRenderer.registerShape('vdd' , Vdd_Shape);
mxCellRenderer.registerShape('gnd' , Gnd_Shape);
mxCellRenderer.registerShape('capacitor', Capacitor_Shape);
mxCellRenderer.registerShape('pin' , Pin_Shape);
mxCellRenderer.registerShape('pout' , Pout_Shape);
mxCellRenderer.registerShape('vdc' , Vdc_Shape);
mxCellRenderer.registerShape('vac' , Vac_Shape);
mxCellRenderer.registerShape('vsin' , Vsin_Shape);
mxCellRenderer.registerShape('vpulse' , Vpulse_Shape);
</script>
<!-- 进行端口限制 -->
<script type="text/javascript">
// Ports are equal for all shapes...
var ports = new Array();
// NOTE: Constraint is used later for orthogonal edge routing (currently ignored)
ports['w'] = {x: 0, y: 0.5, perimeter: true, constraint: 'west'};
ports['e'] = {x: 1, y: 0.5, perimeter: true, constraint: 'east'};
ports['n'] = {x: 0.5, y: 0, perimeter: true, constraint: 'north'};
ports['s'] = {x: 0.5, y: 1, perimeter: true, constraint: 'south'};
ports['nw'] = {x: 0, y: 0, perimeter: true, constraint: 'north west'};
ports['ne'] = {x: 1, y: 0, perimeter: true, constraint: 'north east'};
ports['sw'] = {x: 0, y: 1, perimeter: true, constraint: 'south west'};
ports['se'] = {x: 1, y: 1, perimeter: true, constraint: 'south east'};
// Extends shapes classes to return their ports
mxShape.prototype.getPorts = function()
{
return ports;
};
// ... except for triangles
var ports2 = new Array();
// NOTE: Constraint is used later for orthogonal edge routing (currently ignored)
ports2['in1'] = {x: 0, y: 0, perimeter: true, constraint: 'west'};
ports2['in2'] = {x: 0, y: 0.25, perimeter: true, constraint: 'west'};
ports2['in3'] = {x: 0, y: 0.5, perimeter: true, constraint: 'west'};
ports2['in4'] = {x: 0, y: 0.75, perimeter: true, constraint: 'west'};
ports2['in5'] = {x: 0, y: 1, perimeter: true, constraint: 'west'};
ports2['out1'] = {x: 0.5, y: 0, perimeter: true, constraint: 'north east'};
ports2['out2'] = {x: 1, y: 0.5, perimeter: true, constraint: 'east'};
ports2['out3'] = {x: 0.5, y: 1, perimeter: true, constraint: 'south east'};
mxTriangle.prototype.getPorts = function()
{
return ports2;
};
// for n mosfet
var ports_resistor = new Array();
ports_resistor['pos'] = {x: 0, y: 0.5, perimeter: true, constraint: 'west'};
ports_resistor['neg'] = {x: 1, y: 0.5, perimeter: true, constraint: 'east'};
ResistorShape.prototype.getPorts = function()
{
return ports_resistor;
};
// for n mosfet
var ports_nmosfet = new Array();
ports_nmosfet['gate'] = {x: 0, y: 0.5, perimeter: true, constraint: 'west'};
ports_nmosfet['drain'] = {x: 1, y: 0.25, perimeter: true, constraint: 'east'};
ports_nmosfet['source'] = {x: 1, y: 0.75, perimeter: true, constraint: 'east'};
N_Mosfet_Shape.prototype.getPorts = function(){
return ports_nmosfet;
};
// for p mosfet
var ports_pmosfet = new Array();
ports_pmosfet['gate'] = {x: 0, y: 0.5, perimeter: true, constraint: 'west'};
ports_pmosfet['source'] = {x: 1, y: 0.25, perimeter: true, constraint: 'east'};
ports_pmosfet['drain'] = {x: 1, y: 0.75, perimeter: true, constraint: 'east'};
P_Mosfet_Shape.prototype.getPorts = function(){
return ports_pmosfet;
};
// for vdd
var ports_vdd = new Array();
ports_vdd['vdd'] = {x: 0.5, y: 1, perimeter: true, constraint: 'south'};
Vdd_Shape.prototype.getPorts = function(){
return ports_vdd;
};
// for gnd
var ports_gnd = new Array();
ports_gnd['gnd'] = {x: 0.5, y: 0, perimeter: true, constraint: 'north'};
Gnd_Shape.prototype.getPorts = function(){
return ports_gnd;
};
// for capatiance
var ports_capatiance = new Array();
ports_capatiance['pos'] = {x: 0.0, y: 0.5, perimeter: true, constraint: 'west'};
ports_capatiance['neg'] = {x: 1.0, y: 0.5, perimeter: true, constraint: 'east'};
Capacitor_Shape.prototype.getPorts = function(){
return ports_capatiance;
};
// for port_pin
var ports_pin = new Array();
ports_pin['pin'] = {x: 1.0, y: 0.5, perimeter: true, constraint: 'east'};
Pin_Shape.prototype.getPorts = function(){
return ports_pin;
};
// for port_out
var ports_pout = new Array();
ports_pout['pout'] = {x: 0.0, y: 0.5, perimeter: true, constraint: 'west'};
Pout_Shape.prototype.getPorts = function(){
return ports_pout;
};
// for Vdc
var ports_vdc = new Array();
ports_vdc['pos'] = {x: 0.5, y: 0.0, perimeter: true, constraint: 'north'};
ports_vdc['neg'] = {x: 0.5, y: 1.0, perimeter: true, constraint: 'south'};
Vdc_Shape.prototype.getPorts = function(){
return ports_vdc;
};
// for Vac
var ports_vac = new Array();
ports_vac['pos'] = {x: 0.5, y: 0.0, perimeter: true, constraint: 'north'};
ports_vac['neg'] = {x: 0.5, y: 1.0, perimeter: true, constraint: 'south'};
Vac_Shape.prototype.getPorts = function(){
return ports_vac;
};
// for Vsin
var ports_vsin = new Array();
ports_vsin['pos'] = {x: 0.5, y: 0.0, perimeter: true, constraint: 'north'};
ports_vsin['neg'] = {x: 0.5, y: 1.0, perimeter: true, constraint: 'south'};
Vsin_Shape.prototype.getPorts = function(){
return ports_vsin;
};
// for Vsin
var ports_vpulse = new Array();
ports_vpulse['pos'] = {x: 0.5, y: 0.0, perimeter: true, constraint: 'north'};
ports_vpulse['neg'] = {x: 0.5, y: 1.0, perimeter: true, constraint: 'south'};
Vpulse_Shape.prototype.getPorts = function(){
return ports_vpulse;
};
</script>
</head>
<!-- Calls the main function after the page has loaded. Container is dynamically created. -->
<body onload="main();">
</body>
</html>