diff --git a/graph-diagram.js b/graph-diagram.js index f807134..5c87699 100644 --- a/graph-diagram.js +++ b/graph-diagram.js @@ -1,3 +1,4 @@ + gd = {}; (function() { @@ -57,6 +58,7 @@ gd = {}; var caption; var classes = []; var properties = new Properties(model.stylePrototype.nodeProperties); + var isRectangle = false; this.class = function(classesString) { if (arguments.length == 1) { @@ -174,6 +176,15 @@ gd = {}; return properties; }; + this.isRectangle = function(choice) { + //swap between shapes + if (arguments.length == 1) { + isRectangle = choice; + return isRectangle; + } + return isRectangle; + }; + this.style = styleSet(model.stylePrototype.node); }; @@ -1394,17 +1405,20 @@ gd = {}; return d.model.class().join(" ") + " " + "node-id-" + d.model.id; } - var circles = view.selectAll("circle.node") + var rectangles = view.selectAll("rect.node") .data(nodes); - circles.exit().remove(); + rectangles.exit().remove(); - circles.enter().append("svg:circle") - .attr("class", nodeClasses); + rectangles.enter().append("svg:rect") + .attr("class",nodeClasses); - circles - .attr("r", function(node) { - return node.radius.mid(); + rectangles + .attr("width", function(node) { + return node.radius.mid() * 2; + }) + .attr("height", function(node) { + return node.radius.mid() * 2; }) .attr("fill", function(node) { return node.model.style("background-color"); @@ -1415,8 +1429,25 @@ gd = {}; .attr("stroke-width", function(node) { return node.model.style("border-width"); }) - .attr("cx", field("x")) - .attr("cy", field("y")); + .attr("rx", function(node) { + if(node.model.isRectangle()) + return "30"; + else + return node.radius.mid(); + }) + .attr("ry", function(node) { + if(node.model.isRectangle()) + return "30"; + else + return node.radius.mid(); + }) + .attr("x", function(node) { + return node.x - node.radius.inside(); + }) + .attr("y", function(node) { + return node.y - node.radius.inside(); + }); + function captionClasses(d) { return "caption " + d.node.model.class(); diff --git a/graph-editor.js b/graph-editor.js index c0952a4..968ca5a 100644 --- a/graph-editor.js +++ b/graph-editor.js @@ -21,50 +21,80 @@ window.onload = function() var diagram = gd.diagram() .scaling(gd.scaling.centerOrScaleDiagramToFitSvg) .overlay(function(layoutModel, view) { - var nodeOverlays = view.selectAll("circle.node.overlay") + var nodeOverlays = view.selectAll("rect.node.overlay") .data(layoutModel.nodes); nodeOverlays.exit().remove(); - nodeOverlays.enter().append("circle") + nodeOverlays.enter().append("rect") .attr("class", "node overlay") .call( d3.behavior.drag().on( "drag", drag ).on( "dragend", dragEnd ) ) .on( "dblclick", editNode ); nodeOverlays - .attr("r", function(node) { - return node.radius.outside(); + .attr("width", function(node) { + return node.radius.outside() * 2; + }) + .attr("height", function(node) { + return node.radius.outside() * 2; }) .attr("stroke", "none") .attr("fill", "rgba(255, 255, 255, 0)") - .attr("cx", function(node) { - return node.x; + .attr("rx", function(node) { + if(node.model.isRectangle()) + return "30"; + else + return node.radius.outside(); + }) + .attr("ry", function(node) { + if(node.model.isRectangle()) + return "30"; + else + return node.radius.outside(); + }) + .attr("x", function(node) { + return node.x - node.radius.outside() + node.radius.borderWidth / 2; }) - .attr("cy", function(node) { - return node.y; + .attr("y", function(node) { + return node.y - node.radius.outside() + node.radius.borderWidth / 2; }); - var nodeRings = view.selectAll("circle.node.ring") + var nodeRings = view.selectAll("rect.node.ring") .data(layoutModel.nodes); nodeRings.exit().remove(); - nodeRings.enter().append("circle") + nodeRings.enter().append("rect") .attr("class", "node ring") .call( d3.behavior.drag().on( "drag", dragRing ).on( "dragend", dragEnd ) ); nodeRings - .attr("r", function(node) { - return node.radius.outside() + 5; + .attr("width", function(node) { + return node.radius.outside() * 2 + node.radius.borderWidth; + }) + .attr("height", function(node) { + return node.radius.outside() * 2 + node.radius.borderWidth; }) .attr("fill", "none") .attr("stroke", "rgba(255, 255, 255, 0)") .attr("stroke-width", "10px") - .attr("cx", function(node) { - return node.x; + .attr("rx", function(node) { + if(node.model.isRectangle()) + return "35"; + else + return node.radius.outside() + node.radius.borderWidth; + }) + .attr("ry", function(node) { + if(node.model.isRectangle()) + return "35"; + else + return node.radius.outside() + node.radius.borderWidth; }) - .attr("cy", function(node) { - return node.y; + .attr("x", function(node) { + return node.x - node.radius.outside(); + }) + .attr("y", function(node) { + return node.y - node.radius.outside(); }); var relationshipsOverlays = view.selectAll("path.relationship.overlay") @@ -92,7 +122,7 @@ window.onload = function() svg .data([graphModel]) .call(diagram); - updateSvgDownloadLink(); + updateSvgDownloadLink(); } function save( markup ) @@ -203,13 +233,33 @@ window.onload = function() captionField.node().value = node.caption() || ""; captionField.node().select(); + var propertiesField = editor.select("#node_properties"); propertiesField.node().value = node.properties().list().reduce(function(previous, property) { return previous + property.key + ": " + property.value + "\n"; }, ""); + //current color values + var backgroundColor = editor.select("#node_bg_color").node(); + var textColor = editor.select("#node_txt_color").node(); + backgroundColor.value = node.style("background-color"); + textColor.value = node.style("color"); + function saveChange() { + //updating node's text and background color + node.style("background-color", backgroundColor.value); + node.style("color", textColor.value); + + //updating node's shape + selectedShape = editor.select("#node-shape").node().value; + if(selectedShape == "Circle") { + node.isRectangle(false); + } + else { + node.isRectangle(true); + } + node.caption( captionField.node().value ); node.properties().clearAll(); propertiesField.node().value.split("\n").forEach(function(line) { @@ -222,6 +272,7 @@ window.onload = function() } } }); + save( formatMarkup() ); draw(); cancelModal(); @@ -304,6 +355,7 @@ window.onload = function() function formatMarkup() { + //To-Do: Add colors and shape settings, also add rectangle shape to bootstrap styles var container = d3.select( "body" ).append( "div" ); gd.markup.format( graphModel, container ); var markup = container.node().innerHTML; @@ -363,10 +415,12 @@ window.onload = function() d3.select( "#save_markup" ).on( "click", useMarkupFromMarkupEditor ); - function updateSvgDownloadLink() { - var rawSvg = new XMLSerializer().serializeToString(d3.select("#canvas svg" ).node()); - d3.select("#downloadSvgButton").attr('href', "data:image/svg+xml;base64," + btoa( rawSvg )); - } + function updateSvgDownloadLink() + { + var rawSvg = new XMLSerializer().serializeToString(d3.select("#canvas svg" ).node()); + var rawSvg = new XMLSerializer().serializeToString(d3.select("#canvas svg" ).node()); + d3.select("#downloadSvgButton").attr('href', "data:image/svg+xml;base64," + btoa( rawSvg )); + } var openConsoleWithCypher = function (evt) { @@ -416,12 +470,47 @@ window.onload = function() graphModel.internalScale(d3.select("#internalScale").node().value); draw(); } + + function importDiagram() { + //To-Do: read selected style from file + if (window.File && window.FileReader && window.FileList && window.Blob) { + var fileSelected = document.createElement("input"); + fileSelected.setAttribute("type", "file"); + + fileSelected.addEventListener("change", function(e) { + //Get the file object + var fileTobeRead = fileSelected.files[0]; + + var fileReader = new FileReader(); + fileReader.onload = function (e) { + graphModel = parseMarkup(fileReader.result); + draw(); + } + fileReader.readAsText(fileTobeRead); + }, false); + fileSelected.click(); + } + else { + alert("Files are not supported"); + } + } + + function saveSession() { + //To-Do: save selected style to file + var text = formatMarkup(); + var filename = $("#input-fileName").val() + var blob = new Blob([text], {type: "text/plain;charset=utf-8"}); + saveAs(blob, filename+".graph"); + } + d3.select("#internalScale").node().value = graphModel.internalScale(); d3.select(window).on("resize", draw); d3.select("#internalScale" ).on("change", changeInternalScale); + d3.select( "#saveSessionButton" ).on( "click", saveSession ); d3.select( "#exportMarkupButton" ).on( "click", exportMarkup ); - d3.select( "#exportCypherButton" ).on( "click", exportCypher ); + d3.select( "#importDiagram" ).on( "click", importDiagram ); + d3.select( "#exportCypherButton" ).on( "click", exportCypher ); d3.select( "#chooseStyleButton" ).on( "click", chooseStyle ); d3.selectAll( ".modal-dialog" ).on( "click", function () { diff --git a/img/bootstrap-colorpicker/alpha-horizontal.png b/img/bootstrap-colorpicker/alpha-horizontal.png new file mode 100644 index 0000000..f831889 Binary files /dev/null and b/img/bootstrap-colorpicker/alpha-horizontal.png differ diff --git a/img/bootstrap-colorpicker/alpha.png b/img/bootstrap-colorpicker/alpha.png new file mode 100644 index 0000000..2e53a30 Binary files /dev/null and b/img/bootstrap-colorpicker/alpha.png differ diff --git a/img/bootstrap-colorpicker/hue-horizontal.png b/img/bootstrap-colorpicker/hue-horizontal.png new file mode 100644 index 0000000..3dcd594 Binary files /dev/null and b/img/bootstrap-colorpicker/hue-horizontal.png differ diff --git a/img/bootstrap-colorpicker/hue.png b/img/bootstrap-colorpicker/hue.png new file mode 100644 index 0000000..6f5ec2e Binary files /dev/null and b/img/bootstrap-colorpicker/hue.png differ diff --git a/img/bootstrap-colorpicker/saturation.png b/img/bootstrap-colorpicker/saturation.png new file mode 100644 index 0000000..170841c Binary files /dev/null and b/img/bootstrap-colorpicker/saturation.png differ diff --git a/index.html b/index.html index 9de1066..5abedbe 100644 --- a/index.html +++ b/index.html @@ -2,48 +2,61 @@
+ + -