Render text label (with custom clipping) + Unsaved Document marker + Close Button logic We tend to lock style.FramePadding for a given tab-bar, hence the 'frame_padding' parameter.
| 8564 | // Render text label (with custom clipping) + Unsaved Document marker + Close Button logic |
| 8565 | // We tend to lock style.FramePadding for a given tab-bar, hence the 'frame_padding' parameter. |
| 8566 | void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped) |
| 8567 | { |
| 8568 | ImGuiContext& g = *GImGui; |
| 8569 | ImVec2 label_size = CalcTextSize(label, NULL, true); |
| 8570 | |
| 8571 | if (out_just_closed) |
| 8572 | *out_just_closed = false; |
| 8573 | if (out_text_clipped) |
| 8574 | *out_text_clipped = false; |
| 8575 | |
| 8576 | if (bb.GetWidth() <= 1.0f) |
| 8577 | return; |
| 8578 | |
| 8579 | // In Style V2 we'll have full override of all colors per state (e.g. focused, selected) |
| 8580 | // But right now if you want to alter text color of tabs this is what you need to do. |
| 8581 | #if 0 |
| 8582 | const float backup_alpha = g.Style.Alpha; |
| 8583 | if (!is_contents_visible) |
| 8584 | g.Style.Alpha *= 0.7f; |
| 8585 | #endif |
| 8586 | |
| 8587 | // Render text label (with clipping + alpha gradient) + unsaved marker |
| 8588 | ImRect text_pixel_clip_bb(bb.Min.x + frame_padding.x, bb.Min.y + frame_padding.y, bb.Max.x - frame_padding.x, bb.Max.y); |
| 8589 | ImRect text_ellipsis_clip_bb = text_pixel_clip_bb; |
| 8590 | |
| 8591 | // Return clipped state ignoring the close button |
| 8592 | if (out_text_clipped) |
| 8593 | { |
| 8594 | *out_text_clipped = (text_ellipsis_clip_bb.Min.x + label_size.x) > text_pixel_clip_bb.Max.x; |
| 8595 | //draw_list->AddCircle(text_ellipsis_clip_bb.Min, 3.0f, *out_text_clipped ? IM_COL32(255, 0, 0, 255) : IM_COL32(0, 255, 0, 255)); |
| 8596 | } |
| 8597 | |
| 8598 | const float button_sz = g.FontSize; |
| 8599 | const ImVec2 button_pos(ImMax(bb.Min.x, bb.Max.x - frame_padding.x - button_sz), bb.Min.y + frame_padding.y); |
| 8600 | |
| 8601 | // Close Button & Unsaved Marker |
| 8602 | // We are relying on a subtle and confusing distinction between 'hovered' and 'g.HoveredId' which happens because we are using ImGuiButtonFlags_AllowOverlapMode + SetItemAllowOverlap() |
| 8603 | // 'hovered' will be true when hovering the Tab but NOT when hovering the close button |
| 8604 | // 'g.HoveredId==id' will be true when hovering the Tab including when hovering the close button |
| 8605 | // 'g.ActiveId==close_button_id' will be true when we are holding on the close button, in which case both hovered booleans are false |
| 8606 | bool close_button_pressed = false; |
| 8607 | bool close_button_visible = false; |
| 8608 | if (close_button_id != 0) |
| 8609 | if (is_contents_visible || bb.GetWidth() >= ImMax(button_sz, g.Style.TabMinWidthForCloseButton)) |
| 8610 | if (g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == tab_id || g.ActiveId == close_button_id) |
| 8611 | close_button_visible = true; |
| 8612 | bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x); |
| 8613 | |
| 8614 | if (close_button_visible) |
| 8615 | { |
| 8616 | ImGuiLastItemData last_item_backup = g.LastItemData; |
| 8617 | if (CloseButton(close_button_id, button_pos)) |
| 8618 | close_button_pressed = true; |
| 8619 | g.LastItemData = last_item_backup; |
| 8620 | |
| 8621 | // Close with middle mouse button |
| 8622 | if (!(flags & ImGuiTabItemFlags_NoCloseWithMiddleMouseButton) && IsMouseClicked(2)) |
| 8623 | close_button_pressed = true; |