diff --git a/Architype.js b/Architype.js index afc462d..da176a3 100644 --- a/Architype.js +++ b/Architype.js @@ -102,6 +102,7 @@ class Architype { render.postMessage(this.serialized_); } + // TODO: factor out draw/grid code onResize(e) { this.fixSizes(); } @@ -211,10 +212,6 @@ class Architype { } - - - - diff --git a/Editor.js b/Editor.js index f8179c9..e4d936d 100644 --- a/Editor.js +++ b/Editor.js @@ -4,6 +4,7 @@ class Editor extends List { static NODE = 1; static GROUP = 2; static LINK = 3; + static LABEL = 4; constructor(container, allowedTypes) { super(container); @@ -54,6 +55,24 @@ class Editor extends List { } } + addLabelBefore() { + if (this.isAllowed(Editor.LABEL)) { + EditorLabel.addBefore(this.container_, this.getSelected()); + } + } + + addLabelAfter() { + if (this.isAllowed(Editor.LABEL)) { + EditorLabel.addAfter(this.container_, this.getSelected()); + } + } + + addLinkBefore() { + if (this.isAllowed(Editor.LINK)) { + EditorLink.addBefore(this.container_, this.getSelected()); + } + } + addLinkAfter() { if (this.isAllowed(Editor.LINK)) { EditorLink.addAfter(this.container_, this.getSelected()); @@ -80,6 +99,18 @@ class Editor extends List { onKeyDown(e) { switch (e.key) { + case 'a': + this.addLabelAfter(); + e.stopPropagation(); + e.preventDefault(); + return; + + case 'A': + this.addLabelBefore(); + e.stopPropagation(); + e.preventDefault(); + return; + case 'g': this.addGroupAfter(); e.stopPropagation(); @@ -120,3 +151,9 @@ class Editor extends List { super.onKeyDown(e); } } + + + + + + diff --git a/EditorEntryBase.js b/EditorEntryBase.js index 69f805e..0d93a4c 100644 --- a/EditorEntryBase.js +++ b/EditorEntryBase.js @@ -61,6 +61,8 @@ class EditorEntryBase extends ListenUtils { switch (ser.type) { case 'group': return EditorGroup.unserialize(ser); + case 'label': + return EditorLabel.unserialize(ser); case 'link': return EditorLink.unserialize(ser); case 'node': diff --git a/EditorGroup.js b/EditorGroup.js index 5d88fe9..62b6578 100644 --- a/EditorGroup.js +++ b/EditorGroup.js @@ -6,7 +6,7 @@ class EditorGroup extends EditorEntryBase { this.elem_.classList.add('group'); let nodeList = document.createElement('div'); - this.nodes_ = new Editor(nodeList, [Editor.NODE]); + this.nodes_ = new Editor(nodeList, [Editor.NODE, Editor.LABEL]); this.nodes_.setMinEntries(1); this.nodes_.addNodeAfter(); this.elem_.appendChild(nodeList); diff --git a/EditorLabel.js b/EditorLabel.js new file mode 100644 index 0000000..7727971 --- /dev/null +++ b/EditorLabel.js @@ -0,0 +1,109 @@ +// TODO: Factor out common code with EditorNode +class EditorLabel extends EditorEntryBase { + constructor() { + super(); + + this.elem_.classList.add('label'); + + this.input_ = document.createElement('input'); + this.input_.type = 'text'; + this.input_.placeholder = 'label'; + this.listen(this.input_, 'keydown', (e) => this.onInputKeyDown(e)); + this.listen(this.input_, 'input', (e) => this.onInput()); + this.elem_.appendChild(this.input_); + } + + afterDomAdd() { + this.input_.focus(); + } + + serialize() { + return { + type: 'label', + label: this.getLabel(), + }; + } + + exportGraphviz() { + return []; + } + + getLabel() { + return this.input_.value; + } + + setLabel(label) { + this.input_.value = label; + this.onInput(); + } + + getElement() { + return this.elem_; + } + + wantFocus() { + return this.getLabel() == ''; + } + + onInput() { + this.input_.setAttribute('data-arch-value', this.input_.value); + } + + onInputKeyDown(e) { + switch (e.key) { + case 'Enter': + e.stopPropagation(); + if (this.elem_.nextElementSibling && + this.elem_.nextElementSibling.xArchObj && + this.elem_.nextElementSibling.xArchObj.wantFocus()) { + this.elem_.nextElementSibling.xArchObj.startEdit(); + } else { + this.stopEdit(); + } + break; + + case 'Escape': + e.stopPropagation(); + this.stopEdit(); + break; + + case 'ArrowUp': + case 'ArrowDown': + case 'PageUp': + case 'PageDown': + this.stopEdit(); + break; + + default: + e.stopPropagation(); + break; + } + } + + onKeyDown(e) { + super.onKeyDown(e); + + switch (e.key) { + case 'Enter': + this.startEdit(); + e.stopPropagation(); + e.preventDefault(); + break; + } + } + + startEdit() { + this.input_.focus(); + } + + stopEdit() { + this.elem_.focus(); + } + + static unserialize(ser) { + let label = new EditorLabel(); + label.setLabel(ser.label); + return label.getElement(); + } +} + diff --git a/architype.css b/architype.css index e2830e5..e88d1b8 100644 --- a/architype.css +++ b/architype.css @@ -4,6 +4,7 @@ --node: #091d2a; --group: #092a17; --link: #331400; + --label: #330025; --text: #ffffff; --placeholder: rgba(255,255,255,0.2); --outline: #323434; @@ -89,6 +90,12 @@ body { .editor li.link { background-color: var(--link); } + +.editor li.label { + background-color: var(--label); +} + + .editor li:focus { border-left: 10px solid var(--focus) !important; }