@zakkzhang/tw5-graph 1.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -0
- package/package.json +39 -0
- package/plugins/graph/DefaultColourMappings.multids +8 -0
- package/plugins/graph/ViewTemplateBodyFilter/graph.tid +5 -0
- package/plugins/graph/ViewTemplateBodyFilter/properties.tid +5 -0
- package/plugins/graph/edges/fields/list.tid +7 -0
- package/plugins/graph/edges/fields/tags.tid +7 -0
- package/plugins/graph/edges/functions/links.tid +8 -0
- package/plugins/graph/edges/functions/transcludes.tid +8 -0
- package/plugins/graph/fieldtypes/filter.js +212 -0
- package/plugins/graph/fieldtypes/list.js +31 -0
- package/plugins/graph/fieldtypes/title.js +27 -0
- package/plugins/graph/filterrunprefixes/cache.js +118 -0
- package/plugins/graph/filters/gettyped.js +26 -0
- package/plugins/graph/graphengine.js +38 -0
- package/plugins/graph/icon.tid +16 -0
- package/plugins/graph/images/drag.tid +13 -0
- package/plugins/graph/macros/action.addedge.tid +16 -0
- package/plugins/graph/macros/edges.typed.tid +54 -0
- package/plugins/graph/macros/graph.view.tid +24 -0
- package/plugins/graph/macros/node.default.tid +9 -0
- package/plugins/graph/macros/nodes.neighbors.tid +62 -0
- package/plugins/graph/macros/nodes.writable.tid +37 -0
- package/plugins/graph/macros/properties.persistent.tid +27 -0
- package/plugins/graph/macros/properties.popup.tid +76 -0
- package/plugins/graph/macros/properties.river.tid +27 -0
- package/plugins/graph/macros/properties.settings.tid +56 -0
- package/plugins/graph/macros/properties.stack.tid +17 -0
- package/plugins/graph/macros/tiddlywiki.files +17 -0
- package/plugins/graph/plugin.info +14 -0
- package/plugins/graph/presettypes/edges/fields.tid +18 -0
- package/plugins/graph/presettypes/edges/functions.tid +5 -0
- package/plugins/graph/presettypes/nodes/stack.tid +6 -0
- package/plugins/graph/propertytypes/actions.js +15 -0
- package/plugins/graph/propertytypes/boolean.js +23 -0
- package/plugins/graph/propertytypes/enum.js +25 -0
- package/plugins/graph/propertytypes/image.js +140 -0
- package/plugins/graph/propertytypes/number.js +24 -0
- package/plugins/graph/propertytypes/string.js +13 -0
- package/plugins/graph/propertytypes/tiddlywiki.files +17 -0
- package/plugins/graph/readme.tid +5 -0
- package/plugins/graph/relink/attributes.js +52 -0
- package/plugins/graph/relink/attributes.multids +19 -0
- package/plugins/graph/relink/configprefix.js +76 -0
- package/plugins/graph/relink/fieldedgeprefix.js +39 -0
- package/plugins/graph/relink/fields.multids +11 -0
- package/plugins/graph/relink/graphprefix.js +28 -0
- package/plugins/graph/relink/operators.multids +3 -0
- package/plugins/graph/relink/propertyfields.js +81 -0
- package/plugins/graph/relink/utils.js +99 -0
- package/plugins/graph/settings.tid +13 -0
- package/plugins/graph/startup/messages.js +46 -0
- package/plugins/graph/stylesheets/base.css.tid +263 -0
- package/plugins/graph/stylesheets/fullscreen/core.css +11 -0
- package/plugins/graph/stylesheets/fullscreen/core.css.meta +3 -0
- package/plugins/graph/stylesheets/fullscreen.css.tid +46 -0
- package/plugins/graph/stylesheets/popup.css.tid +107 -0
- package/plugins/graph/subfilters.tid +23 -0
- package/plugins/graph/tags/GraphToolbar.tid +2 -0
- package/plugins/graph/tags/SettingsTab.tid +2 -0
- package/plugins/graph/tags/Template.tid +2 -0
- package/plugins/graph/tags/ViewEditTemplate.tid +2 -0
- package/plugins/graph/templates/live-graph.tid +34 -0
- package/plugins/graph/templates/standard-graph.tid +40 -0
- package/plugins/graph/ui/Buttons/center.tid +38 -0
- package/plugins/graph/ui/Buttons/export.tid +65 -0
- package/plugins/graph/ui/Buttons/fullscreen.tid +35 -0
- package/plugins/graph/ui/Buttons/settings.tid +28 -0
- package/plugins/graph/ui/Buttons/tiddlywiki.files +16 -0
- package/plugins/graph/ui/EditTemplate/Edges.tid +22 -0
- package/plugins/graph/ui/EditTemplate/Neighbors.tid +35 -0
- package/plugins/graph/ui/EditTemplate/Nodes.tid +12 -0
- package/plugins/graph/ui/EditTemplate/Popups.tid +27 -0
- package/plugins/graph/ui/EditTemplate/Properties.tid +21 -0
- package/plugins/graph/ui/EditTemplate/tiddlywiki.files +16 -0
- package/plugins/graph/ui/Modals/NewPropertySet.tid +20 -0
- package/plugins/graph/ui/Modals/NewView.tid +20 -0
- package/plugins/graph/ui/Modals/Select.tid +72 -0
- package/plugins/graph/ui/Modals/SelectField.tid +21 -0
- package/plugins/graph/ui/Modals/SelectTiddler.tid +15 -0
- package/plugins/graph/ui/Modals/Tiddler.tid +22 -0
- package/plugins/graph/ui/Modals/TiddlerHeader.tid +15 -0
- package/plugins/graph/ui/PropertyTypes/boolean.tid +11 -0
- package/plugins/graph/ui/PropertyTypes/color.tid +5 -0
- package/plugins/graph/ui/PropertyTypes/enum.tid +15 -0
- package/plugins/graph/ui/PropertyTypes/number.tid +17 -0
- package/plugins/graph/ui/Settings/Engine.tid +23 -0
- package/plugins/graph/ui/Settings/Graphs/EditTemplate.tid +52 -0
- package/plugins/graph/ui/Settings/Graphs.tid +49 -0
- package/plugins/graph/ui/Settings/Properties/ObjectsTypeTemplate.tid +44 -0
- package/plugins/graph/ui/Settings/Properties.tid +14 -0
- package/plugins/graph/ui/Settings/Toolbar.tid +5 -0
- package/plugins/graph/ui/SideBar/Graph.tid +77 -0
- package/plugins/graph/ui/Toolbars/GraphToolbar.tid +15 -0
- package/plugins/graph/ui/ViewTemplate/graph-object.tid +13 -0
- package/plugins/graph/ui/ViewTemplate/graph.tid +11 -0
- package/plugins/graph/ui/ViewTemplate/properties.tid +80 -0
- package/plugins/graph/ui/grouped-tabs.tid +109 -0
- package/plugins/graph/ui/selector.tid +74 -0
- package/plugins/graph/utils.js +148 -0
- package/plugins/graph/widgets/action-delay.js +72 -0
- package/plugins/graph/widgets/action-modal.js +121 -0
- package/plugins/graph/widgets/action-typed.js +56 -0
- package/plugins/graph/widgets/action-with.js +70 -0
- package/plugins/graph/widgets/boundingbox.js +126 -0
- package/plugins/graph/widgets/fieldTranscriber.js +98 -0
- package/plugins/graph/widgets/fieldtranscriber/filter.js +93 -0
- package/plugins/graph/widgets/fieldtranscriber/json.js +34 -0
- package/plugins/graph/widgets/fieldtranscriber/plain.js +11 -0
- package/plugins/graph/widgets/graphobject.js +120 -0
- package/plugins/graph/widgets/messagerelay.js +115 -0
- package/plugins/graph/widgets/properties.js +131 -0
- package/plugins/graph/widgets/subclass/edge.js +47 -0
- package/plugins/graph/widgets/subclass/graph.js +424 -0
- package/plugins/graph/widgets/subclass/node.js +44 -0
- package/plugins/graph/widgets/tiddlywiki.files +43 -0
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
/*\
|
|
2
|
+
|
|
3
|
+
Widget for creating graphs.
|
|
4
|
+
|
|
5
|
+
\*/
|
|
6
|
+
|
|
7
|
+
"use strict";
|
|
8
|
+
|
|
9
|
+
var utils = require("../../utils.js");
|
|
10
|
+
|
|
11
|
+
var PropertyTypes = $tw.modules.getModulesByTypeAsHashmap("graphpropertytype");
|
|
12
|
+
// Let's collect all the possible graph object types. We might need to
|
|
13
|
+
// reference their base classes later.
|
|
14
|
+
var GraphObjectTypes = {};
|
|
15
|
+
$tw.modules.forEachModuleOfType("widget-subclass", function(title, module) {
|
|
16
|
+
if (module.baseClass == "graphobject") {
|
|
17
|
+
module.graphObjectType = module.prototype.graphObjectType;
|
|
18
|
+
GraphObjectTypes[module.graphObjectType] = module;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
var graphColors = {
|
|
23
|
+
nodeColor: "graph-node-color",
|
|
24
|
+
fontColor: "graph-font-color",
|
|
25
|
+
// We pass along the background too, even though it's probably covered
|
|
26
|
+
// by CSS. Some engines might need this for other coloring effects.
|
|
27
|
+
graphColor: "graph-background"
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
exports.baseClass = "graphobject";
|
|
31
|
+
exports.name = "graph";
|
|
32
|
+
|
|
33
|
+
exports.constructor = function(parseTreeNode, options) {
|
|
34
|
+
this.initialise(parseTreeNode, options);
|
|
35
|
+
utils.registerForGarbageCollection(this);
|
|
36
|
+
this.window = utils.window();
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/*
|
|
40
|
+
Inherit from the base widget class
|
|
41
|
+
*/
|
|
42
|
+
var GraphWidget = exports.prototype = {};
|
|
43
|
+
|
|
44
|
+
GraphWidget.graphObjectType = "graph";
|
|
45
|
+
|
|
46
|
+
/*
|
|
47
|
+
Render this widget into the DOM
|
|
48
|
+
*/
|
|
49
|
+
GraphWidget.render = function(parent, nextSibling) {
|
|
50
|
+
this.parentDomNode = parent;
|
|
51
|
+
this.computeAttributes();
|
|
52
|
+
this.execute();
|
|
53
|
+
this.graphElement = this.document.createElement("div");
|
|
54
|
+
var className = "graph-canvas";
|
|
55
|
+
if (!this.graphEngine) {
|
|
56
|
+
className += " graph-error";
|
|
57
|
+
} else {
|
|
58
|
+
className += " graph-engine-" + this.graphEngineName.toLowerCase();
|
|
59
|
+
}
|
|
60
|
+
this.graphElement.className = className;
|
|
61
|
+
this.graphElement.addEventListener("mousemove", this);
|
|
62
|
+
this.domNodes.push(this.graphElement);
|
|
63
|
+
parent.insertBefore(this.graphElement, nextSibling);
|
|
64
|
+
this.renderChildren(this.graphElement, null);
|
|
65
|
+
|
|
66
|
+
this.computeParents();
|
|
67
|
+
// Render and recenter the view
|
|
68
|
+
if(this.graphEngine) {
|
|
69
|
+
this.graphEngine.onevent = GraphWidget.handleGraphEvent.bind(this);
|
|
70
|
+
var objects = this.findGraphObjects() || {};
|
|
71
|
+
this.properties = this.refreshProperties() || {};
|
|
72
|
+
objects.graph = this.typecastProperties(this.properties, "graph");
|
|
73
|
+
try {
|
|
74
|
+
this.graphEngine.init(this.graphElement, objects, {wiki: this.wiki});
|
|
75
|
+
} catch(e) {
|
|
76
|
+
// Technically, we should drop this engine without destroying it.
|
|
77
|
+
// It didn't successfully init, so it's not initialized.
|
|
78
|
+
// This means it's up to the engines to be "Strong Exception Safe".
|
|
79
|
+
this.graphEngine = undefined;
|
|
80
|
+
// Something went wrong. Rebuild this widget as an error displayer
|
|
81
|
+
console.error(e);
|
|
82
|
+
this.errorState = e.message || e.toString();
|
|
83
|
+
this.refreshSelf();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/*
|
|
89
|
+
Compute the internal state of the widget
|
|
90
|
+
*/
|
|
91
|
+
GraphWidget.execute = function() {
|
|
92
|
+
this.colorWidgets = {};
|
|
93
|
+
this.graphEngineName = this.getEngineName();
|
|
94
|
+
this.setVariable("graphengine", this.graphEngineName);
|
|
95
|
+
this.executeColors();
|
|
96
|
+
this.mouse = {x: "0", y: "0"};
|
|
97
|
+
var Engine = utils.getEngine(this.graphEngineName);
|
|
98
|
+
if (!Engine || this.errorState) {
|
|
99
|
+
var message;
|
|
100
|
+
if (this.errorState) {
|
|
101
|
+
message = this.errorState;
|
|
102
|
+
this.errorState = null;
|
|
103
|
+
} else if (!this.graphEngineName) {
|
|
104
|
+
message = "No graphing libraries installed.";
|
|
105
|
+
} else if (this.getAttribute("$engine")) {
|
|
106
|
+
message = "'" + this.graphEngineName + "' graphing library not found.";
|
|
107
|
+
} else {
|
|
108
|
+
message = "Graph plugin configured to use missing '" + this.graphEngineName + "' engine. Fix this in plugin settings.";
|
|
109
|
+
}
|
|
110
|
+
this.makeChildWidgets([{type: "element", tag: "span", children: [{type: "text", text: message}]}]);
|
|
111
|
+
this.graphEngine = undefined;
|
|
112
|
+
} else {
|
|
113
|
+
this.knownObjects = {};
|
|
114
|
+
this.makeChildWidgets();
|
|
115
|
+
this.graphEngine = new Engine(this.wiki);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
GraphWidget.executeColors = function() {
|
|
120
|
+
for (var color in graphColors) {
|
|
121
|
+
this.colorWidgets[color] = this.wiki.makeWidget({
|
|
122
|
+
tree: [{
|
|
123
|
+
type: "transclude",
|
|
124
|
+
attributes: {
|
|
125
|
+
"$variable": {type: "string", value: "colour"},
|
|
126
|
+
0: {type: "string", value: graphColors[color]}}
|
|
127
|
+
}]}, {parentWidget: this});
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
/*
|
|
132
|
+
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
|
133
|
+
*/
|
|
134
|
+
GraphWidget.refresh = function(changedTiddlers) {
|
|
135
|
+
var changedAttributes = this.computeAttributes(),
|
|
136
|
+
newName = this.getEngineName();
|
|
137
|
+
if(changedAttributes["$engine"] || (this.graphEngineName !== newName)) {
|
|
138
|
+
this.refreshSelf();
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
var changed = false;
|
|
142
|
+
var objects;
|
|
143
|
+
for (var attribute in changedAttributes) {
|
|
144
|
+
if (attribute.charAt(0) !== "$") {
|
|
145
|
+
changed = true;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (this.refreshChildren(changedTiddlers)) {
|
|
149
|
+
// Children have changed. Look for changed nodes and edges.
|
|
150
|
+
objects = this.findGraphObjects();
|
|
151
|
+
changed = true;
|
|
152
|
+
}
|
|
153
|
+
changed = this.computeParents() || changed;
|
|
154
|
+
if (changed || this.refreshColors(changedTiddlers)) {
|
|
155
|
+
var newGraphProperties = this.graphEngine? this.refreshProperties(): Object.create(null);
|
|
156
|
+
if (JSON.stringify(newGraphProperties) !== JSON.stringify(this.properties)) {
|
|
157
|
+
objects = objects || {};
|
|
158
|
+
this.properties = newGraphProperties;
|
|
159
|
+
objects.graph = this.typecastProperties(this.properties, "graph");
|
|
160
|
+
changed = true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (changed) {
|
|
164
|
+
if (!this.graphEngine) {
|
|
165
|
+
// We were in an error state. Maybe we won't be after refreshing.
|
|
166
|
+
this.refreshSelf();
|
|
167
|
+
} else if (objects) {
|
|
168
|
+
try {
|
|
169
|
+
this.graphEngine.update(objects);
|
|
170
|
+
} catch (e) {
|
|
171
|
+
// Something went wrong. Rebuild this widget as an error displayer
|
|
172
|
+
console.error(e);
|
|
173
|
+
this.errorState = e.message || e.toString();
|
|
174
|
+
this.refreshSelf();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return changed;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
GraphWidget.refreshSelf = function() {
|
|
182
|
+
var nextSibling = this.findNextSiblingDomNode();
|
|
183
|
+
this.removeChildDomNodes();
|
|
184
|
+
if (this.graphEngine) {
|
|
185
|
+
this.graphEngine.destroy();
|
|
186
|
+
}
|
|
187
|
+
this.render(this.parentDomNode, nextSibling);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
GraphWidget.refreshColors = function(changedTiddlers) {
|
|
191
|
+
var changed = false;
|
|
192
|
+
for (var color in graphColors) {
|
|
193
|
+
if (!this.colorWidgets[color].refresh(changedTiddlers)) {
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
changed = true;
|
|
197
|
+
}
|
|
198
|
+
return changed;
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
GraphWidget.garbageCollect = function() {
|
|
202
|
+
if (this.graphEngine) {
|
|
203
|
+
this.graphEngine.destroy();
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
GraphWidget.isGarbage = function() {
|
|
208
|
+
var body = this.document.body;
|
|
209
|
+
return !body || !body.contains(this.graphElement);
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
GraphWidget.getEngineName = function() {
|
|
213
|
+
return this.getAttribute("$engine") || this.getVariable("graphengine");
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
GraphWidget.getColor = function(color) {
|
|
217
|
+
var widget = this.colorWidgets[color];
|
|
218
|
+
var container = $tw.fakeDocument.createElement("div");
|
|
219
|
+
widget.render(container, null);
|
|
220
|
+
return container.textContent;
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
GraphWidget.setCustomProperties = function(properties) {
|
|
224
|
+
for (var name in graphColors) {
|
|
225
|
+
var color = this.getColor(name);
|
|
226
|
+
if (color) {
|
|
227
|
+
properties[name] = color;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* This overrides a graphobject method so we're looking inward instead of
|
|
234
|
+
* upward for properties that apply to this widget.
|
|
235
|
+
*/
|
|
236
|
+
GraphWidget.traversePropertyWidgets = function(method) {
|
|
237
|
+
var iterator = new utils.WidgetIterator(this);
|
|
238
|
+
var ptr = null;
|
|
239
|
+
var results;
|
|
240
|
+
while (!(results = iterator.next()).done) {
|
|
241
|
+
var widget = results.value;
|
|
242
|
+
if (widget.type === "graph") {
|
|
243
|
+
// We make a quick in place linked list
|
|
244
|
+
results.next = ptr;
|
|
245
|
+
ptr = results;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// Now we run through that list. This way, we apply the found properties
|
|
249
|
+
// in reverse, since the first found should be executed last as having
|
|
250
|
+
// lowest priority.
|
|
251
|
+
while (ptr !== null) {
|
|
252
|
+
method(ptr.value);
|
|
253
|
+
ptr = ptr.next;
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
GraphWidget.typecastProperties = function(properties, type) {
|
|
258
|
+
var engineDefinitions = this.graphEngine.properties;
|
|
259
|
+
var catalog = (engineDefinitions && engineDefinitions[type]) || {};
|
|
260
|
+
return this.typecastSet(properties, catalog);
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
GraphWidget.typecastSet = function(properties, catalog) {//type, key, value) {
|
|
264
|
+
var output = Object.create(null);
|
|
265
|
+
for (var key in properties) {
|
|
266
|
+
var info = catalog[key];
|
|
267
|
+
if (info && PropertyTypes[info.type]) {
|
|
268
|
+
var value = PropertyTypes[info.type].toProperty(info, properties[key], {widget: this});
|
|
269
|
+
if (value !== null) {
|
|
270
|
+
output[key] = value;
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
output[key] = properties[key];
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return output;
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
GraphWidget.findGraphObjects = function() {
|
|
280
|
+
var self = this;
|
|
281
|
+
var newObjects = {};
|
|
282
|
+
var iterator = new utils.WidgetIterator(this),
|
|
283
|
+
results;
|
|
284
|
+
while (!(results = iterator.next()).done) {
|
|
285
|
+
var widget = results.value;
|
|
286
|
+
var type = widget.graphObjectType;
|
|
287
|
+
if (type && type !== "graph") {
|
|
288
|
+
newObjects[type] = newObjects[type] || Object.create(null);
|
|
289
|
+
newObjects[type][widget.id] = widget;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
// Special handling for edge trimming
|
|
293
|
+
withholdObjects(newObjects);
|
|
294
|
+
var prevObjects = this.knownObjects;
|
|
295
|
+
this.knownObjects = newObjects;
|
|
296
|
+
return this.getDifferences(prevObjects, newObjects);
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
function withholdObjects(objects) {
|
|
300
|
+
// Blank nodes get filtered
|
|
301
|
+
if (objects.nodes) {
|
|
302
|
+
for (var id in objects.nodes) {
|
|
303
|
+
if (!id) {
|
|
304
|
+
objects.nodes[id] = undefined;
|
|
305
|
+
// This can only happen once
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
// Special handling for edge trimming
|
|
311
|
+
if (objects.edges) {
|
|
312
|
+
for (var id in objects.edges) {
|
|
313
|
+
var edge = objects.edges[id];
|
|
314
|
+
// This could probably be done above when deleting nulls
|
|
315
|
+
if (!objects.nodes
|
|
316
|
+
|| !objects.nodes[edge.fromTiddler]
|
|
317
|
+
|| !objects.nodes[edge.toTiddler]) {
|
|
318
|
+
// It must be trimmed
|
|
319
|
+
objects.edges[id] = undefined;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
GraphWidget.getDifferences = function(prevObjects, newObjects) {
|
|
326
|
+
var objects = null
|
|
327
|
+
for (var type in prevObjects) {
|
|
328
|
+
var was = prevObjects[type];
|
|
329
|
+
var is = newObjects[type];
|
|
330
|
+
for (var id in was) {
|
|
331
|
+
if (was[id]) {
|
|
332
|
+
if (!is || !is[id]) {
|
|
333
|
+
// It Was, and no longer Is. Flag for deletion
|
|
334
|
+
objects = objects || {};
|
|
335
|
+
objects[type] = objects[type] || Object.create(null);
|
|
336
|
+
objects[type][id] = null;
|
|
337
|
+
} else if (is[id].changed || is[id] !== was[id]) {
|
|
338
|
+
// It changed, or is another instance of the same ID.
|
|
339
|
+
// Updated it.
|
|
340
|
+
objects = objects || {};
|
|
341
|
+
objects[type] = objects[type] || Object.create(null);
|
|
342
|
+
objects[type][id] = this.typecastProperties(is[id].properties, type);
|
|
343
|
+
is[id].changed = false;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
for (var type in newObjects) {
|
|
349
|
+
var was = prevObjects? prevObjects[type]: undefined;
|
|
350
|
+
var is = newObjects[type];
|
|
351
|
+
for (var id in is) {
|
|
352
|
+
if (is[id] && (!was || !was[id])) {
|
|
353
|
+
// It has been added. Add it.
|
|
354
|
+
objects = objects || {};
|
|
355
|
+
objects[type] = objects[type] || Object.create(null);
|
|
356
|
+
objects[type][id] = this.typecastProperties(is[id].properties, type);
|
|
357
|
+
is[id].changed = false;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return objects;
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* This handles messages bubbling up from internal graph widgets
|
|
366
|
+
*/
|
|
367
|
+
GraphWidget.dispatchEvent = function(event) {
|
|
368
|
+
var messageDef = this.graphEngine.messages && this.graphEngine.messages[event.type];
|
|
369
|
+
if (messageDef) {
|
|
370
|
+
var params = this.typecastSet(event.paramObject, messageDef);
|
|
371
|
+
if (this.graphEngine.handleMessage(event, params) === false) {
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
if (this.parentWidget) {
|
|
376
|
+
return this.parentWidget.dispatchEvent(event);
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
GraphWidget.handleGraphEvent = function(graphEvent, variables) {
|
|
381
|
+
if (graphEvent.objectType === "graph") {
|
|
382
|
+
var iterator = new utils.WidgetIterator(this);
|
|
383
|
+
var results;
|
|
384
|
+
while (!(results = iterator.next()).done) {
|
|
385
|
+
var widget = results.value;
|
|
386
|
+
if (widget.type === "graph") {
|
|
387
|
+
var actions = widget.properties[graphEvent.type];
|
|
388
|
+
if (actions) {
|
|
389
|
+
widget.invokeActionString(actions, widget, graphEvent.event, variables);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
this.catchGraphEvent(graphEvent, this, variables);
|
|
394
|
+
} else {
|
|
395
|
+
var category = this.knownObjects[graphEvent.objectType];
|
|
396
|
+
var object = category && category[graphEvent.id];
|
|
397
|
+
if (object) {
|
|
398
|
+
variables = variables || {};
|
|
399
|
+
// We let the graph object assign some state, such as the id of the
|
|
400
|
+
// targeted node, or the nodes of the targeted edge.
|
|
401
|
+
var module = GraphObjectTypes[object.graphObjectType];
|
|
402
|
+
if (module) {
|
|
403
|
+
$tw.utils.each(module.actionContext, function(name) {
|
|
404
|
+
variables[name] = object[name];
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
// Make sure it's an objects we actually know about
|
|
408
|
+
var target = object;
|
|
409
|
+
while (object && object !== this) {
|
|
410
|
+
if (object.catchGraphEvent) {
|
|
411
|
+
// Start at the object. Go up, finding $style to handle this
|
|
412
|
+
object.catchGraphEvent(graphEvent, target, variables);
|
|
413
|
+
}
|
|
414
|
+
object = object.parentWidget;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
GraphWidget.handleEvent = function(event) {
|
|
421
|
+
// Must be a mousemove, because that's the only one we signed up for.
|
|
422
|
+
this.mouse.x = event.offsetX;
|
|
423
|
+
this.mouse.y = event.offsetY;
|
|
424
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/*\
|
|
2
|
+
|
|
3
|
+
Widget for creating nodes within graphs.
|
|
4
|
+
|
|
5
|
+
\*/
|
|
6
|
+
|
|
7
|
+
"use strict";
|
|
8
|
+
|
|
9
|
+
var axes = ['x', 'y', 'z', 'w'];
|
|
10
|
+
|
|
11
|
+
exports.baseClass = "graphobject";
|
|
12
|
+
exports.name = "node";
|
|
13
|
+
// These are object properties that will get added to the variable context
|
|
14
|
+
// when action strings are invoked.
|
|
15
|
+
exports.actionContext = ["nodeTiddler"];
|
|
16
|
+
|
|
17
|
+
exports.constructor = function(parseTreeNode, options) {
|
|
18
|
+
this.initialise(parseTreeNode, options);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
var NodeWidget = exports.prototype = {};
|
|
22
|
+
|
|
23
|
+
NodeWidget.graphObjectType = "nodes";
|
|
24
|
+
|
|
25
|
+
NodeWidget.execute = function() {
|
|
26
|
+
this.id = this.getAttribute("$tiddler", this.getVariable("currentTiddler"));
|
|
27
|
+
// We set this for the actionContext, which gets automatically scraped
|
|
28
|
+
// when actions for this object get executed.
|
|
29
|
+
this.nodeTiddler = this.id;
|
|
30
|
+
this.pos = this.getAttribute("$pos");
|
|
31
|
+
this.makeChildWidgets();
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
NodeWidget.setCustomProperties = function(properties) {
|
|
35
|
+
if (this.pos) {
|
|
36
|
+
var points = this.pos.split(",");
|
|
37
|
+
var count = Math.min(points.length, axes.length);
|
|
38
|
+
for (var i = 0; i < count; i++) {
|
|
39
|
+
if (points[i]) {
|
|
40
|
+
properties[axes[i]] = points[i];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"directories": [
|
|
3
|
+
{
|
|
4
|
+
"path": ".",
|
|
5
|
+
"filesRegExp": "^.*\\.js$",
|
|
6
|
+
"isTiddlerFile": true,
|
|
7
|
+
"fields": {
|
|
8
|
+
"title": {
|
|
9
|
+
"source": "filename",
|
|
10
|
+
"prefix": "$:/plugins/flibbles/graph/widgets/"
|
|
11
|
+
},
|
|
12
|
+
"type": "application/javascript",
|
|
13
|
+
"module-type": "widget"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"path": "./subclass",
|
|
18
|
+
"filesRegExp": "^.*\\.js$",
|
|
19
|
+
"isTiddlerFile": true,
|
|
20
|
+
"fields": {
|
|
21
|
+
"title": {
|
|
22
|
+
"source": "filename",
|
|
23
|
+
"prefix": "$:/plugins/flibbles/graph/widgets/subclass/"
|
|
24
|
+
},
|
|
25
|
+
"type": "application/javascript",
|
|
26
|
+
"module-type": "widget-subclass"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"path": "./fieldtranscriber",
|
|
31
|
+
"filesRegExp": "^.*\\.js$",
|
|
32
|
+
"isTiddlerFile": true,
|
|
33
|
+
"fields": {
|
|
34
|
+
"title": {
|
|
35
|
+
"source": "filename",
|
|
36
|
+
"prefix": "$:/plugins/flibbles/graph/widgets/fieldtranscriber/"
|
|
37
|
+
},
|
|
38
|
+
"type": "application/javascript",
|
|
39
|
+
"module-type": "fieldtranscribertype"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
}
|