feat: dock editor panels and add resizable pinned track headers

This commit is contained in:
Johannes Findeisen 2026-11-06 00:06:56 +01:00
commit ae8556d83f
13 changed files with 346 additions and 87 deletions

View file

@ -255,14 +255,7 @@ int main(int argc, char **argv)
CHECK(std::strcmp(tabs->value()->label(), std::strchr(view, '/') + 1) == 0);
}
}
GraphWidget *canvas = nullptr;
auto *graph_group = dynamic_cast<Fl_Group *>(find(&window, "Modular Graph"));
CHECK(graph_group != nullptr);
if (graph_group != nullptr) {
for (int i = 0; i < graph_group->children(); ++i) if (auto *scroll = dynamic_cast<Fl_Group *>(graph_group->child(i)))
for (int j = 0; j < scroll->children(); ++j)
if (auto *found = dynamic_cast<GraphWidget *>(scroll->child(j))) canvas = found;
}
GraphWidget *canvas = graph_canvas(&window);
CHECK(canvas != nullptr);
if (canvas == nullptr) return 1;
menu->picked(menu->find_item("View/Modular Graph"));
@ -1204,7 +1197,7 @@ int main(int argc, char **argv)
auto *play=find(&window,"Play");
auto *bpm=dynamic_cast<Fl_Value_Input *>(find(&window,"BPM"));
auto *loop=dynamic_cast<Fl_Check_Button *>(find(&window,"Loop"));
auto *tabs=dynamic_cast<Fl_Tabs *>(sequence->parent()->parent()->parent());
auto *tabs=dynamic_cast<Fl_Tabs *>(sequence->parent()->parent()->parent()->parent());
CHECK(play && bpm && loop && tabs);
int original_y=tabs->y();
for (int pass=0;pass<3;++pass) {
@ -1266,6 +1259,54 @@ int main(int argc, char **argv)
}
unlink(path.c_str());
}
reset();
{
std::string path="/tmp/xtc-editors-"+std::to_string(getpid())+".conf";
{
MainWindow window(false,path.c_str());window.show();CHECK(window.create_track(true)==XTC_OK);
auto *sequence=timeline(&window);auto *graph=graph_canvas(&window);const xtc_project *project=sequence->project();
uint64_t track=sequence->selected_track(),clip=sequence->selected_clip();
auto *scroll=dynamic_cast<Fl_Scroll *>(sequence->parent());CHECK(scroll);scroll->scroll_to(400,0);pump();
int pinned=sequence->header_left();CHECK(pinned==scroll->x());
sequence->header_width(260);pump();CHECK(sequence->header_width()==260 && scroll->xposition()==400);
CHECK(sequence->instrument_choice(track)->x()==pinned+10 && sequence->instrument_choice(track)->w()==238);
gesture(sequence,pinned-sequence->x()+258,16,40,0);CHECK(sequence->header_width()==300);
sequence->header_width(260);
CHECK(window.open_piano_roll()==XTC_OK);auto *piano=window.piano_roll();
CHECK(piano->add_note(0,240,60)==XTC_OK);uint64_t note=piano->selected_note();
project=sequence->project();
auto *piano_scroll=dynamic_cast<Fl_Scroll *>(piano->parent());CHECK(piano_scroll);piano_scroll->scroll_to(10,500);
for(int pass=0;pass<3;++pass) {
window.detach_editor(0,true);window.detach_editor(1,true);window.detach_piano(false);pump();
CHECK(sequence->window()==window.editor_window(0) && graph->window()==window.editor_window(1));
CHECK(find(window.editor_window(0),"Snap")!=nullptr);
CHECK(piano->window()==&window && piano->selected_note()==note && sequence->project()==project);
CHECK(sequence->selected_track()==track && sequence->selected_clip()==clip);
CHECK(scroll->xposition()==400 && piano_scroll->yposition()==500);
window.editor_window(0)->resize(20,20,1200,700);window.editor_window(1)->resize(30,30,1000,500);pump();
window.detach_piano(true);CHECK(piano->window()!=&window);
auto *piano_window=piano->window();piano_window->do_callback();CHECK(piano->window()==&window);
window.editor_window(0)->do_callback();window.editor_window(1)->do_callback();pump();
CHECK(sequence->window()==&window && graph->window()==&window && scroll->xposition()==400);
CHECK(piano->selected_note()==note && sequence->project()==project);
}
window.detach_editor(0,true);window.detach_editor(1,true);window.detach_piano(false);
Fl::add_timeout(.05,[](void *) {auto *d=Fl::first_window();press(find(d,"Apply"));press(find(d,"Close"));});
window.show_preferences();xtc_settings saved{};CHECK(xtc_settings_load(&saved,path.c_str())==XTC_OK);
CHECK(saved.sequencer_detached && saved.graph_detached && !saved.piano_detached && saved.track_header_width==260);
close_result=XTC_ERR_IO;window.do_callback();CHECK(window.editor_window(0)->shown() && window.editor_window(1)->shown());
close_result=XTC_OK;window.do_callback();CHECK(!window.editor_window(0)->shown() && !window.editor_window(1)->shown());
}
{
MainWindow window(false,path.c_str());window.show();pump();
CHECK(window.editor_window(0)->shown() && window.editor_window(1)->shown());
CHECK(window.create_track(true)==XTC_OK && window.open_piano_roll()==XTC_OK && window.piano_roll()->window()==&window);
window.reset_layout();pump();CHECK(timeline(&window) && graph_canvas(&window));
CHECK(!window.editor_window(0)->shown() && !window.editor_window(1)->shown());
CHECK(timeline(&window)->header_width()==180);window.do_callback();
}
unlink(path.c_str());
}
if (failures != 0) return 1;
std::printf("GUI controls/errors/views/timers/cleanup passed: %u opens, %u closes.\n", opens, closes);
return 0;