blob: f43c0eecb16b2d47541b10fc2686d15fe27af1d1 [file] [log] [blame]
Austin Schuh812d0d12021-11-04 20:16:48 -07001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#include "glass/Window.h"
6
James Kuszmaulcf324122023-01-14 14:07:17 -08007#include <imgui.h>
Austin Schuh812d0d12021-11-04 20:16:48 -07008#include <imgui_internal.h>
9#include <wpi/StringExtras.h>
10
11#include "glass/Context.h"
Austin Schuh75263e32022-02-22 18:05:32 -080012#include "glass/Storage.h"
James Kuszmaulcf324122023-01-14 14:07:17 -080013#include "glass/support/ExtraGuiWidgets.h"
Austin Schuh812d0d12021-11-04 20:16:48 -070014
15using namespace glass;
16
Austin Schuh75263e32022-02-22 18:05:32 -080017Window::Window(Storage& storage, std::string_view id,
18 Visibility defaultVisibility)
19 : m_id{id},
20 m_name{storage.GetString("name")},
21 m_defaultName{id},
22 m_visible{storage.GetBool("visible", defaultVisibility != kHide)},
23 m_enabled{storage.GetBool("enabled", defaultVisibility != kDisabled)},
24 m_defaultVisible{storage.GetValue("visible").boolDefault},
25 m_defaultEnabled{storage.GetValue("enabled").boolDefault} {}
26
Austin Schuh812d0d12021-11-04 20:16:48 -070027void Window::SetVisibility(Visibility visibility) {
Austin Schuh75263e32022-02-22 18:05:32 -080028 m_visible = visibility != kHide;
29 m_enabled = visibility != kDisabled;
30}
31
32void Window::SetDefaultVisibility(Visibility visibility) {
33 m_defaultVisible = visibility != kHide;
34 m_defaultEnabled = visibility != kDisabled;
Austin Schuh812d0d12021-11-04 20:16:48 -070035}
36
37void Window::Display() {
38 if (!m_view) {
39 return;
40 }
41 if (!m_visible || !m_enabled) {
42 PushID(m_id);
43 m_view->Hidden();
44 PopID();
45 return;
46 }
47
48 if (m_posCond != 0) {
49 ImGui::SetNextWindowPos(m_pos, m_posCond);
50 }
51 if (m_sizeCond != 0) {
52 ImGui::SetNextWindowSize(m_size, m_sizeCond);
53 }
54 if (m_setPadding) {
55 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, m_padding);
56 }
57
58 char label[128];
59 std::snprintf(label, sizeof(label), "%s###%s",
60 m_name.empty() ? m_defaultName.c_str() : m_name.c_str(),
61 m_id.c_str());
62
63 if (Begin(label, &m_visible, m_flags)) {
James Kuszmaulcf324122023-01-14 14:07:17 -080064 if (m_renamePopupEnabled || m_view->HasSettings()) {
65 bool isClicked = (ImGui::IsMouseReleased(ImGuiMouseButton_Right) &&
66 ImGui::IsItemHovered());
67 ImGuiWindow* window = ImGui::GetCurrentWindow();
68
69 bool settingsButtonClicked = false;
70 // Not docked, and window has just enough for the circles not to be
71 // touching
72 if (!ImGui::IsWindowDocked() &&
73 ImGui::GetWindowWidth() > (ImGui::GetFontSize() + 2) * 3 +
74 ImGui::GetStyle().FramePadding.x * 2) {
75 const ImGuiItemFlags itemFlagsRestore =
76 ImGui::GetCurrentContext()->CurrentItemFlags;
77
78 ImGui::GetCurrentContext()->CurrentItemFlags |=
79 ImGuiItemFlags_NoNavDefaultFocus;
80 window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
81
82 // Allow to draw outside of normal window
83 ImGui::PushClipRect(window->OuterRectClipped.Min,
84 window->OuterRectClipped.Max, false);
85
86 const ImRect titleBarRect = ImGui::GetCurrentWindow()->TitleBarRect();
87 const ImVec2 position = {titleBarRect.Max.x -
88 (ImGui::GetStyle().FramePadding.x * 3) -
89 (ImGui::GetFontSize() * 2),
90 titleBarRect.Min.y};
91 settingsButtonClicked =
92 HamburgerButton(ImGui::GetID("#SETTINGS"), position);
93
94 ImGui::PopClipRect();
95
96 ImGui::GetCurrentContext()->CurrentItemFlags = itemFlagsRestore;
97 }
98 if (settingsButtonClicked || isClicked) {
99 ImGui::OpenPopup(window->ID);
100 }
101
102 if (ImGui::BeginPopupEx(window->ID,
103 ImGuiWindowFlags_AlwaysAutoResize |
104 ImGuiWindowFlags_NoTitleBar |
105 ImGuiWindowFlags_NoSavedSettings)) {
106 if (m_renamePopupEnabled) {
107 ItemEditName(&m_name);
108 }
109 m_view->Settings();
110
111 ImGui::EndPopup();
112 }
Austin Schuh812d0d12021-11-04 20:16:48 -0700113 }
James Kuszmaulcf324122023-01-14 14:07:17 -0800114
Austin Schuh812d0d12021-11-04 20:16:48 -0700115 m_view->Display();
116 } else {
117 m_view->Hidden();
118 }
119 End();
120 if (m_setPadding) {
121 ImGui::PopStyleVar();
122 }
123}
124
125bool Window::DisplayMenuItem(const char* label) {
126 bool wasVisible = m_visible;
127 ImGui::MenuItem(
128 label ? label : (m_name.empty() ? m_id.c_str() : m_name.c_str()), nullptr,
129 &m_visible, m_enabled);
130 return !wasVisible && m_visible;
131}
132
133void Window::ScaleDefault(float scale) {
134 if ((m_posCond & ImGuiCond_FirstUseEver) != 0) {
135 m_pos.x *= scale;
136 m_pos.y *= scale;
137 }
138 if ((m_sizeCond & ImGuiCond_FirstUseEver) != 0) {
139 m_size.x *= scale;
140 m_size.y *= scale;
141 }
142}