blob: 32c7a2104da7eb910acab63660278dd49b2e2603 [file] [log] [blame]
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "glass/Window.h"
#include <imgui.h>
#include <imgui_internal.h>
#include <wpi/StringExtras.h>
#include "glass/Context.h"
#include "glass/Storage.h"
#include "glass/support/ExtraGuiWidgets.h"
using namespace glass;
Window::Window(Storage& storage, std::string_view id,
Visibility defaultVisibility)
: m_id{id},
m_name{storage.GetString("name")},
m_defaultName{id},
m_visible{storage.GetBool("visible", defaultVisibility != kHide)},
m_enabled{storage.GetBool("enabled", defaultVisibility != kDisabled)},
m_defaultVisible{storage.GetValue("visible").boolDefault},
m_defaultEnabled{storage.GetValue("enabled").boolDefault} {}
void Window::SetVisibility(Visibility visibility) {
m_visible = visibility != kHide;
m_enabled = visibility != kDisabled;
}
void Window::SetDefaultVisibility(Visibility visibility) {
m_defaultVisible = visibility != kHide;
m_defaultEnabled = visibility != kDisabled;
}
void Window::Display() {
if (!m_view) {
return;
}
if (!m_visible || !m_enabled) {
PushID(m_id);
m_view->Hidden();
PopID();
return;
}
if (m_posCond != 0) {
ImGui::SetNextWindowPos(m_pos, m_posCond);
}
if (m_sizeCond != 0) {
ImGui::SetNextWindowSize(m_size, m_sizeCond);
}
if (m_setPadding) {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, m_padding);
}
char label[128];
if (m_name.empty()) {
wpi::format_to_n_c_str(label, sizeof(label), "{}###{}", m_defaultName,
m_id);
} else {
wpi::format_to_n_c_str(label, sizeof(label), "{}###{}", m_name, m_id);
}
if (Begin(label, &m_visible, m_flags)) {
if (m_renamePopupEnabled || m_view->HasSettings()) {
bool isClicked = (ImGui::IsMouseReleased(ImGuiMouseButton_Right) &&
ImGui::IsItemHovered());
ImGuiWindow* window = ImGui::GetCurrentWindow();
bool settingsButtonClicked = false;
// Not docked, and window has just enough for the circles not to be
// touching
if (!ImGui::IsWindowDocked() &&
ImGui::GetWindowWidth() > (ImGui::GetFontSize() + 2) * 3 +
ImGui::GetStyle().FramePadding.x * 2) {
const ImGuiItemFlags itemFlagsRestore =
ImGui::GetCurrentContext()->CurrentItemFlags;
ImGui::GetCurrentContext()->CurrentItemFlags |=
ImGuiItemFlags_NoNavDefaultFocus;
window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
// Allow to draw outside of normal window
ImGui::PushClipRect(window->OuterRectClipped.Min,
window->OuterRectClipped.Max, false);
const ImRect titleBarRect = ImGui::GetCurrentWindow()->TitleBarRect();
const ImVec2 position = {titleBarRect.Max.x -
(ImGui::GetStyle().FramePadding.x * 3) -
(ImGui::GetFontSize() * 2),
titleBarRect.Min.y};
settingsButtonClicked =
HamburgerButton(ImGui::GetID("#SETTINGS"), position);
ImGui::PopClipRect();
ImGui::GetCurrentContext()->CurrentItemFlags = itemFlagsRestore;
}
if (settingsButtonClicked || isClicked) {
ImGui::OpenPopup(window->ID);
}
if (ImGui::BeginPopupEx(window->ID,
ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_NoTitleBar |
ImGuiWindowFlags_NoSavedSettings)) {
if (m_renamePopupEnabled) {
ItemEditName(&m_name);
}
m_view->Settings();
ImGui::EndPopup();
}
}
m_view->Display();
} else {
m_view->Hidden();
}
End();
if (m_setPadding) {
ImGui::PopStyleVar();
}
}
bool Window::DisplayMenuItem(const char* label) {
bool wasVisible = m_visible;
ImGui::MenuItem(
label ? label : (m_name.empty() ? m_id.c_str() : m_name.c_str()), nullptr,
&m_visible, m_enabled);
return !wasVisible && m_visible;
}
void Window::ScaleDefault(float scale) {
if ((m_posCond & ImGuiCond_FirstUseEver) != 0) {
m_pos.x *= scale;
m_pos.y *= scale;
}
if ((m_sizeCond & ImGuiCond_FirstUseEver) != 0) {
m_size.x *= scale;
m_size.y *= scale;
}
}