Closed SPYFF closed 7 months ago
Hello @SPYFF ! I created something similar in the past. See: https://arthursonzogni.com/Diagon/#GraphDAG
In your case, I am guessing you are going to make the "node" draggable. I think options 2 is going to work.
I would use the Container::Stacked({...})
with:
Renderer
displaying the canvas
you are talking about for the edges.Window
to display the edgeThanks for the helpful reply! Yes, I'm aware of your Diagon project, and the DAG code is the best currently publicly available on the web (I've tried similar projects, like graph-easy and vijual, but they produce inferior results for large graphs). However, its optimized for compact, static output, which is great for many cases, but I compared it to graphviz output (its unfair, I know) and that output would be better for my interactive usecase. So my plan is to convert graphviz output directly to text.
Thanks for the example and the recommendation, I'll go ahead with it.
With your help I managed to do it:
Screencast from 2024-01-05 18-18-54.webm
In case someone want to reproduce it, here is the snippet:
#include <ftxui/component/component.hpp>
#include <ftxui/component/screen_interactive.hpp>
#include <ftxui/component/component_base.hpp>
#include <ftxui/dom/elements.hpp>
#include <ftxui/dom/node.hpp>
#include <ftxui/dom/canvas.hpp>
#include <iterator>
#include <string>
using namespace ftxui;
int main() {
auto node1 = Renderer([] { return text("node1");});
auto node2 = Renderer([] { return text("node2");});
bool resize = false;
int win1h = 3;
int win1w = std::size(std::string("node1")) + 2;
int win1x = 10, win1y = 5;
int win2h = 3;
int win2w = std::size(std::string("node2")) + 2;
int win2x = 30, win2y = 5;
auto win1 = Window({
.inner = node1,
.left = &win1x,
.top = &win1y,
.width = win1w,
.height = win1h,
.resize_left = resize, .resize_right = resize, .resize_top = resize, .resize_down = resize,
});
auto win2 = Window({
.inner = node2,
.left = &win2x,
.top = &win2y,
.width = win2w,
.height = win2h,
.resize_left = resize, .resize_right = resize, .resize_top = resize, .resize_down = resize,
});
auto edges = Renderer([&] {
auto c = Canvas(400,400);
int from_x = (win1x + win1w / 2) * 2;
int from_y = (win1y + 3 / 2) * 4;
int to_x = (win2x + win2w / 2) * 2;
int to_y = (win2y + 3 / 2) * 4;
c.DrawPointLine(from_x, from_y, to_x, to_y, Color::Red);
return canvas(std::move(c));
});
auto window_container = Container::Stacked({
win1,
win2,
edges,
});
auto screen = ScreenInteractive::Fullscreen();
screen.Loop(window_container);
return EXIT_SUCCESS;
}
Thanks again!
Awesome! I love how it renders. This triggers in me many nice project ideas. Keep us updated what you will achieve from this!
@ArthurSonzogni Sure! I'm thinking about an interactive graph visualizer, something like that:
Screencast from 2024-02-10 14-06-26.webm
Sure, the arrowheads are off, and there are other flaws (all because I forgot everything I learned in trigonometry since school), however your lib doing well rendering the stuff! The layout initially created by graphviz dot, then I parse it to a struct which will be feed to the canvas and that struct updated interactively.
Wow! That's really cool!
Hi,
I want to render interactive DAG graphs (like graphviz dot or d3/cytoscape dagre layout) inside the terminal. Seems like the library can provide all the components needed to render something like this, however I'm not sure if the puzzle pieces fit together. I have three possible approaches in mind, my question is whether one of them works?
Option 1: On the same screen, first render the canvas with the lines (Braille or box) and then, on top of that, render the graph nodes as window components (without title).
Option 2: Only a canvas component, first draw the lines and then render the nodes as boxed text, somehow get the three lines (top, bottom and the text label) in string and put it on top of the lines. Is it possible to render the components as plain text?
Option 3: Is it possible to draw any component on a canvas? To me it looks like canvas at the moment supports limited number of shapes, and not possible to draw other elements (even as static ones, like boxed text).
What approach would work/be possible?
Thanks in advance!