Phase 23: refine routing inspection, signal-flow layout and atomic wire insertion

This commit is contained in:
Johannes Findeisen 2026-10-27 16:00:29 +01:00
commit ba5c2503a7
15 changed files with 533 additions and 22 deletions

View file

@ -63,6 +63,15 @@ SequencerWidget *timeline(Fl_Group *group)
}
return nullptr;
}
GraphWidget *graph_canvas(Fl_Group *group)
{
for (int i = 0; i < group->children(); ++i) {
if (auto *canvas = dynamic_cast<GraphWidget *>(group->child(i))) return canvas;
if (auto *nested = dynamic_cast<Fl_Group *>(group->child(i)))
if (auto *canvas = graph_canvas(nested)) return canvas;
}
return nullptr;
}
void gesture(Fl_Widget *s, int left, int top, int dx, int dy)
{
int old_x = Fl::e_x, old_y = Fl::e_y, old_key = Fl::e_keysym;
@ -549,6 +558,50 @@ int main(int argc, char **argv)
CHECK(xtc_project_get_track(s->project(),0,&t) == XTC_OK && !std::strcmp(t.name,"Keys"));
window.do_callback();
}
{
reset();
MainWindow window(false);
auto *canvas = graph_canvas(&window);
CHECK(canvas != nullptr);
CHECK(canvas->add_node(XTC_NODE_OSCILLATOR) == XTC_OK);
CHECK(canvas->add_node(XTC_NODE_OUTPUT) == XTC_OK);
CHECK(canvas->connect_ports({0,1,1,0}) == XTC_OK);
CHECK(canvas->select_connection(0,1) && contains(&window, "Wire: #0 audio out -> #1 sum in"));
const xtc_graph *original = canvas->graph();
unsigned int submitted = submissions;
submit_result = XTC_ERR_CAPACITY;
CHECK(canvas->insert_gain() == XTC_ERR_CAPACITY && canvas->graph() == original && submissions == submitted+1);
submit_result = XTC_OK;
CHECK(canvas->insert_gain() == XTC_OK);
size_t inserted = canvas->selected_node(), nodes, edges;
CHECK(inserted == 2);
CHECK(xtc_graph_get_counts(canvas->graph(), &nodes, &edges) == XTC_OK && nodes == 3 && edges == 2);
xtc_routing_info route{};
CHECK(canvas->routing(inserted,route) && route.level == 1 && route.reaches_output && route.inputs == 1);
submitted = submissions;
CHECK(canvas->auto_layout() && submissions == submitted);
int sx = 0, sy = 0, gx = 0, gy = 0, ox = 0, oy = 0;
CHECK(canvas->node_position(0,sx,sy) && canvas->node_position(inserted,gx,gy) && canvas->node_position(1,ox,oy));
CHECK(sx < gx && gx < ox);
CHECK(canvas->select_node(inserted) && contains(&window,"1 incoming, 1 outgoing"));
CHECK(canvas->select_connection(0,inserted) && canvas->delete_selected() == XTC_OK);
CHECK(canvas->select_node(inserted) && contains(&window,"unwired input uses external audio"));
CHECK(window.undo() == XTC_OK); // Disconnect is independently undoable.
CHECK(window.undo() == XTC_OK); // Whole insertion is one undo step.
CHECK(xtc_graph_get_counts(canvas->graph(), &nodes, &edges) == XTC_OK && nodes == 2 && edges == 1);
CHECK(window.undo(true) == XTC_OK);
CHECK(xtc_graph_get_counts(canvas->graph(), &nodes, &edges) == XTC_OK && nodes == 3 && edges == 2);
CHECK(canvas->select_node(inserted));
int key = Fl::e_keysym, state = Fl::e_state;
Fl::e_keysym = FL_Right; Fl::e_state = 0;
CHECK(canvas->handle(FL_KEYDOWN) == 1 && canvas->selected_node() == 0);
Fl::e_keysym = key; Fl::e_state = state;
// Whole-project binding must give every new node a distinct position.
canvas->reset_layout(); canvas->set_graph(canvas->graph());
CHECK(canvas->node_position(0,sx,sy) && canvas->node_position(inserted,gx,gy) && canvas->node_position(1,ox,oy));
CHECK((sx != gx || sy != gy) && (sx != ox || sy != oy) && (gx != ox || gy != oy));
window.do_callback();
}
if (const char *module = std::getenv("XTC_TEST_PLUGIN")) {
reset();
MainWindow window(false);