Reorder the chain by dragging a row
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -122,6 +122,30 @@ bool addFromMenu(Gtk::MenuButton& add, const std::string& title) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// The drop target the chain list reorders its rows with.
|
||||
GtkDropTarget* chainDropTarget(Gtk::Widget& list) {
|
||||
GListModel* controllers = gtk_widget_observe_controllers(list.gobj());
|
||||
GtkDropTarget* found = nullptr;
|
||||
for (guint i = 0; i < g_list_model_get_n_items(controllers) && found == nullptr; ++i) {
|
||||
auto* controller = g_list_model_get_item(controllers, i);
|
||||
if (GTK_IS_DROP_TARGET(controller)) found = GTK_DROP_TARGET(controller);
|
||||
g_object_unref(controller);
|
||||
}
|
||||
g_object_unref(controllers);
|
||||
return found;
|
||||
}
|
||||
|
||||
// What dropping the row of stage `index` at `y` does; a real drag needs a
|
||||
// pointer, which the tests do not have.
|
||||
void dropStage(GtkDropTarget* drop, int index, double y) {
|
||||
GValue value = G_VALUE_INIT;
|
||||
g_value_init(&value, G_TYPE_INT);
|
||||
g_value_set_int(&value, index);
|
||||
gboolean handled = FALSE;
|
||||
g_signal_emit_by_name(drop, "drop", &value, 1.0, y, &handled);
|
||||
g_value_unset(&value);
|
||||
}
|
||||
|
||||
void runTests(Gtk::Window& window) {
|
||||
const auto& effects = effector::effects();
|
||||
|
||||
@@ -239,6 +263,43 @@ void runTests(Gtk::Window& window) {
|
||||
"Remove drops the stage and renumbers the rest");
|
||||
check(!sources->get_visible(), "and the sources hide again");
|
||||
|
||||
std::cout << "drag and drop\n";
|
||||
addFromMenu(*add, "Scanlines");
|
||||
for (const auto& effect : effects) {
|
||||
if (effect->title() != "Blur" && effect->title() != "Scanlines") {
|
||||
addFromMenu(*add, effect->title());
|
||||
break;
|
||||
}
|
||||
}
|
||||
GtkDropTarget* drop = chainDropTarget(*chainList);
|
||||
check(drop != nullptr, "the chain list takes drops");
|
||||
if (drop != nullptr && rowCount(*chainList) == 3) {
|
||||
const std::string first = rowTitle(*chainList, 0).substr(3);
|
||||
const std::string second = rowTitle(*chainList, 1).substr(3);
|
||||
const std::string third = rowTitle(*chainList, 2).substr(3);
|
||||
const double bottom = chainList->get_row_at_index(2)->get_height() * 3.0;
|
||||
GdkDragAction action = GDK_ACTION_NONE;
|
||||
g_signal_emit_by_name(drop, "motion", 1.0, bottom, &action);
|
||||
check(chainList->get_row_at_index(2)->has_css_class("drop-after"),
|
||||
"dragging past the last row marks its bottom edge");
|
||||
dropStage(drop, 0, bottom);
|
||||
pump();
|
||||
check(rowTitle(*chainList, 0) == "1. " + second && rowTitle(*chainList, 1) == "2. " + third &&
|
||||
rowTitle(*chainList, 2) == "3. " + first,
|
||||
"dropping the first stage past the last moves it to the end");
|
||||
check(chainList->get_selected_row() == chainList->get_row_at_index(2),
|
||||
"and selects it");
|
||||
check(!chainList->get_row_at_index(2)->has_css_class("drop-after"),
|
||||
"and clears the mark");
|
||||
dropStage(drop, 2, 1.0);
|
||||
pump();
|
||||
check(rowTitle(*chainList, 0) == "1. " + first && rowTitle(*chainList, 1) == "2. " + second,
|
||||
"dropping on the top edge of the first row moves it to the front");
|
||||
}
|
||||
for (int i = rowCount(*chainList) - 1; i > 0; --i) {
|
||||
if (auto* removeRow = withTooltip(*chainList->get_row_at_index(i), "Remove")) press(*removeRow);
|
||||
}
|
||||
|
||||
std::cout << "many stages\n";
|
||||
for (int i = 0; i < 4; ++i) addFromMenu(*add, effects[static_cast<std::size_t>(i) % effects.size()]->title());
|
||||
pump();
|
||||
|
||||
Reference in New Issue
Block a user