1064 lines
35 KiB
JavaScript
1064 lines
35 KiB
JavaScript
/*
|
|
|
|
altium.js schematic renderer
|
|
|
|
Copyright (c) 2022 Graham Sutherland
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
a copy of this software and associated documentation files (the
|
|
"Software"), to deal in the Software without restriction, including
|
|
without limitation the rights to use, copy, modify, merge, publish,
|
|
distribute, sublicense, and/or sell copies of the Software, and to
|
|
permit persons to whom the Software is furnished to do so, subject to
|
|
the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be
|
|
included in all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
|
mxConnectionHandler.prototype.movePreviewAway = false;
|
|
mxConnectionHandler.prototype.waypointsEnabled = true;
|
|
mxGraph.prototype.resetEdgesOnConnect = false;
|
|
mxConstants.SHADOWCOLOR = '#C0C0C0';
|
|
var joinNodeSize = 7;
|
|
var strokeWidth = 2;
|
|
|
|
class AltiumSchematicRenderer
|
|
{
|
|
constructor(canvas, document)
|
|
{
|
|
this.canvas = canvas;
|
|
this.document = document;
|
|
this.graph = null
|
|
}
|
|
|
|
#altiumColourToHex(colourInt)
|
|
{
|
|
return "#" + (colourInt & 0xFF).toString(16).padStart(2, '0') + ((colourInt >> 8) & 0xFF).toString(16).padStart(2, '0') + ((colourInt >> 16) & 0xFF).toString(16).padStart(2, '0');
|
|
}
|
|
|
|
#shouldShow(object)
|
|
{
|
|
if (object.owner_part_id == null || object.owner_part_id < 1)
|
|
return true;
|
|
|
|
const parent = object.find_parent(AltiumComponent);
|
|
if (parent == null)
|
|
return true;
|
|
|
|
if (parent.current_part_id == null || parent.current_part_id < 1)
|
|
return true;
|
|
|
|
return parent.current_part_id == object.owner_part_id;
|
|
}
|
|
|
|
render() {
|
|
|
|
// https://github.com/jgraph/mxgraph/blob/master/javascript/src/js/handler/mxGraphHandler.js#L1036
|
|
mxGraphHandler.prototype.updatePreview = function(remote) {
|
|
if (this.livePreviewUsed && !remote) {
|
|
if (this.cells != null)
|
|
{
|
|
this.setHandlesVisibleForCells(this.graph.getSelectionCells(), false);
|
|
this.updateLivePreview(this.currentDx, this.currentDy);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.updatePreviewShape();
|
|
}
|
|
};
|
|
|
|
this.graph = new mxGraph(document.getElementById('graphContainer'));
|
|
|
|
let oldMove = mxGraphHandler.prototype.mouseMove
|
|
mxGraphHandler.prototype.mouseMove = function(sender, me){
|
|
console.log("mouse move",sender,me)
|
|
// https://github.com/jgraph/mxgraph/blob/master/javascript/src/js/handler/mxGraphHandler.js#L901
|
|
if (!this.livePreviewUsed && this.shape == null) {
|
|
this.shape = this.createPreviewShape(this.bounds);
|
|
}else if(this.shape != null){
|
|
console.log("mouseMove",this)
|
|
}
|
|
oldMove.call(this, sender, me);
|
|
}
|
|
|
|
|
|
let oldClick = mxGraphHandler.prototype.mouseDown
|
|
mxGraphHandler.prototype.mouseDown = function(sender, me){
|
|
console.log("mouse down",sender,me)
|
|
// https://github.com/jgraph/mxgraph/blob/master/javascript/src/js/handler/mxGraphHandler.js#L901
|
|
if(me.state != undefined){
|
|
if(me.state.cell.children != undefined){
|
|
oldClick.call(this, sender, me);
|
|
}else{
|
|
console.log(me.state.cell)
|
|
if(me.state.cell.parent != undefined){
|
|
this.graph.addSelectionCell(me.state.cell.parent)
|
|
oldClick.call(this, sender, me);
|
|
}
|
|
// oldClick.call(this, sender, me);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
let oldMouseUp = mxGraphHandler.prototype.mouseUp
|
|
mxGraphHandler.prototype.mouseUp = function(sender, me){
|
|
console.log("mouse up",sender,me)
|
|
// https://github.com/jgraph/mxgraph/blob/master/javascript/src/js/handler/mxGraphHandler.js#L901
|
|
if(me.state != undefined){
|
|
if(me.state.cell.children != undefined){
|
|
oldMouseUp.call(this, sender, me);
|
|
}else{
|
|
if(me.state.cell.parent != undefined){
|
|
this.graph.addSelectionCell(me.state.cell.parent)
|
|
oldMouseUp.call(this, sender, me);
|
|
}
|
|
// oldClick.call(this, sender, me);
|
|
}
|
|
}
|
|
oldMouseUp.call(this, sender, me);
|
|
|
|
}
|
|
|
|
this.graph.setPanning(true);
|
|
this.graph.setConnectable(true);
|
|
this.graph.setConnectableEdges(true);
|
|
this.graph.setDisconnectOnMove(false);
|
|
this.graph.foldingEnabled = false;
|
|
this.graph.gridSize = 1
|
|
//Maximum size
|
|
this.graph.maximumGraphBounds = new mxRectangle(0, 0, 1920, 1024)
|
|
this.graph.border = 0;
|
|
var fontColor = '#FFFFFF' ;
|
|
var strokeColor = '#C0C0C0' ;
|
|
var fillColor = '#C0C0C0';
|
|
// Panning handler consumed right click so this must be
|
|
// disabled if right click should stop connection handler.
|
|
this.graph.panningHandler.isPopupTrigger = function() { return false; };
|
|
|
|
// Enables return key to stop editing (use shift-enter for newlines)
|
|
this.graph.setEnterStopsCellEditing(true);
|
|
|
|
// Adds rubberband selection
|
|
new mxRubberband(this.graph);
|
|
|
|
this.graph.addListener(mxEvent.CLICK, function(sender, evt)
|
|
{
|
|
var e = evt.getProperty('event'); // mouse event
|
|
var cell = evt.getProperty('cell'); // cell may be null
|
|
|
|
if (cell != null)
|
|
{
|
|
// Do something useful with cell and consume the event
|
|
// evt.consume();
|
|
}
|
|
});
|
|
|
|
var connectionHandlerMouseUp = this.graph.connectionHandler.mouseUp;
|
|
this.graph.connectionHandler.mouseUp = function(sender, me)
|
|
{
|
|
if (this.first != null && this.previous != null)
|
|
{
|
|
var point = mxUtils.convertPoint(this.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 < this.graph.tolerance && dy < this.graph.tolerance)
|
|
{
|
|
// Selects edges in non-wire mode for single clicks, but starts
|
|
// connecting for non-edges regardless of wire-mode
|
|
console.log("sss")
|
|
|
|
return;
|
|
}
|
|
}
|
|
connectionHandlerMouseUp.apply(this, arguments);
|
|
};
|
|
|
|
mxVertexHandler.prototype.rotationEnabled = false;
|
|
|
|
// Alternative solution for implementing connection points without child cells.
|
|
// This can be extended as shown in portrefs.html example to allow for per-port
|
|
// incoming/outgoing direction.
|
|
this.graph.getAllConnectionConstraints = function(terminal) {
|
|
var geo = (terminal != null) ? this.getCellGeometry(terminal.cell) : null;
|
|
console.log("getAllConnectionConstraints ",terminal)
|
|
if ((geo != null ? !geo.relative : false) &&
|
|
this.getModel().isVertex(terminal.cell) &&
|
|
this.getModel().getChildCount(terminal.cell) == 0)
|
|
{
|
|
return [
|
|
new mxConnectionConstraint(new mxPoint(1, 0.5), false)];
|
|
}
|
|
return null;
|
|
};
|
|
// Makes sure non-relative cells can only be connected via constraints
|
|
this.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;
|
|
}
|
|
};
|
|
|
|
var parent = this.graph.getDefaultParent();
|
|
mxVertexHandler.prototype.livePreview = true;
|
|
|
|
var labelBackground = (false) ? '#000000' : '#FFFFFF';
|
|
var fontColor = (false) ? '#FFFFFF' : '#000000';
|
|
var strokeColor = (false) ? '#C0C0C0' : '#000000';
|
|
var fillColor = (false) ? 'none' : '#FFFFFF';
|
|
|
|
|
|
var style = this.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'] = '0';
|
|
style[mxConstants.STYLE_FONTSIZE] = '11';
|
|
|
|
|
|
// Sets join node size
|
|
style['startSize'] = joinNodeSize;
|
|
style['endSize'] = joinNodeSize;
|
|
|
|
style = this.graph.getStylesheet().getDefaultVertexStyle();
|
|
//style['gradientColor'] = '#909090';
|
|
style['strokeColor'] = strokeColor;
|
|
//style['fillColor'] = '#e0e0e0';
|
|
style['fillColor'] = 'none';
|
|
style['fontColor'] = fontColor;
|
|
style['fontStyle'] = '1';
|
|
style['fontSize'] = '6';
|
|
style['resizable'] = '0';
|
|
style['strokeWidth'] = strokeWidth;
|
|
// let canvas = this.canvas;
|
|
let doc = this.document;
|
|
|
|
let sheetObject = doc.objects.find(o => o instanceof AltiumSheet);
|
|
|
|
// canvas.style.width = sheetObject.width + "px";
|
|
// canvas.style.height = sheetObject.height + "px";
|
|
// canvas.width = sheetObject.width * window.devicePixelRatio;
|
|
// canvas.height = sheetObject.height * window.devicePixelRatio;
|
|
let areaColourInt = Number.parseInt(sheetObject.attributes.areacolor, 10);
|
|
let areaColour = this.#altiumColourToHex(areaColourInt);
|
|
// canvas.style.backgroundColor = areaColour;
|
|
// let ctx = canvas.getContext('2d');
|
|
// ctx.scale(1, -1);
|
|
// ctx.translate(0.5, 0.5);
|
|
// ctx.translate(0, -canvas.height);
|
|
// ctx.font = "7pt sans-serif";
|
|
// ctx.textRendering = "optimizeLegibility";
|
|
// ctx.imageSmoothingQuality = "high";
|
|
// ctx.textBaseline = "bottom";
|
|
// ctx.fillStyle = areaColour;
|
|
// ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
|
|
let results = document.getElementById("results");
|
|
|
|
let sheet = doc.objects.find((o) => o instanceof AltiumSheet);
|
|
let gridLight = "#eeeeee";
|
|
let gridDark = "#cccccc";
|
|
// ctx.lineWidth = 1;
|
|
// ctx.globalAlpha = 0.5;
|
|
if (sheet.show_grid)
|
|
{
|
|
|
|
let n = 0;
|
|
// for (let x = 0; x < canvas.width; x += sheet.grid_size)
|
|
// {
|
|
// ctx.strokeStyle = ((n % 10) == 0) ? gridDark : gridLight;
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(x, 0);
|
|
// ctx.lineTo(x, canvas.height);
|
|
// ctx.stroke();
|
|
// n++;
|
|
// }
|
|
// n = 0;
|
|
// for (let y = 0; y < canvas.height; y += sheet.grid_size)
|
|
// {
|
|
// ctx.strokeStyle = ((n % 10) == 0) ? gridDark : gridLight;
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(0, y);
|
|
// ctx.lineTo(canvas.width, y);
|
|
// ctx.stroke();
|
|
// n++;
|
|
// }
|
|
}
|
|
// ctx.globalAlpha = 1;
|
|
|
|
/*
|
|
|
|
ctx.textAlign = "center";
|
|
ctx.font = "bold 100px serif";
|
|
ctx.fillStyle = "#333300";
|
|
ctx.globalAlpha = 0.03;
|
|
ctx.save();
|
|
|
|
ctx.rotate(Math.PI/4);
|
|
ctx.scale(1,-1);
|
|
for (let y = 0; y < canvas.height * 2; y += 400)
|
|
{
|
|
ctx.fillText("PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA", canvas.width / 2, canvas.height - (y + 200));
|
|
ctx.fillText("BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW - BETA - PREVIEW", canvas.width / 2, canvas.height - y);
|
|
}
|
|
|
|
ctx.textAlign = "left";
|
|
*/
|
|
|
|
this.graph.getModel().beginUpdate();
|
|
try{
|
|
let bom = [];
|
|
bom.push("\"designator\", \"part\", \"description\"");
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumDesignator))
|
|
{
|
|
if (!this.#shouldShow(obj)) continue;
|
|
|
|
let bomLine = "";
|
|
//let designator = doc.objects.find((des) => des instanceof AltiumDesignator && des.owner_part_id == obj.current_part_id);
|
|
let component = doc.object_from_record_index(obj.owner_record_index);
|
|
if (component != null && component instanceof AltiumComponent)
|
|
{
|
|
bomLine += "\"" + obj.text + "\", \"" + component.design_item_id + "\", \"" + component.description.replaceAll("\"", "'") + "\"";
|
|
bom.push(bomLine);
|
|
}
|
|
//bomLine += obj.description;
|
|
|
|
}
|
|
results.innerText = bom.join("\n");
|
|
|
|
// for (let obj of doc.objects.filter((o) => o instanceof AltiumWire))
|
|
// {
|
|
// // for (let i = 1; i < obj.points.length; i++)
|
|
// // {
|
|
// // obj.points[i].y = 840 - obj.points[i].y
|
|
// // }
|
|
// var obj1 = this.graph.getCellAt(obj.points[0].x,obj.points[0].y,parent)
|
|
// var obj2 = this.graph.getCellAt(obj.points[obj.points.length - 1].x,
|
|
// obj.points[obj.points.length - 1].y,parent)
|
|
|
|
// console.log(obj1,obj2)
|
|
// // if (!this.#shouldShow(obj)) continue;
|
|
|
|
// // ctx.strokeStyle = this.#altiumColourToHex(obj.colour);
|
|
// // ctx.lineWidth = obj.width;
|
|
// // ctx.beginPath();
|
|
// // ctx.moveTo(obj.points[0].x, obj.points[0].y);
|
|
// // for (let i = 1; i < obj.points.length; i++)
|
|
// // {
|
|
// // ctx.lineTo(obj.points[i].x, obj.points[i].y);
|
|
// // }
|
|
// // ctx.stroke();
|
|
// }
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumBus))
|
|
{
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
|
|
// ctx.strokeStyle = this.#altiumColourToHex(obj.colour);
|
|
// ctx.lineWidth = obj.width;
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.points[0].x, obj.points[0].y);
|
|
// for (let i = 1; i < obj.points.length; i++)
|
|
// {
|
|
// ctx.lineTo(obj.points[i].x, obj.points[i].y);
|
|
// }
|
|
// ctx.stroke();
|
|
}
|
|
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumSheetSymbol))
|
|
{
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
// ctx.fillStyle = this.#altiumColourToHex(obj.attributes.areacolor);
|
|
|
|
// ctx.fillRect(obj.attributes.location_x,
|
|
// obj.attributes.location_y- obj.attributes.ysize,
|
|
// obj.attributes.xsize, obj.attributes.ysize);
|
|
// ctx.stroke();
|
|
// ctx.strokeStyle = this.#altiumColourToHex(obj.attributes.color);
|
|
// ctx.strokeRect(obj.attributes.location_x,
|
|
// obj.attributes.location_y- obj.attributes.ysize,
|
|
// obj.attributes.xsize, obj.attributes.ysize);
|
|
|
|
|
|
// ctx.strokeStyle = "#000080";
|
|
// ctx.lineWidth = obj.width;
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.attributes.location_x, obj.attributes.location_y);
|
|
// ctx.lineTo(obj.attributes.location_x + obj.attributes.xsize,
|
|
// obj.attributes.location_y + obj.attributes.ysize);
|
|
// ctx.stroke();
|
|
|
|
// ctx.strokeStyle = this.#altiumColourToHex(obj.colour);
|
|
// ctx.lineWidth = obj.width;
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.points[0].x, obj.points[0].y);
|
|
// for (let i = 1; i < obj.points.length; i++)
|
|
// {
|
|
// ctx.lineTo(obj.points[i].x, obj.points[i].y);
|
|
// }
|
|
// ctx.stroke();
|
|
}
|
|
let chips = {}
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumRectangle))
|
|
{
|
|
obj.top = 840 - obj.top
|
|
obj.bottom = 840 - obj.bottom
|
|
if(!obj.transparent){
|
|
console.log('verticalLabelPosition=top;verticalAlign=bottom;fillColor='
|
|
+ this.#altiumColourToHex(obj.attributes.areacolor))
|
|
let v1 = this.graph.insertVertex(parent, null, '',
|
|
obj.left, obj.top,
|
|
(obj.right - obj.left),
|
|
(obj.bottom - obj.top),
|
|
'verticalLabelPosition=top;verticalAlign=bottom;fillColor='
|
|
+ this.#altiumColourToHex(obj.attributes.areacolor));
|
|
v1.setConnectable(false);
|
|
if(chips[obj.owner_record_index] == undefined){
|
|
chips[obj.owner_record_index] = []
|
|
}
|
|
v1.geometry.relative = false
|
|
chips[obj.owner_record_index].push(v1)
|
|
}
|
|
// if (!this.#shouldShow(obj))
|
|
// continue;
|
|
// ctx.fillStyle = this.#altiumColourToHex(obj.attributes.areacolor);
|
|
|
|
// ctx.fillRect(obj.attributes.location_x,
|
|
// obj.attributes.location_y,
|
|
// obj.attributes.corner_x - obj.attributes.location_x, obj.attributes.corner_y - obj.attributes.location_y);
|
|
// ctx.stroke();
|
|
// ctx.strokeStyle = this.#altiumColourToHex(obj.attributes.color);
|
|
// ctx.strokeRect(obj.attributes.location_x,
|
|
// obj.attributes.location_y,
|
|
// obj.attributes.corner_x - obj.attributes.location_x, obj.attributes.corner_y - obj.attributes.location_y);
|
|
|
|
}
|
|
|
|
// todo undo
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumSheetEntry))
|
|
{
|
|
if (!this.#shouldShow(obj)) continue;
|
|
|
|
// ctx.strokeStyle = this.#altiumColourToHex(obj.colour);
|
|
// ctx.lineWidth = obj.width;
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.points[0].x, obj.points[0].y);
|
|
// for (let i = 1; i < obj.points.length; i++)
|
|
// {
|
|
// ctx.lineTo(obj.points[i].x, obj.points[i].y);
|
|
// }
|
|
// ctx.stroke();
|
|
}
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumTextFrame))
|
|
{
|
|
obj = obj
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
|
|
// if (!obj.transparent)
|
|
// {
|
|
// ctx.fillStyle = this.#altiumColourToHex(obj.fill_colour);
|
|
// ctx.fillRect(obj.left, obj.top, obj.right - obj.left,
|
|
// obj.bottom - obj.top);
|
|
// }
|
|
// if (obj.show_border)
|
|
// {
|
|
// ctx.strokeStyle = this.#altiumColourToHex(obj.border_colour);
|
|
// ctx.strokeRect(obj.left, obj.top, obj.right - obj.left,
|
|
// obj.bottom - obj.top);
|
|
// }
|
|
}
|
|
|
|
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumPin))
|
|
{
|
|
var style = 'shape=line;fontColor=#000000;strokeColor=#000000;'
|
|
let name = ''
|
|
if(obj.show_name){
|
|
name = obj.name
|
|
}
|
|
if(obj.angle == 0){
|
|
style = style + 'labelPosition=left;'
|
|
}
|
|
if(obj.angle == 90){
|
|
style += 'rotation=90'
|
|
obj.y = obj.y + obj.length/2
|
|
obj.x = obj.x - obj.length/2
|
|
}
|
|
if(obj.angle == 180){
|
|
style = style + 'labelPosition=right;'
|
|
obj.x = obj.x - obj.length
|
|
}
|
|
if(obj.angle == 270){
|
|
style += 'rotation=90'
|
|
obj.y = obj.y - obj.length/2
|
|
obj.x = obj.x - obj.length/2
|
|
}
|
|
obj.y = 840 - obj.y
|
|
|
|
// console.log(style)
|
|
var v11 = this.graph.insertVertex(parent, null, name, obj.x, obj.y,
|
|
obj.length, 1,
|
|
style);
|
|
v11.geometry.relative = false;
|
|
v11.setConnectable(true);
|
|
if(chips[obj.owner_record_index] == undefined){
|
|
chips[obj.owner_record_index] = []
|
|
}
|
|
console.log(v11.geometry.getTerminalPoint (true))
|
|
chips[obj.owner_record_index].push(v11)
|
|
|
|
// v11.geometry.offset = new mxPoint(-v11.geometry.width, 2); // ctx.strokeStyle = "#000000";
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.x, obj.y);
|
|
// ctx.lineTo(obj.x + obj.angle_vec[0] * obj.length, obj.y + obj.angle_vec[1] * obj.length);
|
|
// ctx.stroke();
|
|
|
|
// ctx.fillStyle = this.#altiumColourToHex(obj.colour);
|
|
// ctx.beginPath();
|
|
// ctx.ellipse(obj.x + obj.angle_vec[0] * obj.length, obj.y + obj.angle_vec[1] * obj.length, 5, 4, 0, 0, 2*Math.PI);
|
|
// ctx.fill();
|
|
}
|
|
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumEllipse))
|
|
{
|
|
obj = obj
|
|
obj.y = 840-obj.y
|
|
let v1 = this.graph.insertVertex(parent, null, '',
|
|
obj.x - obj.radius_x, obj.y - obj.radius_x,
|
|
obj.radius_x*2, obj.radius_y*2,'shape=ellipse;fillColor='
|
|
+ this.#altiumColourToHex(obj.fill_colour));
|
|
v1.setConnectable(false)
|
|
chips[obj.owner_record_index].push(v1)
|
|
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
|
|
// if (!obj.transparent)
|
|
// {
|
|
// ctx.fillStyle = this.#altiumColourToHex(obj.fill_colour);
|
|
// }
|
|
// ctx.strokeStyle = this.#altiumColourToHex(obj.line_colour);
|
|
// ctx.beginPath();
|
|
// ctx.ellipse(obj.x, obj.y, obj.radius_x, obj.radius_y, 0, 0, Math.PI*2);
|
|
// ctx.stroke();
|
|
// if (!obj.transparent)
|
|
// ctx.fill();
|
|
}
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumLine)) {
|
|
mxCellRenderer.registerShape('polyline', mxPolyline);
|
|
obj.x2 = 840 - obj.x2
|
|
obj.y2 = 840 - obj.y2
|
|
style = 'shape=polyline;strokeColor=#0000ff;'
|
|
// console.log(style)
|
|
var v11 = this.graph.insertVertex(parent, null, '', obj.x1, obj.x2,
|
|
1,1,style);
|
|
v11.points = [new mxPoint(obj.y1 - obj.x1,obj.y2 - obj.x2)]
|
|
v11.geometry.relative = false;
|
|
if(chips[obj.owner_record_index] == undefined){
|
|
chips[obj.owner_record_index] = []
|
|
}
|
|
if(chips[obj.owner_record_index] == undefined){
|
|
chips[obj.owner_record_index] = []
|
|
}
|
|
v11.setConnectable(false);
|
|
|
|
chips[obj.owner_record_index].push(v11)
|
|
|
|
// 将cell设定为线段
|
|
// cell.edge = true;
|
|
|
|
|
|
// 设置起始点
|
|
// cell.geometry.setTerminalPoint(new mxPoint(obj.x1, obj.x2), true);
|
|
// 设置终结点
|
|
// cell.geometry.setTerminalPoint(new mxPoint(obj.y1, obj.y2), false);
|
|
// 使用 points 定义多个中间节点
|
|
// this.graph.model.root.insert(cell);
|
|
|
|
// this.graph.model.root.insert(cell);
|
|
// chips[obj.owner_record_index].push(cell)
|
|
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
|
|
// ctx.strokeStyle = this.#altiumColourToHex(obj.colour);
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.x1, obj.y1);
|
|
// ctx.lineTo(obj.x2, obj.y2);
|
|
// ctx.stroke();
|
|
}
|
|
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumArc))
|
|
{
|
|
obj = obj
|
|
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
|
|
// ctx.strokeStyle = this.#altiumColourToHex(obj.colour);
|
|
// ctx.lineWidth = obj.width;
|
|
// ctx.beginPath();
|
|
// ctx.arc(obj.x, obj.y, obj.radius, obj.start_angle * Math.PI/180, obj.end_angle * Math.PI/180);
|
|
// ctx.stroke();
|
|
// ctx.lineWidth = 1;
|
|
}
|
|
|
|
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumPolygon))
|
|
{
|
|
obj = obj
|
|
mxCellRenderer.registerShape('polygon', mxPolygon);
|
|
obj.x2 = 840 - obj.x2
|
|
obj.y2 = 840 - obj.y2
|
|
style = 'shape=polygon;strokeColor=#0000ff;'
|
|
// console.log(style)
|
|
var v11 = this.graph.insertVertex(parent, null, '', obj.points[0], obj.points[0],
|
|
1,1,style);
|
|
|
|
v11.points = obj.obj.points
|
|
v11.geometry.relative = false;
|
|
if(chips[obj.owner_record_index] == undefined){
|
|
chips[obj.owner_record_index] = []
|
|
}
|
|
if(chips[obj.owner_record_index] == undefined){
|
|
chips[obj.owner_record_index] = []
|
|
}
|
|
v11.setConnectable(false);
|
|
|
|
chips[obj.owner_record_index].push(v11)
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
|
|
// ctx.strokeStyle = this.#altiumColourToHex(obj.line_colour);
|
|
// ctx.fillStyle = this.#altiumColourToHex(obj.fill_colour);
|
|
// ctx.lineWidth = obj.width;
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.points[0].x, obj.points[0].y);
|
|
// for (let i = 1; i < obj.points.length; i++)
|
|
// {
|
|
// ctx.lineTo(obj.points[i].x, obj.points[i].y);
|
|
// }
|
|
// ctx.closePath();
|
|
// ctx.stroke();
|
|
// ctx.fill();
|
|
// ctx.lineWidth = 1;
|
|
}
|
|
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumJunction))
|
|
{
|
|
obj = obj
|
|
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
|
|
// ctx.fillStyle = this.#altiumColourToHex(obj.colour);
|
|
// ctx.beginPath();
|
|
// ctx.ellipse(obj.x, obj.y, 5, 4, 0, 0, 2*Math.PI);
|
|
// ctx.fill();
|
|
}
|
|
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumPowerPort))
|
|
{
|
|
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
|
|
// ctx.strokeStyle = this.#altiumColourToHex(obj.colour);
|
|
// ctx.fillStyle = this.#altiumColourToHex(obj.colour);
|
|
// ctx.lineWidth = 1;
|
|
// if (!obj.is_off_sheet_connector)
|
|
// {
|
|
// switch (obj.style)
|
|
// {
|
|
// case 2:
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.x, obj.y);
|
|
// ctx.lineTo(obj.x, obj.y + 10);
|
|
// ctx.stroke();
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.x - 5, obj.y + 10);
|
|
// ctx.lineTo(obj.x + 5, obj.y + 10);
|
|
// ctx.stroke();
|
|
// break;
|
|
// case 4:
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.x - 10, obj.y);
|
|
// ctx.lineTo(obj.x + 10, obj.y);
|
|
// ctx.stroke();
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.x - 7.5, obj.y - 2);
|
|
// ctx.lineTo(obj.x + 7.5, obj.y - 2);
|
|
// ctx.stroke();
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.x - 5, obj.y - 4);
|
|
// ctx.lineTo(obj.x + 5, obj.y - 4);
|
|
// ctx.stroke();
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.x - 2.5, obj.y - 6);
|
|
// ctx.lineTo(obj.x + 2.5, obj.y - 6);
|
|
// ctx.stroke();
|
|
// break;
|
|
// case 6:
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.x, obj.y);
|
|
// ctx.lineTo(obj.x, obj.y - 5);
|
|
// ctx.stroke();
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.x - 5, obj.y - 5);
|
|
// ctx.lineTo(obj.x + 5, obj.y - 5);
|
|
// ctx.stroke();
|
|
// for (let g = -1; g < 2; g++)
|
|
// {
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.x + (g * 5), obj.y - 5);
|
|
// ctx.lineTo(obj.x + (g * 5) - 3, obj.y - 10);
|
|
// ctx.stroke();
|
|
// }
|
|
// break;
|
|
// default:
|
|
// ctx.fillRect(obj.x - 10, obj.y, 20, (obj.orientation == 1) ? 10 : -10);
|
|
// break;
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// ctx.save();
|
|
// ctx.translate(obj.x, obj.y);
|
|
// ctx.rotate((obj.orientation - 1) * Math.PI/2);
|
|
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(0, 0);
|
|
// ctx.lineTo(-5, 5);
|
|
// ctx.stroke();
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(0, 0);
|
|
// ctx.lineTo(5, 5);
|
|
// ctx.stroke();
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(0, 5);
|
|
// ctx.lineTo(-5, 10);
|
|
// ctx.stroke();
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(0, 5);
|
|
// ctx.lineTo(5, 10);
|
|
// ctx.stroke();
|
|
|
|
// ctx.restore();
|
|
// }
|
|
//ctx.fillText(obj.style.toString(), obj.x, obj.y);
|
|
}
|
|
|
|
// store the transform for recovery later
|
|
// let savedTransform = ctx.getTransform();
|
|
// ctx.resetTransform();
|
|
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumLabel))
|
|
{
|
|
obj.y = 840 - obj.y
|
|
if(obj.text != undefined){
|
|
console.log(obj.text.length)
|
|
var v11 = this.graph.insertVertex(parent, null, obj.text, obj.x, obj.y - 4,
|
|
obj.text.length*9/2, 0,
|
|
"shape=label;fontSize=9;");
|
|
v11.geometry.relative = false;
|
|
v11.setConnectable(false);
|
|
if(obj.owner_record_index != 1)
|
|
chips[obj.owner_record_index].push(v11)
|
|
}
|
|
|
|
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
|
|
// if (obj.hidden)
|
|
// continue;
|
|
// ctx.textAlign = ["left", "center", "right"][obj.justification];
|
|
// ctx.textBaseline = ["bottom", "bottom", "top", "top"][obj.orientation];
|
|
// ctx.fillStyle = this.#altiumColourToHex(obj.colour);
|
|
// ctx.save();
|
|
// ctx.translate(obj.x, canvas.height - obj.y);
|
|
// ctx.rotate(obj.orientation * -Math.PI/2);
|
|
// ctx.fillText(obj.text, 0, 0);
|
|
// ctx.restore();
|
|
}
|
|
// ctx.textAlign = "left";
|
|
// ctx.textBaseline = "bottom";
|
|
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumDesignator))
|
|
{
|
|
obj = obj
|
|
obj.y = 840 - obj.y
|
|
if(obj.text != undefined){
|
|
console.log(obj.text.length)
|
|
var v11 = this.graph.insertVertex(parent, null, obj.text, obj.x, obj.y - 4,
|
|
obj.text.length*9/2, 0,
|
|
"shape=label;fontSize=9;");
|
|
v11.geometry.relative = false;
|
|
v11.setConnectable(false);
|
|
if(obj.owner_record_index != 1)
|
|
chips[obj.owner_record_index].push(v11)
|
|
}
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
|
|
// if (obj.hidden)
|
|
// continue;
|
|
// ctx.textAlign = ["left", "left", "right", "right"][obj.orientation];
|
|
// ctx.textBaseline = ["bottom", "bottom", "top", "top"][obj.orientation];
|
|
// ctx.fillStyle = this.#altiumColourToHex(obj.colour);
|
|
// ctx.fillText(obj.full_designator, obj.x, canvas.height - obj.y);
|
|
}
|
|
// ctx.textAlign = "left";
|
|
// ctx.textBaseline = "bottom";
|
|
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumParameter)) {
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
|
|
// if (obj.hidden || obj.is_implementation_parameter)
|
|
// continue;
|
|
|
|
// ctx.textAlign = ["left", "left", "right", "right"][obj.orientation];
|
|
// ctx.textBaseline = ["bottom", "bottom", "top", "top"][obj.orientation];
|
|
// ctx.fillStyle = this.#altiumColourToHex(obj.colour);
|
|
// if (obj.orientation == 1)
|
|
// {
|
|
// ctx.save();
|
|
// ctx.translate(obj.x, canvas.height - obj.y);
|
|
// ctx.rotate(-Math.PI/2);
|
|
// ctx.fillText(obj.text, 0, 0);
|
|
// ctx.restore();
|
|
// }
|
|
// else if (obj.orientation == 3)
|
|
// {
|
|
// ctx.save();
|
|
// ctx.translate(obj.x, canvas.height - obj.y);
|
|
// ctx.rotate(Math.PI/2);
|
|
// ctx.fillText(obj.text, 0, 0);
|
|
// ctx.restore();
|
|
// }
|
|
// else
|
|
// {
|
|
// ctx.fillText(obj.text, obj.x, canvas.height - obj.y);
|
|
// }
|
|
}
|
|
// ctx.textAlign = "left";
|
|
// ctx.textBaseline = "bottom";
|
|
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumNetLabel)) {
|
|
obj = obj
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
|
|
// if (obj.hidden)
|
|
// continue;
|
|
// ctx.textAlign = ["left", "center", "right"][obj.justification];
|
|
// ctx.textBaseline = ["bottom", "bottom", "top", "top"][obj.orientation];
|
|
// ctx.fillStyle = this.#altiumColourToHex(obj.colour);
|
|
// if (obj.orientation == 1)
|
|
// {
|
|
// ctx.save();
|
|
// ctx.translate(obj.x, canvas.height - obj.y);
|
|
// ctx.rotate(-Math.PI/2);
|
|
// ctx.fillText(obj.text, 0, 0);
|
|
// ctx.restore();
|
|
// }
|
|
// else if (obj.orientation == 3)
|
|
// {
|
|
// ctx.save();
|
|
// ctx.translate(obj.x, canvas.height - obj.y);
|
|
// ctx.rotate(Math.PI/2);
|
|
// ctx.fillText(obj.text, 0, 0);
|
|
// ctx.restore();
|
|
// }
|
|
// else
|
|
// {
|
|
// ctx.fillText(obj.text, obj.x, canvas.height - obj.y);
|
|
// }
|
|
}
|
|
// ctx.textAlign = "left";
|
|
// ctx.textBaseline = "bottom";
|
|
|
|
|
|
// ctx.textAlign = "left";
|
|
// ctx.textBaseline = "bottom";
|
|
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumPowerPort)) {
|
|
obj = obj
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
|
|
// if (!obj.show_text)
|
|
// continue;
|
|
// ctx.fillStyle = this.#altiumColourToHex(obj.colour);
|
|
// ctx.textBaseline = ["middle", "top", "middle", "bottom"][obj.orientation];
|
|
// ctx.textAlign = ["left", "center", "right", "center"][obj.orientation];
|
|
// let offset_x = [12, 0, -12, 0][obj.orientation];
|
|
// let offset_y = [0, 20, 0, -20][obj.orientation];
|
|
// ctx.fillText(obj.text, obj.x + offset_x, canvas.height - (obj.y + offset_y));
|
|
}
|
|
|
|
// ctx.textAlign = "left";
|
|
// ctx.textBaseline = "middle";
|
|
// let savedFont = ctx.font;
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumTextFrame)) {
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
|
|
// if (obj.font_id > 0 && doc.sheet.fonts[obj.font_id] != null)
|
|
// {
|
|
// const frameFont = doc.sheet.fonts[obj.font_id];
|
|
// const fontStr = (frameFont.size - 1).toString() + "px " + frameFont.name;
|
|
// if (fontStr.includes(":") || fontStr.includes("/") || !document.fonts.check(fontStr))
|
|
// {
|
|
// ctx.font = savedFont;
|
|
// }
|
|
// else
|
|
// {
|
|
// ctx.font = fontStr;
|
|
// }
|
|
// }
|
|
|
|
// ctx.fillStyle = this.#altiumColourToHex(obj.text_colour);
|
|
// ctx.textAlign = ["center", "left", "right"][obj.alignment];
|
|
// let offset_x = [(obj.right-obj.left)/2, obj.text_margin, (obj.right-obj.left) - obj.text_margin][obj.alignment];
|
|
// if (!obj.word_wrap)
|
|
// {
|
|
// ctx.fillText(obj.text.replaceAll("~1", "\n"), obj.left + offset_x, canvas.height - (obj.top + (obj.bottom-obj.top)/2));
|
|
// }
|
|
// else
|
|
// {
|
|
// // todo: refactor this so that an initial pass figures out all the line splits, then a second pass writes the text, so that vertical alignment can be supported.
|
|
// const text = obj.text.replaceAll("~1", "\n");
|
|
// const lines = text.split("\n");
|
|
// let ypos = 0;
|
|
// if (lines.length > 1)
|
|
// {
|
|
// // this is a total hack, but if there are multiple lines in the text then we can make a rough guess at how far up we need to shift the text to center it vertically
|
|
// // this doesn't correct for line wraps (see todo above for refactoring approach) but it's at least something I guess!
|
|
// const roughMeasure = ctx.measureText(text);
|
|
// ypos = ((roughMeasure.fontBoundingBoxDescent + roughMeasure.fontBoundingBoxAscent) * -lines.length) / 2;
|
|
// }
|
|
// const maxWidth = (obj.right - obj.left) + (obj.text_margin * 2);
|
|
// for (let line of lines)
|
|
// {
|
|
// const lineMeasure = ctx.measureText(line);
|
|
// if (lineMeasure.width <= maxWidth)
|
|
// {
|
|
// ctx.fillText(line, obj.left + offset_x, (canvas.height - (obj.top + (obj.bottom-obj.top)/2)) + ypos);
|
|
// ypos += lineMeasure.fontBoundingBoxDescent + lineMeasure.fontBoundingBoxAscent;
|
|
// }
|
|
// else
|
|
// {
|
|
// let words = line.split(" ");
|
|
// while (words.length > 0)
|
|
// {
|
|
// if (words.length == 1)
|
|
// {
|
|
// // we only have one word, either because that's just how many we had or because the final word is super long
|
|
// const lastWord = words[0];
|
|
// const lastWordMeasure = ctx.measureText(lastWord);
|
|
// ctx.fillText(lastWord, obj.left + offset_x, (canvas.height - (obj.top + (obj.bottom-obj.top)/2)) + ypos);
|
|
// ypos += lastWordMeasure.fontBoundingBoxDescent + lineMeasure.fontBoundingBoxAscent;
|
|
// words = [];
|
|
// break;
|
|
// }
|
|
// for (let wc = words.length; wc > 0; wc--)
|
|
// {
|
|
// const partialLine = words.slice(0, wc - 1).join(" ");
|
|
// const partialMeasure = ctx.measureText(partialLine);
|
|
// if (partialMeasure.width <= maxWidth || wc == 1)
|
|
// {
|
|
// ctx.fillText(partialLine, obj.left + offset_x, (canvas.height - (obj.top + (obj.bottom-obj.top)/2)) + ypos);
|
|
// ypos += partialMeasure.fontBoundingBoxDescent + lineMeasure.fontBoundingBoxAscent;
|
|
// words = words.slice(wc - 1);
|
|
// break;
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
|
|
for (let obj of doc.objects.filter((o) => o instanceof AltiumWire))
|
|
{
|
|
let poi = []
|
|
for (let i = 0; i < obj.points.length; i++) {
|
|
obj.points[i].y = 840 - obj.points[i].y
|
|
if((i != 0) &&(i != obj.points.length)){
|
|
poi.push(new mxPoint(obj.points[i].x , obj.points[i].y))
|
|
}
|
|
}
|
|
|
|
var e6 = this.graph.insertEdge(parent, null, '')
|
|
e6.geometry.points = poi
|
|
|
|
e6.geometry.setTerminalPoint(new mxPoint(obj.points[0].x, obj.points[0].y), true)
|
|
e6.geometry.setTerminalPoint(new mxPoint(obj.points[obj.points.length - 1].x,
|
|
obj.points[obj.points.length - 1].y), false)
|
|
|
|
var obj1 = this.graph.getCellAt(obj.points[0].x,obj.points[0].y,parent)
|
|
var obj2 = this.graph.getCellAt(obj.points[obj.points.length - 1].x,
|
|
obj.points[obj.points.length - 1].y,parent)
|
|
for (let i in this.graph.model.cells){
|
|
if(this.graph.model.cells[i].geometry != undefined){
|
|
//
|
|
if((this.graph.model.cells[i].geometry['x'] == obj.points[0].x)
|
|
&&(this.graph.model.cells[i].geometry['y'] == obj.points[0].y)){
|
|
console.log("find first")
|
|
console.log(this.graph.model.cells[i].geometry)
|
|
}
|
|
}
|
|
}
|
|
// if (!this.#shouldShow(obj)) continue;
|
|
|
|
// ctx.strokeStyle = this.#altiumColourToHex(obj.colour);
|
|
// ctx.lineWidth = obj.width;
|
|
// ctx.beginPath();
|
|
// ctx.moveTo(obj.points[0].x, obj.points[0].y);
|
|
// for (let i = 1; i < obj.points.length; i++)
|
|
// {
|
|
// ctx.lineTo(obj.points[i].x, obj.points[i].y);
|
|
// }
|
|
// ctx.stroke();
|
|
}
|
|
for (let i in chips){
|
|
let chip = this.graph.groupCells(null,0,chips[i])
|
|
chip.setStyle("border=0;strokeColor=none")
|
|
}
|
|
}
|
|
finally{
|
|
this.graph.getModel().endUpdate();
|
|
}
|
|
// ctx.font = savedFont;
|
|
|
|
// ctx.textAlign = "left";
|
|
// ctx.textBaseline = "bottom";
|
|
|
|
// ctx.setTransform(savedTransform);
|
|
|
|
// savedFont = ctx.font;
|
|
// ctx.textAlign = "left";
|
|
// ctx.font = "bold 33px sans-serif";
|
|
// ctx.fillStyle = "#000000";
|
|
// ctx.globalAlpha = 0.2;
|
|
// ctx.save();
|
|
// ctx.scale(1,-1);
|
|
// ctx.fillText("Preview generated by altium.js", 10, -(canvas.height - 50));
|
|
// ctx.font = "bold 15px sans-serif";
|
|
// ctx.fillText("for reference purposes only. schematic accuracy not guaranteed.", 12, -(canvas.height - 75));
|
|
// ctx.restore();
|
|
// ctx.globalAlpha = 1;
|
|
// ctx.font = savedFont;
|
|
}
|
|
} |