From 2d86d8e47d7a9cdb318c2867f6646fd7dad6b725 Mon Sep 17 00:00:00 2001 From: Astrid Elocson Date: Mon, 12 Jan 2015 20:03:37 +0000 Subject: [PATCH] Introduce arrow option on railroad widget --- plugins/tiddlywiki/railroad/components.js | 10 +++-- plugins/tiddlywiki/railroad/doc/readme.tid | 1 + .../railroad/files/railroad-diagrams.css | 5 +++ .../railroad/files/railroad-diagrams.js | 42 +++++++++++++++---- plugins/tiddlywiki/railroad/parser.js | 8 ++-- plugins/tiddlywiki/railroad/wrapper.js | 4 +- 6 files changed, 53 insertions(+), 17 deletions(-) diff --git a/plugins/tiddlywiki/railroad/components.js b/plugins/tiddlywiki/railroad/components.js index 959db3840..fed6f82c7 100644 --- a/plugins/tiddlywiki/railroad/components.js +++ b/plugins/tiddlywiki/railroad/components.js @@ -177,10 +177,11 @@ Optional.prototype.toSvg = function() { return railroad.Optional(this.child.toSvg(), this.normal ? undefined : "skip"); } -var OptionalRepeated = function(content,separator,normal) { +var OptionalRepeated = function(content,separator,normal,wantArrow) { this.initialiseWithChild("OptionalRepeated",content); this.separator = toSingleChild(separator); this.normal = normal; + this.wantArrow = wantArrow; }; OptionalRepeated.prototype = new Component(); @@ -189,12 +190,13 @@ OptionalRepeated.prototype.toSvg = function() { // Call ZeroOrMore(component,separator,"skip") var separatorSvg = this.separator ? this.separator.toSvg() : null; var skip = this.normal ? undefined : "skip"; - return railroad.ZeroOrMore(this.child.toSvg(),separatorSvg,skip); + return railroad.ZeroOrMore(this.child.toSvg(),separatorSvg,skip,this.wantArrow); } -var Repeated = function(content,separator) { +var Repeated = function(content,separator,wantArrow) { this.initialiseWithChild("Repeated",content); this.separator = toSingleChild(separator); + this.wantArrow = wantArrow; }; Repeated.prototype = new Component(); @@ -202,7 +204,7 @@ Repeated.prototype = new Component(); Repeated.prototype.toSvg = function() { // Call OneOrMore(component,separator) var separatorSvg = this.separator ? this.separator.toSvg() : null; - return railroad.OneOrMore(this.child.toSvg(),separatorSvg); + return railroad.OneOrMore(this.child.toSvg(),separatorSvg,this.wantArrow); } var Link = function(content,options) { diff --git a/plugins/tiddlywiki/railroad/doc/readme.tid b/plugins/tiddlywiki/railroad/doc/readme.tid index 04536dae9..2f55fd375 100644 --- a/plugins/tiddlywiki/railroad/doc/readme.tid +++ b/plugins/tiddlywiki/railroad/doc/readme.tid @@ -8,6 +8,7 @@ The content of the `<$railroad>` widget is ignored. |!Attribute |!Description | |text |Text in a special syntax that defines the diagram's layout | +|arrow |If set to `no`, repeat paths do not have an arrow on them. The default is `yes` | |mode |If set to `debug`, the diagram will display its internal tree structure. The default mode is `svg` | The entire `text` can be transcluded from another tiddler: diff --git a/plugins/tiddlywiki/railroad/files/railroad-diagrams.css b/plugins/tiddlywiki/railroad/files/railroad-diagrams.css index 4f9ba13b3..cb10b8475 100644 --- a/plugins/tiddlywiki/railroad/files/railroad-diagrams.css +++ b/plugins/tiddlywiki/railroad/files/railroad-diagrams.css @@ -20,4 +20,9 @@ svg.railroad-diagram rect { stroke-width: 3; stroke: black; fill: hsl(120,100%,90%); +} + +/* TiddlyWiki extensions */ +svg.railroad-diagram path.arrow { + stroke-width: 1; } \ No newline at end of file diff --git a/plugins/tiddlywiki/railroad/files/railroad-diagrams.js b/plugins/tiddlywiki/railroad/files/railroad-diagrams.js index b5bae739b..67c17e06e 100644 --- a/plugins/tiddlywiki/railroad/files/railroad-diagrams.js +++ b/plugins/tiddlywiki/railroad/files/railroad-diagrams.js @@ -111,9 +111,9 @@ var temp = (function(options) { return str; } - function Path(x,y) { - if(!(this instanceof Path)) return new Path(x,y); - FakeSVG.call(this, 'path'); + function Path(x,y,attrs) { + if(!(this instanceof Path)) return new Path(x,y,attrs); + FakeSVG.call(this, 'path', attrs); this.attrs.d = "M"+x+' '+y; } subclassOf(Path, FakeSVG); @@ -156,6 +156,11 @@ var temp = (function(options) { this.attrs.d += 'h.5'; return this; } +/* TiddlyWiki: added support for arbitrary straight lines */ + Path.prototype.line = function(dx,dy) { + this.attrs.d += "l"+dx+" "+dy; + return this; + } function Diagram(items) { if(!(this instanceof Diagram)) return new Diagram([].slice.call(arguments)); @@ -325,15 +330,27 @@ var temp = (function(options) { throw "Unknown value for Optional()'s 'skip' argument."; } - function OneOrMore(item, rep) { - if(!(this instanceof OneOrMore)) return new OneOrMore(item, rep); +/* TiddlyWiki: added wantArrow */ + function OneOrMore(item, rep, wantArrow) { + if(!(this instanceof OneOrMore)) return new OneOrMore(item, rep, wantArrow); FakeSVG.call(this, 'g'); + +/* TiddlyWiki: code added */ + this.wantArrow = wantArrow; + rep = rep || (new Skip); this.item = wrapString(item); this.rep = wrapString(rep); this.width = Math.max(this.item.width, this.rep.width) + Diagram.ARC_RADIUS*2; this.up = this.item.up; this.down = Math.max(Diagram.ARC_RADIUS*2, this.item.down + Diagram.VERTICAL_SEPARATION + this.rep.up + this.rep.down); + +/* TiddlyWiki: code added, including moving calculation of distanceFromY (of the repeat arc) to here */ + this.distanceFromY = Math.max(Diagram.ARC_RADIUS*2, this.item.down+Diagram.VERTICAL_SEPARATION+this.rep.up); + if(this.wantArrow && this.distanceFromY < Diagram.ARC_RADIUS*3) { + this.distanceFromY += Diagram.ARC_RADIUS/2; + this.down += Diagram.ARC_RADIUS/2; + } } subclassOf(OneOrMore, FakeSVG); OneOrMore.prototype.needsSpace = true; @@ -350,16 +367,25 @@ var temp = (function(options) { Path(x+this.width-Diagram.ARC_RADIUS,y).right(Diagram.ARC_RADIUS).addTo(this); // Draw repeat arc - var distanceFromY = Math.max(Diagram.ARC_RADIUS*2, this.item.down+Diagram.VERTICAL_SEPARATION+this.rep.up); +/* TiddlyWiki: moved calculation of distanceFromY from here to constructor */ + var distanceFromY = this.distanceFromY; + Path(x+Diagram.ARC_RADIUS,y).arc('nw').down(distanceFromY-Diagram.ARC_RADIUS*2).arc('ws').addTo(this); this.rep.format(x+Diagram.ARC_RADIUS, y+distanceFromY, this.width - Diagram.ARC_RADIUS*2).addTo(this); Path(x+this.width-Diagram.ARC_RADIUS, y+distanceFromY).arc('se').up(distanceFromY-Diagram.ARC_RADIUS*2).arc('en').addTo(this); + +/* TiddlyWiki: code added */ + if(this.wantArrow) { + var arrowSize = 2/3 * Diagram.ARC_RADIUS; + Path(x-arrowSize, y+distanceFromY/2 + arrowSize/2, {class:"arrow"}). + line(arrowSize, -arrowSize).line(arrowSize, arrowSize).addTo(this); + } return this; } - function ZeroOrMore(item, rep, skip) { - return Optional(OneOrMore(item, rep), skip); + function ZeroOrMore(item, rep, skip, wantArrow) { + return Optional(OneOrMore(item, rep, wantArrow), skip); } function Start() { diff --git a/plugins/tiddlywiki/railroad/parser.js b/plugins/tiddlywiki/railroad/parser.js index 1dfd50d29..18db133e7 100644 --- a/plugins/tiddlywiki/railroad/parser.js +++ b/plugins/tiddlywiki/railroad/parser.js @@ -35,9 +35,10 @@ x y z sequence var components = require("$:/plugins/tiddlywiki/railroad/components.js").components; -var Parser = function(widget,source) { +var Parser = function(widget,source,wantArrow) { this.widget = widget; this.source = source; + this.wantArrow = wantArrow; this.tokens = this.tokenise(source); this.tokenPos = 0; this.advance(); @@ -201,7 +202,8 @@ Parser.prototype.parseOptional = function() { } this.close("]"); // Create a component - return repeated ? new components.OptionalRepeated(content,separator,normal) : new components.Optional(content,normal); + return repeated ? new components.OptionalRepeated(content,separator,normal,this.wantArrow) + : new components.Optional(content,normal); }; Parser.prototype.parseRepeated = function() { @@ -217,7 +219,7 @@ Parser.prototype.parseRepeated = function() { // Consume the closing bracket this.close("}"); // Create a component - return new components.Repeated(content,separator); + return new components.Repeated(content,separator,this.wantArrow); }; Parser.prototype.parseSequence = function() { diff --git a/plugins/tiddlywiki/railroad/wrapper.js b/plugins/tiddlywiki/railroad/wrapper.js index a4e8c7032..82d89172d 100644 --- a/plugins/tiddlywiki/railroad/wrapper.js +++ b/plugins/tiddlywiki/railroad/wrapper.js @@ -38,7 +38,7 @@ RailroadWidget.prototype.render = function(parent,nextSibling) { var div = this.document.createElement("div"); try { // Parse the source - var parser = new Parser(this,source); + var parser = new Parser(this,source,this.getAttribute("arrow","yes") === "yes"); // Generate content into the div if(this.getAttribute("mode","svg") === "debug") { this.renderDebug(parser,div); @@ -107,7 +107,7 @@ RailroadWidget.prototype.patchLinks = function(node) { RailroadWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(changedAttributes.text) { + if(changedAttributes.text || changedAttributes.mode || changedAttributes.arrow) { this.refreshSelf(); return true; }