| 3152 | "Future versions will try to simplify and formalize some of this."); |
| 3153 | |
| 3154 | struct ExampleTreeFuncs |
| 3155 | { |
| 3156 | static void DrawNode(ExampleTreeNode* node, ImGuiSelectionBasicStorage* selection) |
| 3157 | { |
| 3158 | ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; |
| 3159 | tree_node_flags |= ImGuiTreeNodeFlags_NavLeftJumpsToParent; // Enable pressing left to jump to parent |
| 3160 | if (node->Childs.Size == 0) |
| 3161 | tree_node_flags |= ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_Leaf; |
| 3162 | if (selection->Contains((ImGuiID)node->UID)) |
| 3163 | tree_node_flags |= ImGuiTreeNodeFlags_Selected; |
| 3164 | |
| 3165 | // Using SetNextItemStorageID() to specify storage id, so we can easily peek into |
| 3166 | // the storage holding open/close stage, using our TreeNodeGetOpen/TreeNodeSetOpen() functions. |
| 3167 | ImGui::SetNextItemSelectionUserData((ImGuiSelectionUserData)(intptr_t)node); |
| 3168 | ImGui::SetNextItemStorageID((ImGuiID)node->UID); |
| 3169 | if (ImGui::TreeNodeEx(node->Name, tree_node_flags)) |
| 3170 | { |
| 3171 | for (ExampleTreeNode* child : node->Childs) |
| 3172 | DrawNode(child, selection); |
| 3173 | ImGui::TreePop(); |
| 3174 | } |
| 3175 | else if (ImGui::IsItemToggledOpen()) |
| 3176 | { |
| 3177 | TreeCloseAndUnselectChildNodes(node, selection); |
| 3178 | } |
| 3179 | } |
| 3180 | |
| 3181 | // When closing a node: 1) close and unselect all child nodes, 2) select parent if any child was selected. |
| 3182 | // FIXME: This is currently handled by user logic but I'm hoping to eventually provide tree node |
| 3183 | // features to do this automatically, e.g. a ImGuiTreeNodeFlags_AutoCloseChildNodes etc. |
| 3184 | static int TreeCloseAndUnselectChildNodes(ExampleTreeNode* node, ImGuiSelectionBasicStorage* selection, int depth = 0) |
| 3185 | { |
| 3186 | // Recursive close (the test for depth == 0 is because we call this on a node that was just closed!) |
| 3187 | int unselected_count = selection->Contains((ImGuiID)node->UID) ? 1 : 0; |
| 3188 | if (depth == 0 || ImGui::TreeNodeGetOpen((ImGuiID)node->UID)) |
| 3189 | { |
| 3190 | for (ExampleTreeNode* child : node->Childs) |
| 3191 | unselected_count += TreeCloseAndUnselectChildNodes(child, selection, depth + 1); |
| 3192 | ImGui::TreeNodeSetOpen((ImGuiID)node->UID, false); |
| 3193 | } |
| 3194 | |
| 3195 | // Select root node if any of its child was selected, otherwise unselect |
| 3196 | selection->SetItemSelected((ImGuiID)node->UID, (depth == 0 && unselected_count > 0)); |
| 3197 | return unselected_count; |
| 3198 | } |
| 3199 | |
| 3200 | // Apply multi-selection requests |
| 3201 | static void ApplySelectionRequests(ImGuiMultiSelectIO* ms_io, ExampleTreeNode* tree, ImGuiSelectionBasicStorage* selection) |
| 3202 | { |
| 3203 | for (ImGuiSelectionRequest& req : ms_io->Requests) |
| 3204 | { |
| 3205 | if (req.Type == ImGuiSelectionRequestType_SetAll) |
| 3206 | { |
| 3207 | if (req.Selected) |
| 3208 | TreeSetAllInOpenNodes(tree, selection, req.Selected); |
| 3209 | else |
| 3210 | selection->Clear(); |
| 3211 | } |
nothing calls this directly
no outgoing calls
no test coverage detected