doNclEditingCommand method
void
doNclEditingCommand( - NclDocument doc,
- String command
)
Implementation
void doNclEditingCommand(NclDocument doc, String command) {
final parsed = _parseCommand(command);
if (parsed == null) return;
Element? parseXml(String xmlStr) {
try {
final root = XmlDocument.parse(xmlStr).rootElement;
return _parseNode(root);
} catch (e) {
return null;
}
}
Element? findElementInHead(bool Function(Element) predicate) {
final head = doc.head;
if (head == null) return null;
Element? search(Element el) {
if (predicate(el)) return el;
for (var child in el.children) {
final res = search(child);
if (res != null) return res;
}
return null;
}
for (var el in head) {
final res = search(el);
if (res != null) return res;
}
return null;
}
bool removeElementFromHead(String id) {
final head = doc.head;
if (head == null) return false;
bool searchAndRemove(Element parent, Element el) {
if (el.id == id) {
parent.children.remove(el);
return true;
}
for (var child in List<Element>.from(el.children)) {
if (searchAndRemove(el, child)) return true;
}
return false;
}
for (var el in List<Element>.from(head)) {
if (el.id == id) {
head.remove(el);
return true;
}
for (var child in List<Element>.from(el.children)) {
if (searchAndRemove(el, child)) return true;
}
}
return false;
}
switch (parsed.name) {
case 'addRegionBase':
if (parsed.args.isEmpty) return;
final el = parseXml(parsed.args[0]);
if (el != null) {
doc.head?.add(el);
}
break;
case 'removeRegionBase':
if (parsed.args.isEmpty) return;
removeElementFromHead(parsed.args[0]);
break;
case 'addRegion':
if (parsed.args.length < 3) return;
final regionBaseId = parsed.args[0];
final regionId = parsed.args[1];
final xmlRegion = parsed.args[2];
final newRegion = parseXml(xmlRegion);
if (newRegion == null) return;
if (regionId != 'null' && regionId.isNotEmpty) {
final parent = findElementInHead(
(el) => el is Region && el.id == regionId,
);
if (parent != null) {
parent.children.add(newRegion);
newRegion.parent = parent;
}
} else {
final parent = findElementInHead(
(el) =>
el.xmlTagName == 'regionBase' &&
(regionBaseId.isEmpty || el.id == regionBaseId),
);
if (parent != null) {
parent.children.add(newRegion);
newRegion.parent = parent;
}
}
break;
case 'removeRegion':
if (parsed.args.isEmpty) return;
removeElementFromHead(parsed.args[0]);
break;
case 'addRuleBase':
if (parsed.args.isEmpty) return;
final el = parseXml(parsed.args[0]);
if (el != null) {
doc.head?.add(el);
}
break;
case 'removeRuleBase':
if (parsed.args.isEmpty) return;
removeElementFromHead(parsed.args[0]);
break;
case 'addRule':
if (parsed.args.isEmpty) return;
final ruleXmlStr =
parsed.args.length > 1 ? parsed.args[1] : parsed.args[0];
final parentId = parsed.args.length > 1 ? parsed.args[0] : null;
final newRule = parseXml(ruleXmlStr);
if (newRule == null) return;
final parentRuleBase = findElementInHead(
(el) => parentId != null
? el.rawAttributes['id'] == parentId
: el.xmlTagName == 'ruleBase',
);
if (parentRuleBase != null) {
parentRuleBase.children.add(newRule);
newRule.parent = parentRuleBase;
}
break;
case 'removeRule':
if (parsed.args.isEmpty) return;
removeElementFromHead(
parsed.args.length > 1 ? parsed.args[1] : parsed.args[0],
);
break;
case 'addConnectorBase':
if (parsed.args.isEmpty) return;
final el = parseXml(parsed.args[0]);
if (el != null) {
doc.head?.add(el);
}
break;
case 'removeConnectorBase':
if (parsed.args.isEmpty) return;
removeElementFromHead(parsed.args[0]);
break;
case 'addConnector':
if (parsed.args.isEmpty) return;
final connXmlStr =
parsed.args.length > 1 ? parsed.args[1] : parsed.args[0];
final parentConnId = parsed.args.length > 1 ? parsed.args[0] : null;
final newConnector = parseXml(connXmlStr);
if (newConnector == null) return;
final parentConnBase = findElementInHead(
(el) => parentConnId != null
? el.rawAttributes['id'] == parentConnId
: el.xmlTagName == 'connectorBase',
);
if (parentConnBase != null) {
parentConnBase.children.add(newConnector);
newConnector.parent = parentConnBase;
}
break;
case 'removeConnector':
if (parsed.args.isEmpty) return;
removeElementFromHead(
parsed.args.length > 1 ? parsed.args[1] : parsed.args[0],
);
break;
case 'addDescriptorBase':
if (parsed.args.isEmpty) return;
final el = parseXml(parsed.args[0]);
if (el != null) {
doc.head?.add(el);
}
break;
case 'removeDescriptorBase':
if (parsed.args.isEmpty) return;
removeElementFromHead(parsed.args[0]);
break;
case 'addDescriptor':
if (parsed.args.isEmpty) return;
final descXmlStr =
parsed.args.length > 1 ? parsed.args[1] : parsed.args[0];
final parentDescId = parsed.args.length > 1 ? parsed.args[0] : null;
final newDesc = parseXml(descXmlStr);
if (newDesc == null) return;
final parentDescBase = findElementInHead(
(el) => parentDescId != null
? el.rawAttributes['id'] == parentDescId
: el.xmlTagName == 'descriptorBase',
);
if (parentDescBase != null) {
parentDescBase.children.add(newDesc);
newDesc.parent = parentDescBase;
}
break;
case 'removeDescriptor':
if (parsed.args.isEmpty) return;
removeElementFromHead(
parsed.args.length > 1 ? parsed.args[1] : parsed.args[0],
);
break;
case 'addDescriptorSwitch':
if (parsed.args.isEmpty) return;
final descSwXmlStr =
parsed.args.length > 1 ? parsed.args[1] : parsed.args[0];
final parentDescSwId = parsed.args.length > 1 ? parsed.args[0] : null;
final newDescSwitch = parseXml(descSwXmlStr);
if (newDescSwitch == null) return;
final parentDescSwBase = findElementInHead(
(el) => parentDescSwId != null
? el.rawAttributes['id'] == parentDescSwId
: el.xmlTagName == 'descriptorBase',
);
if (parentDescSwBase != null) {
parentDescSwBase.children.add(newDescSwitch);
newDescSwitch.parent = parentDescSwBase;
}
break;
case 'removeDescriptorSwitch':
if (parsed.args.isEmpty) return;
removeElementFromHead(
parsed.args.length > 1 ? parsed.args[1] : parsed.args[0],
);
break;
case 'addTransitionBase':
if (parsed.args.isEmpty) return;
final el = parseXml(parsed.args[0]);
if (el != null) {
doc.head?.add(el);
}
break;
case 'removeTransitionBase':
if (parsed.args.isEmpty) return;
removeElementFromHead(parsed.args[0]);
break;
case 'addTransition':
if (parsed.args.isEmpty) return;
final transXmlStr =
parsed.args.length > 1 ? parsed.args[1] : parsed.args[0];
final parentTransId = parsed.args.length > 1 ? parsed.args[0] : null;
final newTrans = parseXml(transXmlStr);
if (newTrans == null) return;
final parent = findElementInHead(
(el) => parentTransId != null
? el.rawAttributes['id'] == parentTransId
: el.xmlTagName == 'transitionBase',
);
if (parent != null) {
parent.children.add(newTrans);
newTrans.parent = parent;
}
break;
case 'removeTransition':
if (parsed.args.isEmpty) return;
removeElementFromHead(
parsed.args.length > 1 ? parsed.args[1] : parsed.args[0],
);
break;
case 'addImportBase':
if (parsed.args.isEmpty) return;
final newImport = parseXml(parsed.args[0]);
if (newImport == null) return;
final parent = findElementInHead(
(el) => el.xmlTagName == 'importedDocumentBase',
);
if (parent != null) {
parent.children.add(newImport);
newImport.parent = parent;
}
break;
case 'removeImportBase':
if (parsed.args.isEmpty) return;
final docURI = parsed.args[0];
final parentImport = findElementInHead(
(el) => el.xmlTagName == 'importedDocumentBase',
);
if (parentImport != null) {
parentImport.children.removeWhere(
(el) => el.rawAttributes['documentURI'] == docURI,
);
}
break;
case 'addImportedDocumentBase':
if (parsed.args.isEmpty) return;
final el = parseXml(parsed.args[0]);
if (el != null) {
doc.head?.add(el);
}
break;
case 'removeImportedDocumentBase':
if (parsed.args.isEmpty) return;
removeElementFromHead(parsed.args[0]);
break;
case 'addImportNCL':
if (parsed.args.isEmpty) return;
final newImportNCL = parseXml(parsed.args[0]);
if (newImportNCL == null) return;
final parentImportNCL = findElementInHead(
(el) => el.xmlTagName == 'importedDocumentBase',
);
if (parentImportNCL != null) {
parentImportNCL.children.add(newImportNCL);
newImportNCL.parent = parentImportNCL;
}
break;
case 'removeImportNCL':
if (parsed.args.isEmpty) return;
final docURINcl = parsed.args[0];
final parentImportNcl = findElementInHead(
(el) => el.xmlTagName == 'importedDocumentBase',
);
if (parentImportNcl != null) {
parentImportNcl.children.removeWhere(
(el) => el.rawAttributes['documentURI'] == docURINcl,
);
}
break;
case 'addNode':
if (parsed.args.length < 2) return;
final compositeId = parsed.args[0];
final nodeArg = parsed.args[1];
final parentComp = doc.getNodeById(compositeId);
if (parentComp is Composition) {
if (nodeArg.trim().startsWith('<')) {
final newNode = parseXml(nodeArg);
if (newNode is Node) {
parentComp.children.add(newNode);
newNode.parent = parentComp;
}
} else {
final nodeId = nodeArg;
final docURI = parsed.args.length > 2 ? parsed.args[2] : '';
final newNode = Media(
rawAttributes: {'id': nodeId, 'refer': docURI},
);
parentComp.children.add(newNode);
newNode.parent = parentComp;
}
}
break;
case 'removeNode':
if (parsed.args.length < 2) return;
final compositeId = parsed.args[0];
final nodeId = parsed.args[1];
final parentComp = doc.getNodeById(compositeId);
if (parentComp is Composition) {
parentComp.children.removeWhere(
(el) => el is Node && el.id == nodeId,
);
}
break;
case 'addInterface':
if (parsed.args.length < 2) return;
final nodeId = parsed.args[0];
final xmlInterface = parsed.args[1];
final targetNode = doc.getNodeById(nodeId);
if (targetNode != null) {
final newInterface = parseXml(xmlInterface);
if (newInterface != null) {
targetNode.children.add(newInterface);
newInterface.parent = targetNode;
}
}
break;
case 'removeInterface':
if (parsed.args.length < 2) return;
final nodeId = parsed.args[0];
final interfaceId = parsed.args[1];
final targetNode = doc.getNodeById(nodeId);
if (targetNode != null) {
targetNode.children.removeWhere((el) => el.id == interfaceId);
}
break;
case 'addLink':
if (parsed.args.length < 2) return;
final compositeId = parsed.args[0];
final xmlLink = parsed.args[1];
final parentComp = doc.getNodeById(compositeId);
if (parentComp is Composition) {
final newLink = parseXml(xmlLink);
if (newLink is Link) {
parentComp.children.add(newLink);
newLink.parent = parentComp;
}
}
break;
case 'removeLink':
if (parsed.args.length < 2) return;
final compositeId = parsed.args[0];
final linkId = parsed.args[1];
final parentComp = doc.getNodeById(compositeId);
if (parentComp is Composition) {
parentComp.children.removeWhere(
(el) => el is Link && el.id == linkId,
);
}
break;
case 'addPort':
if (parsed.args.length < 2) return;
final compositeId = parsed.args[0];
final xmlPort = parsed.args[1];
final parentComp = doc.getNodeById(compositeId);
if (parentComp is Composition) {
final newPort = parseXml(xmlPort);
if (newPort is Port) {
parentComp.children.add(newPort);
newPort.parent = parentComp;
}
}
break;
case 'removePort':
if (parsed.args.length < 2) return;
final compositeId = parsed.args[0];
final portId = parsed.args[1];
final parentComp = doc.getNodeById(compositeId);
if (parentComp is Composition) {
parentComp.children.removeWhere(
(el) => el is Port && el.id == portId,
);
}
break;
case 'setPropertyValue':
if (parsed.args.length < 3) return;
final nodeId = parsed.args[0];
final propertyId = parsed.args[1];
final value = parsed.args[2];
final targetNode = doc.getNodeById(nodeId);
if (targetNode != null) {
targetNode.setPropertyValue(propertyId, value);
}
break;
case 'addFontBase':
if (parsed.args.isEmpty) return;
final el = parseXml(parsed.args[0]);
if (el != null) {
doc.head?.add(el);
}
break;
case 'removeFontBase':
if (parsed.args.isEmpty) return;
removeElementFromHead(parsed.args[0]);
break;
case 'addFont':
if (parsed.args.isEmpty) return;
final newFont = parseXml(parsed.args[0]);
if (newFont != null) {
final parent = findElementInHead((el) => el.xmlTagName == 'fontBase');
if (parent != null) {
parent.children.add(newFont);
newFont.parent = parent;
}
}
break;
case 'removeFont':
if (parsed.args.length < 3) return;
final family = parsed.args[0];
final style = parsed.args[1];
final weight = parsed.args[2];
final parent = findElementInHead((el) => el.xmlTagName == 'fontBase');
if (parent != null) {
parent.children.removeWhere(
(el) =>
(el.rawAttributes['family'] == family ||
el.rawAttributes['fontFamily'] == family) &&
(el.rawAttributes['style'] == style ||
el.rawAttributes['fontStyle'] == style) &&
(el.rawAttributes['weight'] == weight ||
el.rawAttributes['fontWeight'] == weight),
);
}
break;
}
}