From 23ff50bd76c2667769c81264911d7eb6450360fc Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sun, 5 Jun 2022 14:40:10 +0300 Subject: [PATCH] feat: multi-parental tree controls --- modules/dynamic/editors/cultures-editor.js | 73 +++++++++++++++------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/modules/dynamic/editors/cultures-editor.js b/modules/dynamic/editors/cultures-editor.js index b72702a7..154fe9fe 100644 --- a/modules/dynamic/editors/cultures-editor.js +++ b/modules/dynamic/editors/cultures-editor.js @@ -298,15 +298,13 @@ function cultureHighlightOn(event) { const culture = Number(event.id || event.target.dataset.id); const $info = byId("cultureInfo"); if ($info) { - d3.select("#hierarchy") - .select("g[data-id='" + culture + "'] > path") - .classed("selected", 1); + d3.select("#hierarchy").select(`g[data-id='${culture}']`).classed("selected", 1); const c = pack.cultures[culture]; const rural = c.rural * populationRate; const urban = c.urban * populationRate * urbanization; const population = rural + urban > 0 ? si(rn(rural + urban)) + " people" : "Extinct"; $info.innerHTML = `${c.name} culture. ${c.type}. ${population}`; - tip("Drag to change parent, drag to itself to move to the top level. Hold CTRL and click to change abbreviation"); + tip("Drag to other node to add parent, click to edit"); } if (!layerIsOn("toggleCultures")) return; @@ -329,11 +327,10 @@ function cultureHighlightOn(event) { function cultureHighlightOff(event) { const culture = Number(event.id || event.target.dataset.id); + const $info = byId("cultureInfo"); if ($info) { - d3.select("#hierarchy") - .select("g[data-id='" + culture + "'] > path") - .classed("selected", 0); + d3.select("#hierarchy").select(`g[data-id='${culture}']`).classed("selected", 0); $info.innerHTML = "‍"; tip(""); } @@ -673,11 +670,20 @@ function showHierarchy() { const h = height + 30 - margin.top - margin.bottom; const treeLayout = d3.tree().size([w, h]); + alertMessage.innerHTML = /* html */ `
+
+ +
`; + // prepare svg - alertMessage.innerHTML = "
"; const svg = d3 .select("#alertMessage") - .insert("svg", "#cultureInfo") + .insert("svg", "#cultureChartDetails") .attr("id", "hierarchy") .attr("width", width) .attr("height", height) @@ -745,6 +751,7 @@ function showHierarchy() { .attr("transform", d => `translate(${d.x}, ${d.y})`) .on("mouseenter", cultureHighlightOn) .on("mouseleave", cultureHighlightOff) + .on("click", cultureSelect) .call(d3.drag().on("start", dragToReorigin)); node @@ -771,9 +778,38 @@ function showHierarchy() { } }); - function dragToReorigin(d) { - if (isCtrlClick(d3.event.sourceEvent)) return changeCode(d); + function cultureSelect(d) { + d3.event.stopPropagation(); + nodes.selectAll("g").style("outline", "none"); + this.style.outline = "1px solid #c13119"; + byId("cultureSelected").style.display = "block"; + byId("cultureInfo").style.display = "none"; + + const culture = d.data; + byId("cultureSelectedName").innerText = culture.name; + byId("cultureSelectedCode").value = culture.code; + + byId("cultureSelectedCode").onchange = function () { + if (this.value.length > 3) return tip("Abbreviation must be 3 characters or less", false, "error", 3000); + if (!this.value.length) return tip("Abbreviation cannot be empty", false, "error", 3000); + nodes.select(`g[data-id="${d.id}"] > text`).text(this.value); + culture.code = this.value; + }; + + byId("cultureSelectedClear").onclick = () => { + culture.origins = [0]; + showHierarchy(); + }; + + byId("cultureSelectedClose").onclick = () => { + this.style.outline = "none"; + byId("cultureSelected").style.display = "none"; + byId("cultureInfo").style.display = "block"; + }; + } + + function dragToReorigin(d) { const originLine = graph.append("path").attr("class", "dragLine").attr("d", `M${d.x},${d.y}L${d.x},${d.y}`); d3.event.on("drag", () => { @@ -782,10 +818,11 @@ function showHierarchy() { d3.event.on("end", () => { originLine.remove(); - const selected = graph.select("path.selected"); + const selected = graph.select("g.selected"); if (!selected.size()) return; + const cultureId = d.data.i; - let newOrigin = Number(selected.datum().data.i); + const newOrigin = Number(selected.datum().data.i); if (cultureId === newOrigin) return; // dragged to itself if (d.data.origins.includes(newOrigin)) return; // already a child of the selected node if (newOrigin && d.descendants().some(node => node.id === newOrigin)) return; // cannot be a child of its own child @@ -797,16 +834,6 @@ function showHierarchy() { showHierarchy(); }); } - - function changeCode(d) { - prompt(`Please provide an abbreviation for culture: ${d.data.name}`, {default: d.data.code}, v => { - pack.cultures[d.data.i].code = v; - nodes - .select("g[data-id='" + d.data.i + "']") - .select("text") - .text(v); - }); - } } function recalculateCultures(must) {