tw5-graph 1.7.1
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 +54 -0
- package/plugins/graph/macros/properties.stack.tid +17 -0
- package/plugins/graph/macros/tiddlywiki.files +17 -0
- package/plugins/graph/nodes/neighbors/1.tid +8 -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/neighbors.tid +4 -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/color.js +61 -0
- package/plugins/graph/propertytypes/enum.js +25 -0
- package/plugins/graph/propertytypes/filter.js +44 -0
- package/plugins/graph/propertytypes/image.js +185 -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 +272 -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 +48 -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 +16 -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 +46 -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/propertyholder.js +80 -0
- package/plugins/graph/utils/widgetiterator.js +47 -0
- package/plugins/graph/utils.js +95 -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/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/fieldtranscriber.js +98 -0
- package/plugins/graph/widgets/graphobject.js +154 -0
- package/plugins/graph/widgets/messagerelay.js +115 -0
- package/plugins/graph/widgets/properties.js +130 -0
- package/plugins/graph/widgets/subclass/edge.js +55 -0
- package/plugins/graph/widgets/subclass/edit-color.js +52 -0
- package/plugins/graph/widgets/subclass/graph.js +380 -0
- package/plugins/graph/widgets/subclass/node.js +56 -0
- package/plugins/graph/widgets/tiddlywiki.files +43 -0
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
/*\
|
|
2
|
+
|
|
3
|
+
Widget for creating graphs.
|
|
4
|
+
|
|
5
|
+
\*/
|
|
6
|
+
|
|
7
|
+
"use strict";
|
|
8
|
+
|
|
9
|
+
var utils = require("../../utils.js");
|
|
10
|
+
|
|
11
|
+
// Let's collect all the possible graph object types. We might need to
|
|
12
|
+
// reference their base classes later.
|
|
13
|
+
var GraphObjectTypes = {};
|
|
14
|
+
$tw.modules.forEachModuleOfType("widget-subclass", function(title, module) {
|
|
15
|
+
if (module.baseClass == "graphobject") {
|
|
16
|
+
module.graphObjectType = module.prototype.graphObjectType;
|
|
17
|
+
GraphObjectTypes[module.graphObjectType] = module;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
exports.baseClass = "graphobject";
|
|
22
|
+
exports.name = "graph";
|
|
23
|
+
|
|
24
|
+
exports.constructor = function(parseTreeNode, options) {
|
|
25
|
+
this.initialise(parseTreeNode, options);
|
|
26
|
+
utils.registerForGarbageCollection(this);
|
|
27
|
+
this.window = utils.window();
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
Inherit from the base widget class
|
|
32
|
+
*/
|
|
33
|
+
var GraphWidget = exports.prototype = {};
|
|
34
|
+
|
|
35
|
+
GraphWidget.graphObjectType = "graph";
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
Render this widget into the DOM
|
|
39
|
+
*/
|
|
40
|
+
GraphWidget.render = function(parent, nextSibling) {
|
|
41
|
+
this.parentDomNode = parent;
|
|
42
|
+
this.computeAttributes();
|
|
43
|
+
this.execute();
|
|
44
|
+
this.graphElement = this.document.createElement("div");
|
|
45
|
+
var className = "graph-canvas";
|
|
46
|
+
if (!this.graphEngine) {
|
|
47
|
+
className += " graph-error";
|
|
48
|
+
} else {
|
|
49
|
+
className += " graph-engine-" + this.graphEngineName.toLowerCase();
|
|
50
|
+
}
|
|
51
|
+
this.graphElement.className = className;
|
|
52
|
+
this.graphElement.addEventListener("mousemove", this);
|
|
53
|
+
this.domNodes.push(this.graphElement);
|
|
54
|
+
parent.insertBefore(this.graphElement, nextSibling);
|
|
55
|
+
this.renderChildren(this.graphElement, null);
|
|
56
|
+
|
|
57
|
+
this.computeParents();
|
|
58
|
+
// Render and recenter the view
|
|
59
|
+
if(this.graphEngine) {
|
|
60
|
+
this.graphEngine.onevent = GraphWidget.handleGraphEvent.bind(this);
|
|
61
|
+
var objects = this.computeGraphObjects() || {};
|
|
62
|
+
objects.graph = this.calculatePropertyValues(getCatalog(this.graphEngine, "graph"));
|
|
63
|
+
try {
|
|
64
|
+
this.graphEngine.init(this.graphElement, objects, {wiki: this.wiki});
|
|
65
|
+
} catch(e) {
|
|
66
|
+
// Technically, we should drop this engine without destroying it.
|
|
67
|
+
// It didn't successfully init, so it's not initialized.
|
|
68
|
+
// This means it's up to the engines to be "Strong Exception Safe".
|
|
69
|
+
this.graphEngine = undefined;
|
|
70
|
+
// Something went wrong. Rebuild this widget as an error displayer
|
|
71
|
+
console.error(e);
|
|
72
|
+
this.errorState = e.message || e.toString();
|
|
73
|
+
this.refreshSelf();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/*
|
|
79
|
+
Compute the internal state of the widget
|
|
80
|
+
*/
|
|
81
|
+
GraphWidget.execute = function() {
|
|
82
|
+
this.graphEngineName = this.getEngineName();
|
|
83
|
+
this.setVariable("graphengine", this.graphEngineName);
|
|
84
|
+
this.mouse = {x: "0", y: "0"};
|
|
85
|
+
var Engine = utils.getEngine(this.graphEngineName);
|
|
86
|
+
if (!Engine || this.errorState) {
|
|
87
|
+
var message;
|
|
88
|
+
if (this.errorState) {
|
|
89
|
+
message = this.errorState;
|
|
90
|
+
this.errorState = null;
|
|
91
|
+
} else if (!this.graphEngineName) {
|
|
92
|
+
message = "No graphing libraries installed.";
|
|
93
|
+
} else if (this.getAttribute("$engine")) {
|
|
94
|
+
message = "'" + this.graphEngineName + "' graphing library not found.";
|
|
95
|
+
} else {
|
|
96
|
+
message = "Graph plugin configured to use missing '" + this.graphEngineName + "' engine. Fix this in plugin settings.";
|
|
97
|
+
}
|
|
98
|
+
this.makeChildWidgets([{type: "element", tag: "span", children: [{type: "text", text: message}]}]);
|
|
99
|
+
this.graphEngine = undefined;
|
|
100
|
+
} else {
|
|
101
|
+
this.graphObjects = null;
|
|
102
|
+
this.makeChildWidgets();
|
|
103
|
+
this.graphEngine = new Engine(this.wiki);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/*
|
|
108
|
+
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
|
109
|
+
*/
|
|
110
|
+
GraphWidget.refresh = function(changedTiddlers) {
|
|
111
|
+
var changedAttributes = this.computeAttributes(),
|
|
112
|
+
newName = this.getEngineName();
|
|
113
|
+
if(changedAttributes["$engine"] || (this.graphEngineName !== newName)) {
|
|
114
|
+
this.refreshSelf();
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
var selfChanged = false, childrenChanged = false;
|
|
118
|
+
var objects;
|
|
119
|
+
for (var attribute in changedAttributes) {
|
|
120
|
+
if (attribute.charAt(0) !== "$") {
|
|
121
|
+
selfChanged = true;
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (this.refreshChildren(changedTiddlers)) {
|
|
126
|
+
childrenChanged = true;
|
|
127
|
+
}
|
|
128
|
+
if (!this.graphEngine && (selfChanged || childrenChanged)) {
|
|
129
|
+
// At this point, we know widgets have literally changed.
|
|
130
|
+
// If we're in an error state, we can refresh self now, because
|
|
131
|
+
// all properties would have to be regenerated anyway.
|
|
132
|
+
this.refreshSelf();
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
// From here on, we now try to narrow down which properties changed,
|
|
136
|
+
// because we can update instead of full refresh. Updates only bother
|
|
137
|
+
// with changed properties.
|
|
138
|
+
if (childrenChanged) {
|
|
139
|
+
// Children have changed. Look for changed nodes and edges
|
|
140
|
+
// and evaluate their properties
|
|
141
|
+
objects = this.computeGraphObjects();
|
|
142
|
+
}
|
|
143
|
+
selfChanged = this.computeParents() || selfChanged;
|
|
144
|
+
if (selfChanged || this.refreshProperties(changedTiddlers)) {
|
|
145
|
+
var rules = getCatalog(this.graphEngine, "graph");
|
|
146
|
+
var newTypecastProperties = this.calculatePropertyValues(rules);
|
|
147
|
+
objects = objects || {};
|
|
148
|
+
objects.graph = newTypecastProperties;
|
|
149
|
+
}
|
|
150
|
+
if (objects) {
|
|
151
|
+
try {
|
|
152
|
+
this.graphEngine.update(objects);
|
|
153
|
+
} catch (e) {
|
|
154
|
+
// Something went wrong. Rebuild this widget as an error displayer
|
|
155
|
+
console.error(e);
|
|
156
|
+
this.errorState = e.message || e.toString();
|
|
157
|
+
this.refreshSelf();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return selfChanged || childrenChanged;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
GraphWidget.refreshSelf = function() {
|
|
164
|
+
var nextSibling = this.findNextSiblingDomNode();
|
|
165
|
+
this.removeChildDomNodes();
|
|
166
|
+
if (this.graphEngine) {
|
|
167
|
+
this.graphEngine.destroy();
|
|
168
|
+
}
|
|
169
|
+
this.render(this.parentDomNode, nextSibling);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
GraphWidget.garbageCollect = function() {
|
|
173
|
+
if (this.graphEngine) {
|
|
174
|
+
this.graphEngine.destroy();
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
GraphWidget.isGarbage = function() {
|
|
179
|
+
var body = this.document.body;
|
|
180
|
+
return !body || !body.contains(this.graphElement);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
GraphWidget.getEngineName = function() {
|
|
184
|
+
return this.getAttribute("$engine") || this.getVariable("graphengine");
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* This overrides a graphobject method so we're looking inward instead of
|
|
189
|
+
* upward for properties that apply to this widget.
|
|
190
|
+
*/
|
|
191
|
+
GraphWidget.traversePropertyWidgets = function(method) {
|
|
192
|
+
var iterator = new utils.WidgetIterator(this);
|
|
193
|
+
var ptr = null;
|
|
194
|
+
var results;
|
|
195
|
+
while (!(results = iterator.next()).done) {
|
|
196
|
+
var widget = results.value;
|
|
197
|
+
if (widget.type === "graph") {
|
|
198
|
+
// We make a quick in place linked list
|
|
199
|
+
results.next = ptr;
|
|
200
|
+
ptr = results;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Now we run through that list. This way, we apply the found properties
|
|
204
|
+
// in reverse, since the first found should be executed last as having
|
|
205
|
+
// lowest priority.
|
|
206
|
+
while (ptr !== null) {
|
|
207
|
+
method(ptr.value);
|
|
208
|
+
ptr = ptr.next;
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* This handles messages bubbling up from internal graph widgets
|
|
214
|
+
*/
|
|
215
|
+
GraphWidget.dispatchEvent = function(event) {
|
|
216
|
+
var messageDef = this.graphEngine.messages && this.graphEngine.messages[event.type];
|
|
217
|
+
if (messageDef) {
|
|
218
|
+
// We create a propertyHolder out of the widget.
|
|
219
|
+
var message = Object.assign(Object.create(event.widget), utils.PropertyHolder);
|
|
220
|
+
var params = message.evaluateProperties(event.paramObject, messageDef);
|
|
221
|
+
if (this.graphEngine.handleMessage(event, params) === false) {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (this.parentWidget) {
|
|
226
|
+
return this.parentWidget.dispatchEvent(event);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
GraphWidget.handleGraphEvent = function(graphEvent, variables) {
|
|
231
|
+
if (graphEvent.objectType === "graph") {
|
|
232
|
+
var iterator = new utils.WidgetIterator(this);
|
|
233
|
+
var results;
|
|
234
|
+
while (!(results = iterator.next()).done) {
|
|
235
|
+
var widget = results.value;
|
|
236
|
+
if (widget.type === "graph") {
|
|
237
|
+
var actions = widget.properties[graphEvent.type];
|
|
238
|
+
if (actions) {
|
|
239
|
+
widget.invokeActionString(actions, widget, graphEvent.event, variables);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
this.catchGraphEvent(graphEvent, this, variables);
|
|
244
|
+
} else {
|
|
245
|
+
var category = this.graphObjects[graphEvent.objectType];
|
|
246
|
+
var object = category && category[graphEvent.id];
|
|
247
|
+
if (object) {
|
|
248
|
+
variables = variables || {};
|
|
249
|
+
// We let the graph object assign some state,such as the id of the
|
|
250
|
+
// targeted node, or the nodes of the targeted edge.
|
|
251
|
+
var module = GraphObjectTypes[object.graphObjectType];
|
|
252
|
+
if (module) {
|
|
253
|
+
$tw.utils.each(module.actionContext, function(name) {
|
|
254
|
+
variables[name] = object[name];
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
// Make sure it's an objects we actually know about
|
|
258
|
+
var target = object;
|
|
259
|
+
while (object && object !== this) {
|
|
260
|
+
if (object.catchGraphEvent) {
|
|
261
|
+
// Start at the object. Go up, finding $style to handle this
|
|
262
|
+
object.catchGraphEvent(graphEvent, target, variables);
|
|
263
|
+
}
|
|
264
|
+
object = object.parentWidget;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
GraphWidget.handleEvent = function(event) {
|
|
271
|
+
// Must be a mousemove, because that's the only one we signed up for.
|
|
272
|
+
// All we do is remember the mouse position if we need it later for
|
|
273
|
+
// graph events.
|
|
274
|
+
this.mouse.x = event.offsetX;
|
|
275
|
+
this.mouse.y = event.offsetY;
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
GraphWidget.computeGraphObjects = function() {
|
|
279
|
+
var prevObjects = this.graphObjects || {},
|
|
280
|
+
widgetInfo = findGraphObjects(this),
|
|
281
|
+
newObjects = widgetInfo.objects,
|
|
282
|
+
order = widgetInfo.order;
|
|
283
|
+
// Prune any objects which shouldn't be passed along
|
|
284
|
+
curateObjects(newObjects, order, this.graphEngine.properties);
|
|
285
|
+
var evaluated = getDifferences(this.graphEngine, prevObjects, newObjects);
|
|
286
|
+
this.graphObjects = newObjects;
|
|
287
|
+
return evaluated;
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
function getCatalog(graphEngine, type) {
|
|
291
|
+
var definitions = graphEngine.properties;
|
|
292
|
+
return (definitions && definitions[type]) || Object.create(null);
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
function findGraphObjects(graphWidget) {
|
|
296
|
+
var newObjects = {};
|
|
297
|
+
var discoveryOrder = {};
|
|
298
|
+
var iterator = new utils.WidgetIterator(graphWidget),
|
|
299
|
+
results;
|
|
300
|
+
while (!(results = iterator.next()).done) {
|
|
301
|
+
var widget = results.value;
|
|
302
|
+
var type = widget.graphObjectType;
|
|
303
|
+
if (type && type !== "graph") {
|
|
304
|
+
newObjects[type] = newObjects[type] || Object.create(null);
|
|
305
|
+
newObjects[type][widget.id] = widget;
|
|
306
|
+
// We've got to recall the order that we found the widgets in
|
|
307
|
+
// storing them in objects doesn't work, because that sorts oddly
|
|
308
|
+
discoveryOrder[type] = discoveryOrder[type] || new $tw.utils.LinkedList();
|
|
309
|
+
discoveryOrder[type].pushTop(widget.id);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
for (var type in discoveryOrder) {
|
|
313
|
+
discoveryOrder[type] = discoveryOrder[type].toArray();
|
|
314
|
+
}
|
|
315
|
+
return {objects: newObjects, order: discoveryOrder};
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Checking for objects that should be pruned must take place after all
|
|
320
|
+
* objects have been collected. Some object types, like edge, need to know
|
|
321
|
+
* what other objects are present to know if they're valid or not.
|
|
322
|
+
*/
|
|
323
|
+
function curateObjects(objects, orders, catalog) {
|
|
324
|
+
for (var groupName in objects) {
|
|
325
|
+
var type = GraphObjectTypes[groupName];
|
|
326
|
+
if (type && type.graphObjectType !== "graph") {
|
|
327
|
+
var group = objects[groupName];
|
|
328
|
+
var order = orders[groupName];
|
|
329
|
+
var rules = catalog[type.graphObjectType];
|
|
330
|
+
var index = 0;
|
|
331
|
+
for (var i = 0; i < order.length; i++) {
|
|
332
|
+
var id = order[i];
|
|
333
|
+
if (group[id].curate(objects, rules, index)) {
|
|
334
|
+
group[id] = undefined;
|
|
335
|
+
} else {
|
|
336
|
+
++index;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
function getDifferences(graphEngine, prevObjects, newObjects) {
|
|
344
|
+
var objects = null
|
|
345
|
+
for (var type in prevObjects) {
|
|
346
|
+
var was = prevObjects[type];
|
|
347
|
+
var is = newObjects[type];
|
|
348
|
+
var catalog = getCatalog(graphEngine, type);
|
|
349
|
+
for (var id in was) {
|
|
350
|
+
if (was[id]) {
|
|
351
|
+
if (!is || !is[id]) {
|
|
352
|
+
// It Was, and no longer Is. Flag for deletion
|
|
353
|
+
objects = objects || {};
|
|
354
|
+
objects[type] = objects[type] || Object.create(null);
|
|
355
|
+
objects[type][id] = null;
|
|
356
|
+
} else if (!is[id].properties || is[id] !== was[id]) {
|
|
357
|
+
// It changed, or is another instance of the same ID.
|
|
358
|
+
// Updated it.
|
|
359
|
+
objects = objects || {};
|
|
360
|
+
objects[type] = objects[type] || Object.create(null);
|
|
361
|
+
objects[type][id] = is[id].calculatePropertyValues(catalog);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
for (var type in newObjects) {
|
|
367
|
+
var was = prevObjects? prevObjects[type]: undefined;
|
|
368
|
+
var is = newObjects[type];
|
|
369
|
+
var catalog = getCatalog(graphEngine, type);
|
|
370
|
+
for (var id in is) {
|
|
371
|
+
if (is[id] && (!was || !was[id])) {
|
|
372
|
+
// It has been added. Add it.
|
|
373
|
+
objects = objects || {};
|
|
374
|
+
objects[type] = objects[type] || Object.create(null);
|
|
375
|
+
objects[type][id] = is[id].calculatePropertyValues(catalog);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return objects;
|
|
380
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
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.curate = function(objects, rules, index) {
|
|
35
|
+
if (rules.index && this.index !== index) {
|
|
36
|
+
this.index = index;
|
|
37
|
+
this.properties = null;
|
|
38
|
+
}
|
|
39
|
+
// Nodes must have non-empty IDs. If empty, this node should be pruned.
|
|
40
|
+
return !this.id;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
NodeWidget.setCustomProperties = function(properties, rules) {
|
|
44
|
+
if (this.pos) {
|
|
45
|
+
var points = this.pos.split(",");
|
|
46
|
+
var count = Math.min(points.length, axes.length);
|
|
47
|
+
for (var i = 0; i < count; i++) {
|
|
48
|
+
if (points[i]) {
|
|
49
|
+
properties[axes[i]] = points[i];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (this.index !== undefined) {
|
|
54
|
+
properties.index = this.index;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
@@ -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
|
+
}
|