/**
* Replay plugin. To record steps in the Editor, click on Extras, Record.
* To stop recording click Extras, Record again. Enter the delay between
* the steps and use the URL that opens in the new window.
*/
Draw.loadPlugin(function(ui) {
var graph = ui.editor.graph;
var model = graph.model;
function decodeChanges(delta, direct)
{
var codec2 = new mxCodec(delta.ownerDocument);
codec2.lookup = function(id)
{
return model.getCell(id);
};
var changeNode = (direct) ? delta.firstChild : delta.firstChild.firstChild;
var changes = [];
while (changeNode != null)
{
var change = codec2.decode(changeNode);
change.model = model;
change.execute();
changes.push(change);
changeNode = changeNode.nextSibling;
}
return changes;
};
function createUndoableEdit(changes)
{
var edit = new mxUndoableEdit(model);
edit.changes = changes;
edit.notify = function()
{
// LATER: Remove changes property (deprecated)
edit.source.fireEvent(new mxEventObject(mxEvent.CHANGE,
'edit', edit, 'changes', edit.changes));
edit.source.fireEvent(new mxEventObject(mxEvent.NOTIFY,
'edit', edit, 'changes', edit.changes));
};
return edit;
};
function processDelta(delta, direct)
{
var changes = decodeChanges(delta, direct);
if (changes.length > 0)
{
var edit = createUndoableEdit(changes);
if (ui.chromelessResize)
{
// No notify event here to avoid the edit from being encoded and transmitted
// LATER: Remove changes property (deprecated)
model.fireEvent(new mxEventObject(mxEvent.CHANGE,
'edit', edit, 'changes', changes));
model.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', edit));
ui.chromelessResize();
}
else
{
edit.notify();
}
}
return edit;
};
if (ui.editor.isChromelessView())
{
var replayData = urlParams['replay-data'];
var delay = parseInt(urlParams['delay-delay'] || 1000);
if (replayData != null)
{
var xmlDoc = mxUtils.parseXml(Graph.decompress(replayData));
// LATER: Avoid duplicate parsing
ui.fileLoaded(new LocalFile(ui, mxUtils.getXml(xmlDoc.documentElement.firstChild.firstChild)));
// Process deltas
var delta = xmlDoc.documentElement.firstChild.nextSibling;
function nextStep()
{
if (delta != null)
{
window.setTimeout(function()
{
processDelta(delta);
delta = delta.nextSibling;
nextStep();
}, delay);
}
};
nextStep();
}
}
else
{
var tape = null;
var codec = new mxCodec();
codec.lookup = function(id)
{
return model.getCell(id);
};
model.addListener(mxEvent.CHANGE, function(sender, evt)
{
if (tape != null)
{
var changes = evt.getProperty('changes');
var node = codec.encode(changes);
var delta = codec.document.createElement('delta');
delta.appendChild(node);
tape.push(mxUtils.getXml(delta));
}
});
mxResources.parse('record=Record');
mxResources.parse('replay=Replay');
// Adds actions
var action = ui.actions.addAction('record...', function()
{
if (tape == null)
{
var node = codec.encode(model);
var state = codec.document.createElement('state');
state.appendChild(node);
tape =[mxUtils.getXml(state)];
ui.editor.setStatus('Recording started');
}
else if (tape != null)
{
ui.editor.setStatus('Recording stopped');
var tmp = tape;
tape = null;
var dlg = new FilenameDialog(ui, 1000, mxResources.get('apply'), function(newValue)
{
if (newValue != null)
{
var dlg = new EmbedDialog(ui, 'https://www.draw.io/?p=replay&lightbox=1&replay-delay=' +
parseFloat(newValue) + '&replay-data=' + Graph.compress('' +
tmp.join('') + ''));
ui.showDialog(dlg.container, 450, 240, true, true);
dlg.init();
}
}, 'Delay');
ui.showDialog(dlg.container, 300, 80, true, true);
dlg.init();
}
action.label = (tape != null) ? 'Stop recording' : mxResources.get('record') + '...';
});
ui.actions.addAction('replay...', function()
{
var dlg = new TextareaDialog(ui, 'Changes [JSON export, compressed edits or ..]:', '',
function(newValue)
{
if (newValue.length > 0)
{
try
{
var current = null;
if (newValue.charAt(0) == '{')
{
var temp = JSON.parse(newValue);
current = temp.current;
newValue = temp.edits;
}
if (newValue.charAt(0) != '<')
{
newValue = Graph.decompress(newValue);
}
if (newValue.charAt(0) == '[')
{
newValue = JSON.parse(newValue);
console.log(JSON.stringify(newValue, null, 2));
var pageId = null;
var temp = [];
for (var i = 0; i < newValue.length; i++)
{
if (pageId == null)
{
pageId = newValue[i].pageid;
}
if (pageId == newValue[i].pageid)
{
temp.push(newValue[i].data);
}
else
{
mxLog.debug('edit ignored for page ' + newValue[i].pageid);
mxLog.show();
}
}
newValue = temp.join('');
}
var edits = mxUtils.parseXml('' + newValue + '');
var edit = edits.documentElement.firstChild;
function step()
{
console.log(processDelta(edit, true));
edit = edit.nextSibling;
return edit != null;
}
if (ui.buttonContainer != null)
{
console.log(mxUtils.getPrettyXml(edit));
var button = mxUtils.button('Step', function()
{
if (!step())
{
button.parentNode.removeChild(button);
}
else
{
console.log(mxUtils.getPrettyXml(edit));
}
});
button.className = 'geBtn gePrimaryBtn';
ui.buttonContainer.appendChild(button);
}
else
{
while (step())
{
// repeat
}
}
}
catch (e)
{
ui.handleError(e);
console.error(e);
}
}
});
ui.showDialog(dlg.container, 620, 460, true, true);
dlg.init();
});
var menu = ui.menus.get('extras');
var oldFunct = menu.funct;
menu.funct = function(menu, parent)
{
oldFunct.apply(this, arguments);
ui.menus.addMenuItems(menu, ['-', 'record', 'replay'], parent);
};
}
});