|
@@ -827,7 +827,7 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
|
|
|
ImU32 col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered);
|
|
|
ImVec2 center = bb.GetCenter();
|
|
|
if (hovered)
|
|
|
- window->DrawList->AddCircleFilled(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col, 12);
|
|
|
+ window->DrawList->AddCircleFilled(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col);
|
|
|
|
|
|
float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
|
|
|
ImU32 cross_col = GetColorU32(ImGuiCol_Text);
|
|
@@ -854,7 +854,7 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos, ImGuiDockNode* dock_no
|
|
|
ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
|
|
ImU32 text_col = GetColorU32(ImGuiCol_Text);
|
|
|
if (hovered || held)
|
|
|
- window->DrawList->AddCircleFilled(bb.GetCenter() + ImVec2(0,-0.5f), g.FontSize * 0.5f + 1.0f, bg_col, 12);
|
|
|
+ window->DrawList->AddCircleFilled(bb.GetCenter() + ImVec2(0,-0.5f), g.FontSize * 0.5f + 1.0f, bg_col);
|
|
|
|
|
|
if (dock_node)
|
|
|
RenderArrowDockMenu(window->DrawList, bb.Min + g.Style.FramePadding, g.FontSize, text_col);
|
|
@@ -1239,17 +1239,18 @@ bool ImGui::RadioButton(const char* label, bool active)
|
|
|
MarkItemEdited(id);
|
|
|
|
|
|
RenderNavHighlight(total_bb, id);
|
|
|
- window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16);
|
|
|
+ const int num_segment = window->DrawList->_CalcCircleAutoSegmentCount(radius);
|
|
|
+ window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), num_segment);
|
|
|
if (active)
|
|
|
{
|
|
|
const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
|
|
|
- window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark), 16);
|
|
|
+ window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark));
|
|
|
}
|
|
|
|
|
|
if (style.FrameBorderSize > 0.0f)
|
|
|
{
|
|
|
- window->DrawList->AddCircle(center + ImVec2(1, 1), radius, GetColorU32(ImGuiCol_BorderShadow), 16, style.FrameBorderSize);
|
|
|
- window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16, style.FrameBorderSize);
|
|
|
+ window->DrawList->AddCircle(center + ImVec2(1, 1), radius, GetColorU32(ImGuiCol_BorderShadow), num_segment, style.FrameBorderSize);
|
|
|
+ window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), num_segment, style.FrameBorderSize);
|
|
|
}
|
|
|
|
|
|
ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y);
|
|
@@ -3705,10 +3706,34 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* ob
|
|
|
r->num_chars = (int)(text_remaining - (text + line_start_idx));
|
|
|
}
|
|
|
|
|
|
-// When ImGuiInputTextFlags_Password is set, we don't want actions such as CTRL+Arrow to leak the fact that underlying data are blanks or separators.
|
|
|
-static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r'; }
|
|
|
-static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (is_separator(obj->TextW[idx - 1]) && !is_separator(obj->TextW[idx]) ) : 1; }
|
|
|
-static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx])) : 1; }
|
|
|
+static bool is_separator(unsigned int c)
|
|
|
+{
|
|
|
+ return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r' || c=='.' || c=='!';
|
|
|
+}
|
|
|
+
|
|
|
+static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx)
|
|
|
+{
|
|
|
+ // When ImGuiInputTextFlags_Password is set, we don't want actions such as CTRL+Arrow to leak the fact that underlying data are blanks or separators.
|
|
|
+ if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ bool prev_white = ImCharIsBlankW(obj->TextW[idx - 1]);
|
|
|
+ bool prev_separ = is_separator(obj->TextW[idx - 1]);
|
|
|
+ bool curr_white = ImCharIsBlankW(obj->TextW[idx]);
|
|
|
+ bool curr_separ = is_separator(obj->TextW[idx]);
|
|
|
+ return ((prev_white || prev_separ) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ);
|
|
|
+}
|
|
|
+static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)
|
|
|
+{
|
|
|
+ if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ bool prev_white = ImCharIsBlankW(obj->TextW[idx]);
|
|
|
+ bool prev_separ = is_separator(obj->TextW[idx]);
|
|
|
+ bool curr_white = ImCharIsBlankW(obj->TextW[idx - 1]);
|
|
|
+ bool curr_separ = is_separator(obj->TextW[idx - 1]);
|
|
|
+ return ((prev_white) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ);
|
|
|
+}
|
|
|
static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
|
|
|
static int STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
|
|
|
static int STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
|
|
@@ -5621,7 +5646,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
|
|
float sin_hue_angle = ImSin(H * 2.0f * IM_PI);
|
|
|
ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f);
|
|
|
float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f;
|
|
|
- int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32);
|
|
|
+ int hue_cursor_segments = draw_list->_CalcCircleAutoSegmentCount(hue_cursor_rad); // Lock segment count so the +1 one matches others.
|
|
|
draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments);
|
|
|
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad + 1, col_midgrey, hue_cursor_segments);
|
|
|
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments);
|
|
@@ -5631,13 +5656,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
|
|
ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle);
|
|
|
ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle);
|
|
|
ImVec2 uv_white = GetFontTexUvWhitePixel();
|
|
|
- draw_list->PrimReserve(6, 6);
|
|
|
+ draw_list->PrimReserve(3, 3);
|
|
|
draw_list->PrimVtx(tra, uv_white, hue_color32);
|
|
|
- draw_list->PrimVtx(trb, uv_white, hue_color32);
|
|
|
- draw_list->PrimVtx(trc, uv_white, col_white);
|
|
|
- draw_list->PrimVtx(tra, uv_white, 0);
|
|
|
draw_list->PrimVtx(trb, uv_white, col_black);
|
|
|
- draw_list->PrimVtx(trc, uv_white, 0);
|
|
|
+ draw_list->PrimVtx(trc, uv_white, col_white);
|
|
|
draw_list->AddTriangle(tra, trb, trc, col_midgrey, 1.5f);
|
|
|
sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V));
|
|
|
}
|
|
@@ -5660,9 +5682,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
|
|
|
|
|
// Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range)
|
|
|
float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f;
|
|
|
- draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, 12);
|
|
|
- draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad + 1, col_midgrey, 12);
|
|
|
- draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, 12);
|
|
|
+ int sv_cursor_segments = draw_list->_CalcCircleAutoSegmentCount(sv_cursor_rad); // Lock segment count so the +1 one matches others.
|
|
|
+ draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, sv_cursor_segments);
|
|
|
+ draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad + 1, col_midgrey, sv_cursor_segments);
|
|
|
+ draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, sv_cursor_segments);
|
|
|
|
|
|
// Render alpha bar
|
|
|
if (alpha_bar)
|
|
@@ -7616,6 +7639,12 @@ void ImGui::EndTabBar()
|
|
|
g.CurrentTabBar = g.CurrentTabBarStack.empty() ? NULL : GetTabBarFromTabBarRef(g.CurrentTabBarStack.back());
|
|
|
}
|
|
|
|
|
|
+// Scrolling happens only in the central section (leading/trailing sections are not scrolling)
|
|
|
+static float TabBarCalcScrollableWidth(ImGuiTabBar* tab_bar, ImGuiTabBarSection* sections)
|
|
|
+{
|
|
|
+ return tab_bar->BarRect.GetWidth() - sections[0].Width - sections[2].Width - sections[1].Spacing;
|
|
|
+}
|
|
|
+
|
|
|
// This is called only once a frame before by the first call to ItemTab()
|
|
|
// The reason we're not calling it in BeginTabBar() is to leave a chance to the user to call the SetTabItemClosed() functions.
|
|
|
static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
|
@@ -7822,9 +7851,23 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
|
|
if (g.NavWindowingTarget != NULL && g.NavWindowingTarget->DockNode && g.NavWindowingTarget->DockNode->TabBar == tab_bar)
|
|
|
tab_bar->VisibleTabId = scroll_to_tab_id = g.NavWindowingTarget->TabId;
|
|
|
|
|
|
- // Update scrolling
|
|
|
+ // Apply request requests
|
|
|
if (scroll_to_tab_id != 0)
|
|
|
TabBarScrollToTab(tab_bar, scroll_to_tab_id, sections);
|
|
|
+ else if ((tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll) && IsMouseHoveringRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, true) && IsWindowContentHoverable(g.CurrentWindow))
|
|
|
+ {
|
|
|
+ const float wheel = g.IO.MouseWheelRequestAxisSwap ? g.IO.MouseWheel : g.IO.MouseWheelH;
|
|
|
+ const ImGuiKey wheel_key = g.IO.MouseWheelRequestAxisSwap ? ImGuiKey_MouseWheelY : ImGuiKey_MouseWheelX;
|
|
|
+ if (TestKeyOwner(wheel_key, tab_bar->ID) && wheel != 0.0f)
|
|
|
+ {
|
|
|
+ const float scroll_step = wheel * TabBarCalcScrollableWidth(tab_bar, sections) / 3.0f;
|
|
|
+ tab_bar->ScrollingTargetDistToVisibility = 0.0f;
|
|
|
+ tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget - scroll_step);
|
|
|
+ }
|
|
|
+ SetKeyOwner(wheel_key, tab_bar->ID);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Update scrolling
|
|
|
tab_bar->ScrollingAnim = TabBarScrollClamp(tab_bar, tab_bar->ScrollingAnim);
|
|
|
tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget);
|
|
|
if (tab_bar->ScrollingAnim != tab_bar->ScrollingTarget)
|
|
@@ -7998,8 +8041,7 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
|
|
|
int order = TabBarGetTabOrder(tab_bar, tab);
|
|
|
|
|
|
// Scrolling happens only in the central section (leading/trailing sections are not scrolling)
|
|
|
- // FIXME: This is all confusing.
|
|
|
- float scrollable_width = tab_bar->BarRect.GetWidth() - sections[0].Width - sections[2].Width - sections[1].Spacing;
|
|
|
+ float scrollable_width = TabBarCalcScrollableWidth(tab_bar, sections);
|
|
|
|
|
|
// We make all tabs positions all relative Sections[0].Width to make code simpler
|
|
|
float tab_x1 = tab->Offset - sections[0].Width + (order > sections[0].TabCount - 1 ? -margin : 0.0f);
|