78 lines
2.5 KiB
JavaScript
78 lines
2.5 KiB
JavaScript
// select.js — which nodes and edges are selected.
|
|
//
|
|
// Kept apart from the document so selection never lands in the undo stack or
|
|
// on disk: undoing an edit should restore geometry, not re-select whatever
|
|
// happened to be highlighted at the time.
|
|
window.Canvas = window.Canvas || {};
|
|
|
|
Canvas.Select = (function () {
|
|
var nodes = {};
|
|
var edges = {};
|
|
var listeners = [];
|
|
|
|
function emit() {
|
|
for (var i = 0; i < listeners.length; i++) listeners[i]();
|
|
}
|
|
|
|
function keys(obj) { return Object.keys(obj); }
|
|
|
|
return {
|
|
nodes: function () { return keys(nodes); },
|
|
edges: function () { return keys(edges); },
|
|
hasNode: function (id) { return !!nodes[id]; },
|
|
hasEdge: function (id) { return !!edges[id]; },
|
|
isEmpty: function () { return !keys(nodes).length && !keys(edges).length; },
|
|
count: function () { return keys(nodes).length + keys(edges).length; },
|
|
|
|
set: function (nodeIds, edgeIds) {
|
|
nodes = {};
|
|
edges = {};
|
|
(nodeIds || []).forEach(function (id) { nodes[id] = true; });
|
|
(edgeIds || []).forEach(function (id) { edges[id] = true; });
|
|
emit();
|
|
},
|
|
|
|
addNode: function (id) {
|
|
if (nodes[id]) return;
|
|
nodes[id] = true;
|
|
emit();
|
|
},
|
|
|
|
toggleNode: function (id) {
|
|
if (nodes[id]) delete nodes[id]; else nodes[id] = true;
|
|
emit();
|
|
},
|
|
|
|
toggleEdge: function (id) {
|
|
if (edges[id]) delete edges[id]; else edges[id] = true;
|
|
emit();
|
|
},
|
|
|
|
clear: function () {
|
|
if (!keys(nodes).length && !keys(edges).length) return;
|
|
nodes = {};
|
|
edges = {};
|
|
emit();
|
|
},
|
|
|
|
// prune drops ids that no longer exist. Called after undo/redo, where
|
|
// the document can lose nodes the selection still refers to.
|
|
prune: function (doc) {
|
|
var changed = false;
|
|
var live = {};
|
|
doc.nodes.forEach(function (n) { live[n.id] = true; });
|
|
keys(nodes).forEach(function (id) {
|
|
if (!live[id]) { delete nodes[id]; changed = true; }
|
|
});
|
|
var liveEdges = {};
|
|
doc.edges.forEach(function (e) { liveEdges[e.id] = true; });
|
|
keys(edges).forEach(function (id) {
|
|
if (!liveEdges[id]) { delete edges[id]; changed = true; }
|
|
});
|
|
if (changed) emit();
|
|
},
|
|
|
|
onChange: function (fn) { listeners.push(fn); }
|
|
};
|
|
})();
|