#include "main.h" #include int treecb(struct ncplane* n, void* curry, int pos){ ncplane_printf_yx(n, 0, 0, "item: %s pos: %d", static_cast(curry), pos); return 0; } TEST_CASE("Tree") { auto nc_ = testing_notcurses(); if(!nc_){ return; } struct ncplane* n_ = notcurses_stdplane(nc_); REQUIRE(n_); REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0)); SUBCASE("RefuseStandardPlane") { struct nctree_options opts{}; opts.nctreecb = treecb; auto treen = nctree_create(n_, &opts); REQUIRE(nullptr == treen); CHECK(0 == notcurses_render(nc_)); } // trivial tree with null items SUBCASE("TreeNoItems") { struct ncplane_options nopts{}; nopts.rows = 7; nopts.cols = 20; auto p = ncplane_create(n_, &nopts); REQUIRE(p); struct nctree_options opts{}; opts.nctreecb = treecb; auto treen = nctree_create(p, &opts); REQUIRE(treen); CHECK(0 == notcurses_render(nc_)); nctree_destroy(treen); } nctree_item subs[] = { { .curry = strdup("sub1-0"), .subs = nullptr, .subcount = 0, },{ .curry = strdup("sub1-1"), .subs = nullptr, .subcount = 0, } }; nctree_item items[] = { { .curry = strdup("item0"), .subs = nullptr, .subcount = 0, }, { .curry = strdup("item1"), .subs = subs, .subcount = 2, }, }; // should be refused with a null callback SUBCASE("BadTreeNoCallback") { struct nctree_options opts = { .items = items, .count = sizeof(items) / sizeof(*items), .nctreecb = nullptr, .indentcols = 1, .flags = 0, }; auto treen = nctree_create(n_, &opts); REQUIRE(nullptr == treen); } // should be refused with negative indentcols SUBCASE("BadTreeNoCallback") { struct nctree_options opts = { .items = items, .count = sizeof(items) / sizeof(*items), .nctreecb = treecb, .indentcols = -1, .flags = 0, }; auto treen = nctree_create(n_, &opts); REQUIRE(nullptr == treen); } SUBCASE("Create") { struct nctree_options opts = { .items = items, .count = sizeof(items) / sizeof(*items), .nctreecb = treecb, .indentcols = 1, .flags = 0, }; const ncplane_options nopts = { .y = 0, .x = 0, .rows = 3, .cols = ncplane_dim_y(n_), .userptr = nullptr, .name = nullptr, .resizecb = nullptr, .flags = 0, .margin_b = 0, .margin_r = 0, }; auto treen = ncplane_create(n_, &nopts); REQUIRE(nullptr != treen); auto tree = nctree_create(treen, &opts); REQUIRE(nullptr != tree); CHECK(0 == notcurses_render(nc_)); CHECK(treen == nctree_plane(tree)); CHECK(items[0].curry == nctree_focused(tree)); nctree_destroy(tree); } SUBCASE("Traverse") { struct nctree_options opts = { .items = items, .count = sizeof(items) / sizeof(*items), .nctreecb = treecb, .indentcols = 2, .flags = 0, }; const ncplane_options nopts = { .y = 0, .x = 0, .rows = 3, .cols = ncplane_dim_y(n_), .userptr = nullptr, .name = nullptr, .resizecb = nullptr, .flags = 0, .margin_b = 0, .margin_r = 0, }; auto treen = ncplane_create(n_, &nopts); REQUIRE(nullptr != treen); auto tree = nctree_create(treen, &opts); REQUIRE(nullptr != tree); CHECK(0 == notcurses_render(nc_)); CHECK(treen == nctree_plane(tree)); CHECK(items[0].curry == nctree_focused(tree)); CHECK(items[0].curry == nctree_prev(tree)); CHECK(items[0].curry == nctree_focused(tree)); CHECK(items[1].curry == nctree_next(tree)); CHECK(items[1].curry == nctree_focused(tree)); CHECK(items[1].subs[0].curry == nctree_next(tree)); CHECK(items[1].subs[0].curry == nctree_focused(tree)); CHECK(items[1].subs[1].curry == nctree_next(tree)); CHECK(items[1].subs[1].curry == nctree_focused(tree)); CHECK(items[1].subs[1].curry == nctree_next(tree)); CHECK(items[1].subs[1].curry == nctree_focused(tree)); CHECK(items[1].subs[0].curry == nctree_prev(tree)); CHECK(items[1].subs[0].curry == nctree_focused(tree)); CHECK(items[1].curry == nctree_prev(tree)); CHECK(items[1].curry == nctree_focused(tree)); CHECK(items[0].curry == nctree_prev(tree)); CHECK(items[0].curry == nctree_focused(tree)); CHECK(items[0].curry == nctree_prev(tree)); CHECK(items[0].curry == nctree_focused(tree)); nctree_destroy(tree); } free(subs[0].curry); free(subs[1].curry); free(items[0].curry); free(items[1].curry); nctree_item alphaUs[] = { { .curry = const_cast("²¹⁴U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²¹⁵U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²¹⁶U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²¹⁷U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²¹⁸U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²¹⁹U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²²¹U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²²²U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²²⁸U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²²⁹U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁰U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³¹U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³²U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³³U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁴U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁵U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁶U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁸U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²⁴⁰U"), .subs = NULL, .subcount = 0, }, }; nctree_item alphaU = { .curry = const_cast("ɑ-emitting U"), .subs = alphaUs, .subcount = sizeof(alphaUs) / sizeof(*alphaUs), }; nctree_item doubleUs[] = { { .curry = const_cast("²³⁰U"), .subs = NULL, .subcount = 0, } }; nctree_item doubleU = { .curry = const_cast("ββ-emitting U"), .subs = doubleUs, .subcount = sizeof(doubleUs) / sizeof(*doubleUs), }; nctree_item doubleminusUs[] = { { .curry = const_cast("²³⁸U"), .subs = NULL, .subcount = 0, } }; nctree_item doubleminusU = { .curry = const_cast("β−β−-emitting U"), .subs = doubleminusUs, .subcount = sizeof(doubleminusUs) / sizeof(*doubleminusUs), }; nctree_item betaminusUs[] = { { .curry = const_cast("²³⁹U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²⁴⁰U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²⁴²U"), .subs = NULL, .subcount = 0, } }; nctree_item betaminusPus[] = { { .curry = const_cast("²⁴¹Pu"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²⁴³Pu"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²⁴⁵Pu"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²⁴⁶Pu"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²⁴⁷Pu"), .subs = NULL, .subcount = 0, } }; nctree_item betaminus[] = { { .curry = const_cast("β−-emitting U"), .subs = betaminusUs, .subcount = sizeof(betaminusUs) / sizeof(*betaminusUs), }, { .curry = const_cast("β−-emitting Pu"), .subs = betaminusPus, .subcount = sizeof(betaminusPus) / sizeof(*betaminusPus), }, }; nctree_item betaplusUs[] = { { .curry = const_cast("²²²U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²²⁷U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²²⁹U"), .subs = NULL, .subcount = 0, }, }; nctree_item betaplus = { .curry = const_cast("β-emitting U"), .subs = betaplusUs, .subcount = sizeof(betaplusUs) / sizeof(*betaplusUs), }; nctree_item gammaUs[] = { { .curry = const_cast("²¹⁶Uᵐ"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁴Uᵐ"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁵Uᵐ"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁶Uᵐ¹"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁶Uᵐ²"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁸Uᵐ"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁹Uᵐ¹"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁹Uᵐ²"), .subs = NULL, .subcount = 0, }, }; nctree_item gammas = { .curry = const_cast("γ-emitting U"), .subs = gammaUs, .subcount = sizeof(gammaUs) / sizeof(*gammaUs), }; nctree_item sfissionUs[] = { { .curry = const_cast("²³⁰U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³²U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³³U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁴U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁵U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁶U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁸U"), .subs = NULL, .subcount = 0, }, }; nctree_item sfissions = { .curry = const_cast("spontaneously fissioning U"), .subs = sfissionUs, .subcount = sizeof(sfissionUs) / sizeof(*sfissionUs), }; nctree_item ecaptureUs[] = { { .curry = const_cast("²²⁸U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³¹U"), .subs = NULL, .subcount = 0, }, }; nctree_item ecaptures = { .curry = const_cast("electron capturing U"), .subs = ecaptureUs, .subcount = sizeof(ecaptureUs) / sizeof(*ecaptureUs), }; nctree_item cdecayUs[] = { { .curry = const_cast("²³²U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³³U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁴U"), .subs = NULL, .subcount = 0, }, { .curry = const_cast("²³⁵U"), .subs = NULL, .subcount = 0, }, }; nctree_item cdecays = { .curry = const_cast("cluster decaying U"), .subs = cdecayUs, .subcount = sizeof(cdecayUs) / sizeof(*cdecayUs), }; nctree_item radUs[] = { { .curry = const_cast("ɑ emitters"), .subs = &alphaU, .subcount = 1, }, { .curry = const_cast("β− emitters"), .subs = betaminus, .subcount = sizeof(betaminus) / sizeof(*betaminus), }, { .curry = const_cast("β−β− emitters"), .subs = &doubleminusU, .subcount = 1, }, { .curry = const_cast("ββ emitters"), .subs = &doubleU, .subcount = 1, }, { .curry = const_cast("β emitters"), .subs = &betaplus, .subcount = 1, }, { .curry = const_cast("γ emitters"), .subs = &gammas, .subcount = 1, }, { .curry = const_cast("spontaneous fissions"), .subs = &sfissions, .subcount = 1, }, { .curry = const_cast("cluster decays"), .subs = &cdecays, .subcount = 1, }, { .curry = const_cast("electron captures"), .subs = &ecaptures, .subcount = 1, }, }; nctree_item rads = { .curry = const_cast("radiating isotopes"), .subs = radUs, .subcount = sizeof(radUs) / sizeof(*radUs), }; SUBCASE("TraverseLongList") { struct ncplane_options nopts{}; nopts.rows = 7; nopts.cols = 20; auto p = ncplane_create(n_, &nopts); REQUIRE(p); struct nctree_options topts = { .items = &rads, .count = 1, .nctreecb = treecb, .indentcols = 2, .flags = 0, }; struct nctree* tree = nctree_create(p, &topts); REQUIRE(nullptr != tree); CHECK(0 == notcurses_render(nc_)); void* curry = nctree_focused(tree); void* first = curry; CHECK(nullptr != curry); void* tmpcurry; while( (tmpcurry = nctree_next(tree)) ){ if(tmpcurry == curry){ break; } curry = tmpcurry; } CHECK(nullptr != tmpcurry); while( (tmpcurry = nctree_prev(tree)) ){ if(tmpcurry == curry){ break; } curry = tmpcurry; } CHECK(nullptr != tmpcurry); CHECK(curry == first); nctree_destroy(tree); } CHECK(0 == notcurses_stop(nc_)); }