LkEngine 0.1.2
 
Loading...
Searching...
No Matches
Widgets.h
1#pragma once
2
4#include "LkEngine/Core/LObject/Enum.h"
5#include "LkEngine/Core/Delegate/Delegate.h"
8#include "LkEngine/Renderer/UI/Property.h"
9#include "LkEngine/Renderer/UI/TreeNode.h"
10#include "LkEngine/Renderer/UI/Table.h"
11
12#include <imgui/imgui.h>
13#include <imgui/imgui_internal.h>
14
15
16namespace LkEngine::UI {
17
18 class Widget
19 {
20 public:
21 template<uint32_t BufSize = 256, float InputBarWidth = 220.0f, typename StringType>
22 static bool SearchWidget(StringType& SearchStr,
23 const char* Hint = "Search...",
24 bool* GrabFocus = nullptr)
25 {
26 ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 1.0f);
27
28 bool Modified = false;
29 bool Searching = false;
30
31 const float AreaPosX = ImGui::GetCursorPosX();
32 const float FramePaddingX = ImGui::GetStyle().FramePadding.x;
33 const float FramePaddingY = ImGui::GetStyle().FramePadding.y;
34
35 /* Set frame rounding and padding styles. */
36 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
37 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(28.0f, FramePaddingY));
38
39 ImGui::SameLine();
40 ImGui::SetNextItemAllowOverlap();
41 ImGui::SetNextItemWidth(InputBarWidth);
42
43 if constexpr (std::is_same_v<StringType, std::string>)
44 {
45 char SearchBuf[BufSize + 1]{};
46 strncpy(SearchBuf, SearchStr.c_str(), BufSize);
47
48 if (ImGui::InputText("##Search", SearchBuf, BufSize))
49 {
50 SearchStr = SearchBuf;
51 Modified = true;
52 }
53 else if (ImGui::IsItemDeactivatedAfterEdit())
54 {
55 SearchStr = SearchBuf;
56 Modified = true;
57 }
58
59 Searching = (SearchBuf[0] != '\0');
60 }
61 else
62 {
63 static_assert(std::is_same_v<decltype(&SearchStr[0]), char*>, "SearchStr parameter must be std::string& or char*");
64 if (ImGui::InputText("##Search", SearchStr, BufSize))
65 {
66 Modified = true;
67 }
68 else if (ImGui::IsItemDeactivatedAfterEdit())
69 {
70 Modified = true;
71 }
72
73 Searching = SearchStr[0] != '\0';
74 }
75
76 LK_UI_DEBUG_BOUNDING_BOX(RGBA32::NiceBlue);
77
78 const ImVec2 InputBarPosStart = ImGui::GetItemRectMin();
79 const ImVec2 InputBarPosEnd = ImGui::GetItemRectMax();
80
81 /* Size of the search text input bar. */
82 const ImVec2 InputBarSize(
83 InputBarPosEnd.x - InputBarPosStart.x,
84 InputBarPosEnd.y - InputBarPosStart.y
85 );
86
87 /* Handle focus grabbing. */
88 if (GrabFocus && *GrabFocus)
89 {
90 if (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows)
91 && !ImGui::IsAnyItemActive()
92 && !ImGui::IsMouseClicked(0))
93 {
94 ImGui::SetKeyboardFocusHere(-1);
95 }
96
97 if (ImGui::IsItemFocused())
98 {
99 *GrabFocus = false;
100 LK_CORE_DEBUG_TAG("SearchWidget", "Setting GrabFocus to false");
101 }
102 }
103
104 /* Draw activity outline. */
105 const ImRect ItemRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
106 ImGui::RenderNavCursor(ItemRect, ImGui::GetID("##Search"));
107
108 ImGui::SameLine(AreaPosX + 5.0f);
109
110 /***********************************
111 * Search and clear icon.
112 ***********************************/
113 ImGui::BeginGroup();
114 const ImVec2 IconSize(ImGui::GetTextLineHeight(), ImGui::GetTextLineHeight());
115 LK_CORE_ASSERT((IconSize.x > 0) && (IconSize.y > 0));
116
117 /* Search Icon. */
118 {
119 const float IconYOffset = FramePaddingY - 3.0f;
120 ImGui::SetCursorPosY(ImGui::GetCursorPosY() + IconYOffset);
121 UI::Image(
122 FEditorResources::SearchIcon, /* Texture ID. */
123 IconSize, /* Image Size. */
124 ImVec2(0.0f, 0.0f), /* UV0. */
125 ImVec2(1.0f, 1.0f), /* UV1. */
126 ImVec4(1.0f, 1.0f, 1.0f, 0.20f), /* Tint Color. */
127 ImVec4(0.0f, 0.0f, 0.0f, 0.0f) /* Border Color. */
128 );
129 ImGui::SetCursorPosY(ImGui::GetCursorPosY() - IconYOffset);
130
131 /* Display the hint text if not searching. */
132 if (!Searching)
133 {
134 ImGui::SameLine();
135
136 ImGui::SetCursorPosY(ImGui::GetCursorPosY() - FramePaddingY + 2.0f);
137 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.50f, 0.50f, 0.50f, 1.0f));
138 ImGui::TextUnformatted(Hint);
139 ImGui::PopStyleColor();
140 ImGui::SetCursorPosY(ImGui::GetCursorPosY() + FramePaddingY - 2.0f);
141 }
142 }
143
144 /* Draw the clear button if searching. */
145 if (Searching)
146 {
147 static constexpr float SpacingX = 4.0f;
148 const float LineHeight = ImGui::GetItemRectSize().y - (FramePaddingY / 2.0f);
149 ImGui::SameLine(0.0f, InputBarSize.x - (2.0f * IconSize.x) - FramePaddingX - SpacingX);
150 ImGui::SetCursorPosY(ImGui::GetCursorPosY() + FramePaddingY);
151 if (ImGui::InvisibleButton("##Clear", ImVec2(LineHeight, LineHeight)))
152 {
153 if constexpr (std::is_same_v<StringType, std::string>)
154 {
155 SearchStr.clear();
156 }
157 else
158 {
159 std::memset(SearchStr, 0, BufSize);
160 }
161
162 Modified = true;
163 }
164 ImGui::SetCursorPosY(ImGui::GetCursorPosY() - FramePaddingY);
165
166 /* Change mouse cursor to arrow if hovering over clear button. */
167 if (ImGui::IsItemHovered())
168 {
169 ImGui::SetMouseCursor(ImGuiMouseCursor_Arrow);
170 UI::SetTooltip(LK_FMT_LIB::format("StartPos: ({}, {}) EndPos: ({}, {}) InputBarSize: ({}, {})",
171 InputBarPosStart.x, InputBarPosStart.y,
172 InputBarPosEnd.x, InputBarPosEnd.y,
173 InputBarSize.x, InputBarSize.y));
174 }
175
176 /* Clear Icon. */
177 UI::DrawButtonImage(
178 FEditorResources::ClearIcon,
179 IM_COL32(150, 150, 150, 200),
180 IM_COL32(170, 170, 170, 255),
181 IM_COL32(160, 160, 160, 150),
182 UI::RectExpanded(UI::GetItemRect(), -1.0f, -1.0f)
183 );
184 }
185
186 LK_UI_DEBUG_BOUNDING_BOX(RGBA32::BrightGreen);
187
188 /* Set the cursor to the end of the search bar (text input). */
189 ImGui::SetCursorScreenPos(ImVec2(InputBarPosEnd.x, ImGui::GetCursorScreenPos().y));
190
191 ImGui::EndGroup();
192
193 /* Restore cursor position and styles. */
194 ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 1.0f);
195 ImGui::PopStyleVar(2);
196
197 return Modified;
198 }
199
200 static bool OptionsButton();
201
202 };
203
204}
Core header.
Editor core.
Core UI.
Definition Widgets.h:19