Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Dimitri Chauvel committed Sep 18, 2023
1 parent 1730cc3 commit 713b944
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 48 deletions.
4 changes: 2 additions & 2 deletions demo/src/assets/resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export default {
{% if hasError %}
<g class="error-icon">
<svg width="15" height="15" x="5" y="5" fill="#BB0A21" viewBox="0 0 512 512">
<svg width="15" height="15" x="200" y="10" fill="yellow" viewBox="0 0 512 512">
<path d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512
256 512zm0-384c13.3 0 24 10.7 24 24V264c0 13.3-10.7 24-24
24s-24-10.7-24-24V152c0-13.3 10.7-24 24-24zm32 224c0 17.7-14.3 32-32
Expand Down Expand Up @@ -85,7 +85,7 @@ export default {
{% endif %}
/>
<g class="components" transform="translate({{ 6 + padding }},{{ 50 + padding }})"></g>
<g class="components" transform="translate({{ 6 }},{{ 50 }})"></g>
</svg>
`,
},
Expand Down
57 changes: 24 additions & 33 deletions src/draw/DefaultDrawer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as d3 from 'd3';
import ElkLayout from './ElkLayout';
import ElkLayout from './layout/ElkLayout';
import ComponentRenderer from './render/ComponentRenderer';

/**
Expand All @@ -11,20 +11,41 @@ class DefaultDrawer {
* @param {DefaultData} pluginData - Plugin data storage.
* @param {object} [resources] - Object that contains resources.
* @param {string} [viewPortId] - Id of HTML element where we want to draw.
* @param option
*/
constructor(pluginData, resources = null, viewPortId = 'view-port') {
constructor(pluginData, resources = null, viewPortId = 'view-port', option = {
padding: 10,
gap: 50,
}) {
/**
* Plugin data storage.
* @type {DefaultData}
*/
this.pluginData = pluginData;

/**
* Component renderer.
*/
this.componentRenderer = new ComponentRenderer({ padding: option.padding });

/**
* Plugin layout system.
* @type {DefaultLayout}
* @default new ElkLayout()
*/
this.layout = new ElkLayout(this.pluginData);
this.layout = new ElkLayout(
this.pluginData,
{ componentRenderer: this.componentRenderer },
{
'elk.padding': `[
left=${option.padding},
top=${option.padding},
right=${option.padding},
bottom=${option.padding}
]`,
'elk.layered.spacing.baseValue': option.gap,
},
);

/**
* Object that contains resources.
Expand All @@ -51,11 +72,6 @@ class DefaultDrawer {
* @type {Selection}
*/
this.root = null;

/**
* Component renderer.
*/
this.componentRenderer = new ComponentRenderer();
}

/**
Expand All @@ -80,28 +96,6 @@ class DefaultDrawer {
this.componentRenderer.resources = this.resources;
}

automaticLayout() {
// TODO: implement automatic layout
// first step: sort components by depth (decrescent)
// like this [[depth: 3, depth: 3], [depth: 2, depth: 2], [depth: 1, depth: 1]]
// second step: automatic layout for the deepest components
// third step: filter the components of the previous depth - 1
// to keep the container with children
// four step: set the width and height of these container components

const containerGroups = this.groupNodesByDepth().map((group) => (
group.filter((d) => d.data.definition.isContainer && !!d.children)
));

containerGroups.forEach((group) => {
group.each((d) => {
// TODO: autolayout its children

this.componentRenderer.setAutomaticlyContainerSize(d.data.id);
});
});
}

groupNodesByDepth() {
const nodes = d3.selectAll('.component');
const maxDepth = d3.max(nodes.data(), (d) => d.depth);
Expand All @@ -121,7 +115,6 @@ class DefaultDrawer {
draw() {
this.__drawingComponents();
this.registerComponentsDrawOption();
this.automaticLayout();
}

/**
Expand Down Expand Up @@ -215,8 +208,6 @@ class DefaultDrawer {
const position = this.getNodePosition(component.id);
const size = this.getNodeSize(component.id);

console.log(position, size);

component.drawOption.x = position.x;
component.drawOption.y = position.y;
component.drawOption.width = size.width;
Expand Down
File renamed without changes.
31 changes: 20 additions & 11 deletions src/draw/ElkLayout.js → src/draw/layout/ElkLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,11 @@ class ElkLayout extends DefaultLayout {
/**
* Initializes ELK parameters and inherited fields.
* @param {DefaultData} pluginData - A graph to be arranged.
* @param {object} [renderer] - Renderer for the components. (use defaults if unsure)
* @param {object} [elkParams] - Parameters for the layout algorithm. (use defaults if unsure)
* @see Parameters for ELK: {@link https://eclipse.dev/elk/reference/options.html}
*/
constructor(pluginData, elkParams = {}) {
constructor(pluginData, renderer = {}, elkParams = {}) {
super(pluginData);

/**
Expand All @@ -114,7 +115,6 @@ class ElkLayout extends DefaultLayout {
this.elkParams = {
// default parameters
'elk.algorithm': 'elk.layered',
'spacing.baseValue': '50',
separateConnectedComponents: 'true',
'elk.layered.cycleBreaking.strategy': 'INTERACTIVE',
'elk.layered.layering.strategy': 'INTERACTIVE',
Expand All @@ -126,6 +126,11 @@ class ElkLayout extends DefaultLayout {

...elkParams,
};

this.renderer = {
componentRenderer: null,
...renderer,
};
}

/**
Expand Down Expand Up @@ -158,10 +163,7 @@ class ElkLayout extends DefaultLayout {

// For each parent, from the deepest nodes up to the root, get a layout for its children.
return Promise.all(
this.getParentsByDepth(nodes)
.map(
(node) => this.generateELKLayout(node, nodes, links),
),
this.getParentsByDepth(nodes).map((node) => this.generateELKLayout(node, nodes, links)),
);
}

Expand All @@ -171,7 +173,9 @@ class ElkLayout extends DefaultLayout {
* @private
*/
writeLayout(layout) {
layout.forEach((elkNode) => this.writeSingleDepthLayout(elkNode));
layout.forEach((elkNode) => {
this.writeSingleDepthLayout(elkNode);
});
}

/**
Expand Down Expand Up @@ -273,7 +277,15 @@ class ElkLayout extends DefaultLayout {
}));

// Finally calling ELK.
return ElkLayout.elk.layout(graph);
const layout = await ElkLayout.elk.layout(graph);

this.writeSingleDepthLayout(layout);
this.renderer.componentRenderer.render(layout.id);
if (layout.id !== 'root') {
this.renderer.componentRenderer.setAutomaticlyContainerSize(layout.id);
}

return layout;
}

/**
Expand All @@ -282,7 +294,6 @@ class ElkLayout extends DefaultLayout {
* @private
*/
writeSingleDepthLayout(elkNode) {
console.log('elkNode: ', elkNode);
const nodes = new Map(elkNode.children
.map((node) => [node.id, {
x: node.x,
Expand All @@ -297,8 +308,6 @@ class ElkLayout extends DefaultLayout {
component.drawOption.x = x;
component.drawOption.y = y;
});


}

/**
Expand Down
5 changes: 3 additions & 2 deletions src/draw/render/ComponentRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,24 +74,25 @@ class ComponentRenderer {
/**
* Create nodes.
* @param {string} contextId - Id of current context.
* @param {number} [depth] - Depth of current context.
* @private
*/
render(contextId = this.drawingContextId) {
const context = d3.select(`#${contextId}`);

context.select('.components').selectAll('.component')
context.select('.components').selectAll(`.component[depth="${context.datum().depth + 1}"]`)
.data(({ children }) => children)
.join('g')
.attr('id', ({ data }) => data.id)
.attr('class', 'component')
.attr('depth', (data) => data.depth)
.html(({ data }) => this.renderModel(data))
.filter(({ data, children }) => data.definition.isContainer && !(!children))
.each(({ data }) => this.render(data.id));
}

setAutomaticlyContainerSize(nodeId) {
const node = d3.select(`#${nodeId}`);

const { width, height } = node.select('.components').node().getBoundingClientRect();

node.datum().data.drawOption.innerWidth = width;
Expand Down

0 comments on commit 713b944

Please sign in to comment.