| 10082 | } |
| 10083 | |
| 10084 | void ImGui::EndGroup() |
| 10085 | { |
| 10086 | ImGuiContext& g = *GImGui; |
| 10087 | ImGuiWindow* window = g.CurrentWindow; |
| 10088 | IM_ASSERT(g.GroupStack.Size > 0); // Mismatched BeginGroup()/EndGroup() calls |
| 10089 | |
| 10090 | ImGuiGroupData& group_data = g.GroupStack.back(); |
| 10091 | IM_ASSERT(group_data.WindowID == window->ID); // EndGroup() in wrong window? |
| 10092 | |
| 10093 | if (window->DC.IsSetPos) |
| 10094 | ErrorCheckUsingSetCursorPosToExtendParentBoundaries(); |
| 10095 | |
| 10096 | ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos)); |
| 10097 | |
| 10098 | window->DC.CursorPos = group_data.BackupCursorPos; |
| 10099 | window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos); |
| 10100 | window->DC.Indent = group_data.BackupIndent; |
| 10101 | window->DC.GroupOffset = group_data.BackupGroupOffset; |
| 10102 | window->DC.CurrLineSize = group_data.BackupCurrLineSize; |
| 10103 | window->DC.CurrLineTextBaseOffset = group_data.BackupCurrLineTextBaseOffset; |
| 10104 | if (g.LogEnabled) |
| 10105 | g.LogLinePosY = -FLT_MAX; // To enforce a carriage return |
| 10106 | |
| 10107 | if (!group_data.EmitItem) |
| 10108 | { |
| 10109 | g.GroupStack.pop_back(); |
| 10110 | return; |
| 10111 | } |
| 10112 | |
| 10113 | window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now. |
| 10114 | ItemSize(group_bb.GetSize()); |
| 10115 | ItemAdd(group_bb, 0, NULL, ImGuiItemFlags_NoTabStop); |
| 10116 | |
| 10117 | // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group. |
| 10118 | // It would be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but would put a little more burden on individual widgets. |
| 10119 | // Also if you grep for LastItemId you'll notice it is only used in that context. |
| 10120 | // (The two tests not the same because ActiveIdIsAlive is an ID itself, in order to be able to handle ActiveId being overwritten during the frame.) |
| 10121 | const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId; |
| 10122 | const bool group_contains_prev_active_id = (group_data.BackupActiveIdPreviousFrameIsAlive == false) && (g.ActiveIdPreviousFrameIsAlive == true); |
| 10123 | if (group_contains_curr_active_id) |
| 10124 | g.LastItemData.ID = g.ActiveId; |
| 10125 | else if (group_contains_prev_active_id) |
| 10126 | g.LastItemData.ID = g.ActiveIdPreviousFrame; |
| 10127 | g.LastItemData.Rect = group_bb; |
| 10128 | |
| 10129 | // Forward Hovered flag |
| 10130 | const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive == false) && g.HoveredId != 0; |
| 10131 | if (group_contains_curr_hovered_id) |
| 10132 | g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow; |
| 10133 | |
| 10134 | // Forward Edited flag |
| 10135 | if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame) |
| 10136 | g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited; |
| 10137 | |
| 10138 | // Forward Deactivated flag |
| 10139 | g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDeactivated; |
| 10140 | if (group_contains_prev_active_id && g.ActiveId != g.ActiveIdPreviousFrame) |
| 10141 | g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Deactivated; |