blob: 289a57766c165994bd938ffaaa76ce4affdd5df1 [file] [log] [blame]
declare var require: any
import { Component, OnInit } from '@angular/core';
import * as $ from 'jquery';
import * as _ from 'lodash';
const joint = require('../../node_modules/jointjs/dist/joint.js');
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
title = 'jointJS-designer';
public graph: any;
public paper: any;
public rect: any;
public rect2: any;
public link: any;
public stencilGraph: any;
public stencilPaper: any;
public selectedElement = {
attributes: {
attrs: {
label: {
text: 'abc'
}
}
}
};
grapJson: any;
sourceMode = false;
constructor() {
}
ngOnInit() {
// this.creatElementWithPorts();
// this.dragCopyPlainElements();
this.sourceMode = false;
this.dragCopyElementsWithPort();
// this.newDragCopy();
this.createContainerElements();
}
creatElementWithPorts() {
// working code
// create graph
let elementList: any[] = [];
// this.graph = new joint.dia.Graph;
// // create paper
// this.paper = new joint.dia.Paper({
// el: document.getElementById('paper'),
// width: 1000,
// height: 1000,
// model: this.graph,
// gridSize: 2,
// drawGrid: true
// });
// this.paper.setGrid({
// name: 'dot',
// args:
// { color: 'black', thickness: 2, scaleFactor: 8 }
// }).drawGrid();
// create element
this.rect = new joint.shapes.basic.Rect({
position: { x: 100, y: 30 },
size: { width: 100, height: 100 },
attrs: { rect: { fill: 'white' }, text: { text: 'my box', fill: 'white' } }
});
this.rect.translate(100, 50);
elementList.push(this.rect);
this.rect.position(10, 10);
// clone element
// this.rect2 = this.rect.clone();
// this.rect2.translate(180);
// elementList.push(this.rect2);
// Create link
// this.link = new joint.dia.Link({
// source: { id: this.rect.id },
// target: { id: this.rect2.id }
// });
// create circle
var circle = new joint.shapes.standard.Circle();
circle.resize(100, 100);
circle.position(180, 10);
circle.attr('root/title', 'joint.shapes.standard.Circle');
circle.attr('label/text', 'Circle');
circle.attr('body/fill', 'lightblue');
elementList.push(circle);
// create link
var ellipse = new joint.shapes.standard.Ellipse();
ellipse.resize(150, 100);
ellipse.position(180, 150);
ellipse.attr('root/title', 'joint.shapes.standard.Ellipse');
ellipse.attr('label/text', 'Ellipse');
ellipse.attr('body/fill', 'lightblue');
elementList.push(ellipse);
// rectangle with header
var headeredRectangle = new joint.shapes.standard.HeaderedRectangle();
headeredRectangle.resize(150, 100);
headeredRectangle.position(10, 280);
headeredRectangle.attr('root/title', 'joint.shapes.standard.HeaderedRectangle');
headeredRectangle.attr('header/fill', 'lightgray');
headeredRectangle.attr('headerText/text', 'Header');
headeredRectangle.attr('bodyText/text', 'Headered\nRectangle');
elementList.push(headeredRectangle);
let m1 = new joint.shapes.devs.Model({
position: { x: 200, y: 280 },
size: { width: 90, height: 90 },
inPorts: ['in1', 'in2'],
outPorts: ['out', 'out2'],
ports: {
groups: {
'in': {
attrs: {
'.port-body': {
fill: '#16A085'
}
}
},
'out': {
attrs: {
'.port-body': {
fill: '#E74C3C'
}
}
}
}
},
attrs: {
'.label': { text: 'Model', 'ref-x': .5, 'ref-y': .2 },
rect: { fill: 'white' }
}
});
elementList.push(m1);
//container element
let c1 = new joint.shapes.devs.Coupled({
position: {
x: 150,
y: 470
},
size: {
width: 200,
height: 200
}
});
c1.set('inPorts', ['in']);
c1.set('outPorts', ['out 1', 'out 2']);
c1.attr({
'.body': {
'rx': 6,
'ry': 6
}
});
elementList.push(c1);
// circle.position(10, 150);
var a1 = new joint.shapes.devs.Atomic({
position: {
x: 10,
y: 150
},
inPorts: ['xy'],
outPorts: ['x', 'y']
});
a1.attr({
'.body': {
'rx': 6,
'ry': 6
}
});
elementList.push(a1);
return elementList;
}
dragCopyPlainElements() {
// Canvas where sape are dropped
this.graph = new joint.dia.Graph,
this.paper = new joint.dia.Paper({
el: $('#paper'),
model: this.graph
});
// Canvas from which you take shapes
this.stencilGraph = new joint.dia.Graph,
this.stencilPaper = new joint.dia.Paper({
el: $('#stencil'),
height: 60,
model: this.stencilGraph,
interactive: false
});
var r1 = new joint.shapes.basic.Rect({
position: {
x: 10,
y: 10
},
size: {
width: 100,
height: 40
},
attrs: {
text: {
text: 'Rect1'
}
}
});
var r2 = new joint.shapes.basic.Rect({
position: {
x: 120,
y: 10
},
size: {
width: 100,
height: 40
},
attrs: {
text: {
text: 'Rect2'
}
}
});
this.stencilGraph.addCells([r1, r2]);
let _this = this;
this.stencilPaper.on('cell:pointerdown', function (cellView, e, x, y) {
$('body').append('<div id="flyPaper" style="position:fixed;z-index:100;opacity:.7;pointer-event:none;"></div>');
var flyGraph = new joint.dia.Graph,
flyPaper = new joint.dia.Paper({
el: $('#flyPaper'),
model: flyGraph,
interactive: false
}),
flyShape = cellView.model.clone(),
pos = cellView.model.position(),
offset = {
x: x - pos.x,
y: y - pos.y
};
flyShape.position(0, 0);
flyGraph.addCell(flyShape);
$("#flyPaper").offset({
left: e.pageX - offset.x,
top: e.pageY - offset.y
});
$('body').on('mousemove.fly', function (e) {
$("#flyPaper").offset({
left: e.pageX - offset.x,
top: e.pageY - offset.y
});
});
$('body').on('mouseup.fly', function (e) {
var x = e.pageX,
y = e.pageY,
target = _this.paper.$el.offset();
// Dropped over paper ?
if (x > target.left && x < target.left + _this.paper.$el.width() && y > target.top && y < target.top + _this.paper.$el.height()) {
var s = flyShape.clone();
s.position(x - target.left - offset.x, y - target.top - offset.y);
_this.graph.addCell(s);
}
$('body').off('mousemove.fly').off('mouseup.fly');
flyShape.remove();
$('#flyPaper').remove();
});
})
}
dragCopyElementsWithPort() {
// Canvas where sape are dropped
this.graph = new joint.dia.Graph,
this.paper = new joint.dia.Paper({
el: $('#paper'),
model: this.graph,
height: 700,
width: 1000,
gridSize: 2,
drawGrid: true
});
// create paper
// this.paper = new joint.dia.Paper({
// el: document.getElementById('paper'),
// width: 1000,
// height: 1000,
// model: this.graph,
// gridSize: 2,
// drawGrid: true
// });
this.paper.setGrid({
name: 'dot',
args:
{ color: 'black', thickness: 2, scaleFactor: 8 }
}).drawGrid();
// Canvas from which you take shapes
this.stencilGraph = new joint.dia.Graph,
this.stencilPaper = new joint.dia.Paper({
el: $('#stencil'),
height: 700,
width: 382,
model: this.stencilGraph,
interactive: false
});
let elementWithPort = this.creatElementWithPorts();
// let elementWithPort = this.createCustomElement();
// let elementWithPort = this.myCustomElementGenerator();
elementWithPort.forEach(element => {
this.stencilGraph.addCell(element);
});
let _this = this;
this.stencilPaperEventListeners(_this);
this.drawAreapaperEventListerners();
}
resetAll(paper) {
this.paper.drawBackground({
color: 'white'
})
var elements = this.paper.model.getElements();
for (var i = 0, ii = elements.length; i < ii; i++) {
var currentElement = elements[i];
currentElement.attr('body/stroke', 'black');
}
var links = this.paper.model.getLinks();
for (var j = 0, jj = links.length; j < jj; j++) {
var currentLink = links[j];
currentLink.attr('line/stroke', 'black');
currentLink.label(0, {
attrs: {
body: {
stroke: 'black'
}
}
})
}
}
onDrag(evt) {
// transform client to paper coordinates
var p = evt.data.paper.snapToGrid({
x: evt.clientX,
y: evt.clientY
});
// manually execute the linkView mousemove handler
evt.data.view.pointermove(evt, p.x, p.y);
}
onDragEnd(evt) {
// manually execute the linkView mouseup handler
evt.data.view.pointerup(evt);
$(document).off('.example');
}
stencilPaperEventListeners(_this) {
this.stencilPaper.on('cell:pointerdown', function (cellView, e, x, y) {
$('body').append('<div id="flyPaper" style="position:fixed;z-index:100;opacity:.7;pointer-event:none;"></div>');
var flyGraph = new joint.dia.Graph,
flyPaper = new joint.dia.Paper({
el: $('#flyPaper'),
model: flyGraph,
interactive: true
}),
flyShape = cellView.model.clone(),
pos = cellView.model.position(),
offset = {
x: x - pos.x,
y: y - pos.y
};
flyShape.position(0, 0);
flyGraph.addCell(flyShape);
$("#flyPaper").offset({
left: e.pageX - offset.x,
top: e.pageY - offset.y
});
$('body').on('mousemove.fly', function (e) {
$("#flyPaper").offset({
left: e.pageX - offset.x,
top: e.pageY - offset.y
});
});
let elementabove, elementBelow;
$('body').on('mouseup.fly', function (e) {
console.log(this);
var x = e.pageX,
y = e.pageY,
target = _this.paper.$el.offset();
// Dropped over paper ?
if (x > target.left && x < target.left + _this.paper.$el.width() && y > target.top && y < target.top + _this.paper.$el.height()) {
var s = flyShape.clone();
// var coordinates = new g.Point(x, y);
// elementabove = s;
// elementBelow = _this.paper.model.findModelsFromPoint(coordinates).find(function(el) {
// return (el.id !== elementabove.id);
// });
// elementBelow =_this.paper.findModelsFromPoint(coordinates).find(function(el) {
// return (el.id !== elementabove.id);
// });
// elementBelow.embed(elementabove);
s.position(x - target.left - offset.x, y - target.top - offset.y);
_this.graph.addCell(s);
// let elementssss = (_this.graph.getElements());
// console.log("elementsss", elementssss);
// let elementBelow = elementssss[0];
// let elementAbove;
// if(elementssss[1]) {
// elementAbove = elementssss[1];
// elementBelow.embed(elementabove);
// }
}
$('body').off('mousemove.fly').off('mouseup.fly');
flyShape.remove();
$('#flyPaper').remove();
});
_this.paper.on('mouse')
})
}
drawAreapaperEventListerners() {
// create event listerners
let _this = this;
this.paper.on('element:pointerdblclick', function (elementView) {
_this.resetAll(this);
_this.selectedElement = elementView.model;
var currentElement = elementView.model;
currentElement.attr('body/stroke', 'orange');
// currentElement.attr('label/text', "abc");
});
this.paper.on('blank:pointerdblclick', function () {
_this.resetAll(this);
this.drawBackground({
color: 'orange'
});
});
this.paper.on('link:pointerclick', function (linkView) {
_this.resetAll(this);
let currentElement = linkView.model;
currentElement.appendLabel({
attrs: {
text: {
text: "Hello to new link!"
}
}
});
});
this.paper.on('blank:pointerdown', function (evt, x, y) {
let linkView = this.getDefaultLink()
.set({
'source': { x: x, y: y },
'target': { x: x, y: y }
})
.addTo(this.model)
.findView(this);
linkView.startArrowheadMove('target');
$(document).on({
'mousemove.example': _this.onDrag,
'mouseup.example': _this.onDragEnd
}, {
// shared data between listeners
view: linkView,
paper: this
});
});
this.paper.on({
// 'element:pointerdown': function(elementView, evt) {
// evt.data = elementView.model.position();
// },
'element:pointerup': function(elementView, evt, x, y) {
var coordinates = new g.Point(x, y);
var elementAbove = elementView.model;
var elementBelow = this.model.findModelsFromPoint(coordinates).find(function(el) {
return (el.id !== elementAbove.id);
});
if(elementBelow) elementBelow.embed(elementAbove);
}
}); //end of my event
}
createCustomElement() {
joint.shapes.html = {};
joint.shapes.html.Element = joint.shapes.basic.Rect.extend({
defaults: joint.util.deepSupplement({
type: 'html.Element',
attrs: {
rect: { stroke: 'none', 'fill-opacity': 0 }
}
}, joint.shapes.basic.Rect.prototype.defaults)
});
// / Create a custom view for that element that displays an HTML div above it.
// -------------------------------------------------------------------------
joint.shapes.html.ElementView = joint.dia.ElementView.extend({
template: [
'<div class="html-element">',
'<button class="delete">x</button>',
'<label></label>',
'<span></span>', '<br/>',
'<select><option>--</option><option>one</option><option>two</option></select>',
'<input type="text" value="I\'m HTML input" />',
'</div>'
].join(''),
initialize: function() {
_.bindAll(this, 'updateBox');
joint.dia.ElementView.prototype.initialize.apply(this, arguments);
this.$box = $(_.template(this.template)());
// Prevent paper from handling pointerdown.
this.$box.find('input,select').on('mousedown click', function(evt) {
evt.stopPropagation();
});
// This is an example of reacting on the input change and storing the input data in the cell model.
this.$box.find('input').on('change', _.bind(function(evt) {
this.model.set('input', $(evt.target).val());
}, this));
this.$box.find('select').on('change', _.bind(function(evt) {
this.model.set('select', $(evt.target).val());
}, this));
this.$box.find('select').val(this.model.get('select'));
this.$box.find('.delete').on('click', _.bind(this.model.remove, this.model));
// Update the box position whenever the underlying model changes.
this.model.on('change', this.updateBox, this);
// Remove the box when the model gets removed from the graph.
this.model.on('remove', this.removeBox, this);
this.updateBox();
},
render: function() {
joint.dia.ElementView.prototype.render.apply(this, arguments);
this.paper.$el.prepend(this.$box);
this.updateBox();
return this;
},
updateBox: function() {
// Set the position and dimension of the box so that it covers the JointJS element.
var bbox = this.model.getBBox();
// Example of updating the HTML with a data stored in the cell model.
this.$box.find('label').text(this.model.get('label'));
this.$box.find('span').text(this.model.get('select'));
this.$box.css({
width: bbox.width,
height: bbox.height,
left: bbox.x,
top: bbox.y,
transform: 'rotate(' + (this.model.get('angle') || 0) + 'deg)'
});
},
removeBox: function(evt) {
this.$box.remove();
}
});
// Create JointJS elements and add them to the graph as usual.
// -----------------------------------------------------------
var el1 = new joint.shapes.html.Element({
position: { x: 10, y: 10 },
size: { width: 170, height: 100 },
label: 'I am HTML',
select: 'one'
});
var el2 = new joint.shapes.html.Element({
position: { x: 370, y: 160 },
size: { width: 170, height: 100 },
label: 'Me too',
select: 'two'
});
var l = new joint.dia.Link({
source: { id: el1.id },
target: { id: el2.id },
attrs: { '.connection': { 'stroke-width': 5, stroke: '#34495E' }}
});
let elementArray : any[] = [];
elementArray.push(el1, el2);
return elementArray;
}
myCustomElementGenerator() {
var Ellipse = joint.dia.Element.define('examples.Ellipse', {
// default attributes
markup: [{
tagName: 'ellipse',
selector: 'ellipse' // not necessary but faster
}],
attrs: {
ellipse: {
fill: 'white',
stroke: 'black',
strokeWidth: 4,
refRx: .5,
refRy: .5,
refCx: .5,
refCy: .5
}
}
});
var Rectangle = joint.shapes.standard.Rectangle.define('examples.CustomRectangle', {
markup: [{
tagName: 'body',
selector: 'body' // not necessary but faster
},
{
tagName: 'label',
selector: 'label'
}],
attrs: {
body: {
rx: 10, // add a corner radius
ry: 10,
strokeWidth: 1,
fill: 'cornflowerblue'
},
label: {
textAnchor: 'left', // align text to left
refX: 10, // offset text from right edge of model bbox
fill: 'white',
fontSize: 18,
text: 'mad mad mad'
}
}
})
var customElement = (new joint.dia.Element.examples.Ellipse()).position(100, 100).size(120, 50);
let elementsArray = [];
elementsArray.push(customElement);
var customRect = new Rectangle().position(100, 200).size(120, 120);
elementsArray.push(customRect);
return elementsArray;
}
convertGraphToJson() {
this.grapJson = JSON.stringify(this.graph.toJSON());
// this.grapJson = this.graph.toJSON();
console.log(this.graph.toJSON());
console.log(this.grapJson);
this.sourceMode = true;
}
setNewValue(event) {
// this.selectedElement.attr('label/text', event.currentTarget.value);
}
convertJsonToGraph() {
this.sourceMode = false;
}
zoomIn() {
var graphScale = 1;
graphScale += 0.1;
this.paper.scale(graphScale, graphScale);
}
zoomOut() {
var graphScale = 1;
graphScale -= 0.1;
this.paper.scale(graphScale, graphScale);
}
createContainerElements() {
this.graph = new joint.dia.Graph;
this.paper = new joint.dia.Paper({
el: document.getElementById('paper'),
width: 800,
height: 400,
gridSize: 1,
model: this.graph,
snapLinks: true,
linkPinning: false,
embeddingMode: true,
clickThreshold: 5,
defaultConnectionPoint: { name: 'boundary' },
highlighting: {
'default': {
name: 'stroke',
options: {
padding: 6
}
},
'embedding': {
name: 'addClass',
options: {
className: 'highlighted-parent'
}
}
},
validateEmbedding: function(childView, parentView) {
return parentView.model instanceof joint.shapes.devs.Coupled;
},
validateConnection: function(sourceView, sourceMagnet, targetView, targetMagnet) {
return sourceMagnet != targetMagnet;
}
});
let c1 = new joint.shapes.devs.Coupled({
position: {
x: 230,
y: 50
},
size: {
width: 300,
height: 300
}
});
c1.set('inPorts', ['in']);
c1.set('outPorts', ['out 1', 'out 2']);
var a1 = new joint.shapes.devs.Atomic({
position: {
x: 360,
y: 260
},
inPorts: ['xy'],
outPorts: ['x', 'y']
});
var a2 = new joint.shapes.devs.Atomic({
position: {
x: 50,
y: 160
},
outPorts: ['out']
});
var a3 = new joint.shapes.devs.Atomic({
position: {
x: 650,
y: 50
},
size: {
width: 100,
height: 300
},
inPorts: ['a', 'b']
});
[c1, a1, a2, a3].forEach(function(element) {
element.attr({
'.body': {
'rx': 6,
'ry': 6
}
});
});
this.graph.addCells([c1, a1, a2, a3]);
c1.embed(a1);
this.connect(a2, 'out', c1, 'in');
this.connect(c1, 'in', a1, 'xy');
this.connect(a1, 'x', c1, 'out 1');
this.connect(a1, 'y', c1, 'out 2');
this.connect(c1, 'out 1', a3, 'a');
this.connect(c1, 'out 2', a3, 'b');
var strokeDasharrayPath = '.body/strokeDasharray';
let _this = this;
this.paper.on('element:pointerdblclick', function(elementView) {
var element = elementView.model;
if (element.get('type') === 'devs.Atomic') {
_this.toggleDelegation(element);
}
});
this.paper.setInteractivity(function(elementView) {
return {
stopDelegation: !elementView.model.attr(strokeDasharrayPath)
};
});
} // function end
// function
connect(source, sourcePort, target, targetPort) {
var link = new joint.shapes.devs.Link({
source: {
id: source.id,
port: sourcePort
},
target: {
id: target.id,
port: targetPort
}
});
link.addTo(this.graph).reparent();
}
toggleDelegation(element) {
var strokeDasharrayPath = '.body/strokeDasharray';
element.attr(strokeDasharrayPath, element.attr(strokeDasharrayPath) ? '' : '15,1');
}
createContainerElemnetsByDragDrop() {
}
}