cabana: center speed dropdown label, add divider after loop button (#38785)

This commit is contained in:
Trey Moen
2026-09-05 15:34:00 -07:00
committed by GitHub
parent a4f7c50d2a
commit cb0da74b41
3 changed files with 31 additions and 24 deletions
+10 -7
View File
@@ -442,18 +442,21 @@ bool menuButton(const char *id, const std::string &text, const char *popup_id, b
// on press; a press while it is open toggles it closed (imgui closes the popup at the end of the frame of
// a click outside it, so only open when it is not already open)
if (bold) pushBoldFont();
ImGui::PushStyleColor(ImGuiCol_Button, popup_open ? style.Colors[ImGuiCol_ButtonActive] : ImVec4(0, 0, 0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f));
const bool clicked = ImGui::ButtonEx((text + "###" + id).c_str(), ImVec2(width, 0.0f), ImGuiButtonFlags_PressedOnClick);
ImGui::PopStyleVar(2);
ImGui::PopStyleColor();
const float text_width = ImGui::CalcTextSize(text.c_str(), nullptr, true).x;
const float ascent = ImGui::GetFontBaked()->Ascent;
// the text and the arrow are centered as a group in the button
const float padding_x = std::max(style.FramePadding.x, (width - (text_width + MENU_ARROW_SPACING + MENU_ARROW_SIZE)) * 0.5f);
ImGui::PushStyleColor(ImGuiCol_Button, popup_open ? style.Colors[ImGuiCol_ButtonActive] : ImVec4(0, 0, 0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(padding_x, style.FramePadding.y));
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f));
const bool clicked = ImGui::ButtonEx((text + "###" + id).c_str(), ImVec2(width, 0.0f), ImGuiButtonFlags_PressedOnClick);
ImGui::PopStyleVar(3);
ImGui::PopStyleColor();
if (bold) popBoldFont();
// a 6 px arrow right after the text, sitting on the text baseline
const ImVec2 min = ImGui::GetItemRectMin();
const float x = min.x + style.FramePadding.x + text_width + MENU_ARROW_SPACING;
const float x = min.x + padding_x + text_width + MENU_ARROW_SPACING;
const float baseline = min.y + style.FramePadding.y + ascent;
ImGui::GetWindowDrawList()->AddTriangleFilled(ImVec2(x, baseline - MENU_ARROW_SIZE * 0.5f),
ImVec2(x + MENU_ARROW_SIZE, baseline - MENU_ARROW_SIZE * 0.5f),
+1 -1
View File
@@ -182,7 +182,7 @@ float toolbarWidth(const std::vector<ToolbarItem> &items, size_t spacer_index);
void drawToolbar(const std::vector<ToolbarItem> &items, size_t spacer_index);
// an auto-raise button that opens `popup_id` below itself, with a dropdown arrow after the text. width 0:
// sized to the text, otherwise the arrow sits at the right edge
// sized to the text, otherwise the text and the arrow are centered in the button
float menuButtonWidth(const std::string &text, bool bold = false);
bool menuButton(const char *id, const std::string &text, const char *popup_id, bool bold = false, float width = 0.0f);
@@ -143,7 +143,7 @@ static float toolbarHeight() { return TOOLBAR_MARGIN_Y + ImGui::GetFrameHeight()
void VideoWidget::drawPlaybackController() {
beginToolbar();
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + TOOLBAR_MARGIN_Y);
const float speed_width = menuButtonWidth("0.05x ", true);
const float speed_width = menuButtonWidth("0.05x", true);
const char *play_icon = can->isPaused() ? icon::PLAY : icon::PAUSE;
const char *play_tooltip = can->isPaused() ? "Play" : "Pause";
@@ -186,21 +186,25 @@ void VideoWidget::drawPlaybackController() {
}
// the expanding spacer: the items after it are right aligned as long as everything fits
const size_t spacer_index = items.size();
if (!can->liveStreaming()) {
items.push_back({toolbarButtonWidth(loop_icon), [&]() { if (toolButton("loop", loop_icon, "Loop playback")) loopPlaybackClicked(); },
"Loop playback", [this]() { loopPlaybackClicked(); }});
}
items.push_back({speed_width, [&]() { drawSpeedDropdown(speed_width); }});
if (!can->liveStreaming()) {
ToolbarItem separator{TOOLBAR_SEPARATOR_EXTENT, []() {
auto separator = []() {
ToolbarItem item{TOOLBAR_SEPARATOR_EXTENT, []() {
// a 1 px separator line centered in TOOLBAR_SEPARATOR_EXTENT, inset from the top and bottom
const ImVec2 min = ImGui::GetCursorScreenPos();
ImGui::Dummy(ImVec2(TOOLBAR_SEPARATOR_EXTENT, ImGui::GetFrameHeight()));
const float x = std::floor(min.x + TOOLBAR_SEPARATOR_EXTENT * 0.5f);
ImGui::GetWindowDrawList()->AddLine(ImVec2(x, min.y + 4.0f), ImVec2(x, min.y + ImGui::GetFrameHeight() - 4.0f), ImGui::GetColorU32(ImGuiCol_Separator));
}};
separator.in_menu = false;
items.push_back(std::move(separator));
item.in_menu = false;
return item;
};
if (!can->liveStreaming()) {
items.push_back({toolbarButtonWidth(loop_icon), [&]() { if (toolButton("loop", loop_icon, "Loop playback")) loopPlaybackClicked(); },
"Loop playback", [this]() { loopPlaybackClicked(); }});
items.push_back(separator());
}
items.push_back({speed_width, [&]() { drawSpeedDropdown(speed_width); }});
if (!can->liveStreaming()) {
items.push_back(separator());
items.push_back({toolbarButtonWidth(icon::INFO_CIRCLE),
[&]() { if (toolButton("route_info", icon::INFO_CIRCLE, "View route details")) showRouteInfo(); },
"View route details", [this]() { showRouteInfo(); }});
@@ -221,16 +225,16 @@ void VideoWidget::toggleTimeDisplay() {
settings.absolute_time = !settings.absolute_time;
}
static std::string speedText(float speed, const char *suffix) {
static std::string speedText(float speed) {
char buf[32];
snprintf(buf, sizeof(buf), "%gx%s", speed, suffix);
snprintf(buf, sizeof(buf), "%gx", speed);
return buf;
}
void VideoWidget::createSpeedDropdown() {
speed_index_ = NORMAL_SPEED_INDEX;
can->setSpeed(speeds[speed_index_]);
speed_text_ = speedText(speeds[speed_index_], " ");
speed_text_ = speedText(speeds[speed_index_]);
}
void VideoWidget::drawSpeedDropdown(float width) {
@@ -247,14 +251,14 @@ void VideoWidget::drawSpeedMenuItems() {
const float indent = ImGui::GetFontSize();
float label_width = 0;
for (int i = 0; i < (int)std::size(speeds); ++i) {
label_width = std::max(label_width, ImGui::CalcTextSize(speedText(speeds[i], "").c_str()).x);
label_width = std::max(label_width, ImGui::CalcTextSize(speedText(speeds[i]).c_str()).x);
}
for (int i = 0; i < (int)std::size(speeds); ++i) {
const float speed = speeds[i];
if (radioMenuItem(speedText(speed, "").c_str(), speed_index_ == i, indent + label_width + indent)) {
if (radioMenuItem(speedText(speed).c_str(), speed_index_ == i, indent + label_width + indent)) {
speed_index_ = i;
can->setSpeed(speed);
speed_text_ = speedText(speed, " ");
speed_text_ = speedText(speed);
}
}
}