Added DragFloat(), DragInt() work in progress #180

This commit is contained in:
ocornut 2015-04-03 14:07:52 +01:00
parent d25578efd8
commit 1247ce251f
2 changed files with 161 additions and 14 deletions

163
imgui.cpp
View File

@ -135,6 +135,7 @@
Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix.
Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
- 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive.
- 2015/03/17 (1.36) - renamed GetItemRectMin()/GetItemRectMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function (will obsolete).
- 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing
- 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function (will obsolete).
@ -559,6 +560,8 @@ ImGuiStyle::ImGuiStyle()
Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f);
Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.60f);
Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input
Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90f, 0.80f, 0.80f, 0.40f);
Colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.65f, 0.65f, 0.45f);
Colors[ImGuiCol_TitleBg] = ImVec4(0.50f, 0.50f, 1.00f, 0.45f);
Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f);
Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.40f, 0.40f, 0.80f, 0.15f);
@ -566,8 +569,6 @@ ImGuiStyle::ImGuiStyle()
Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);
Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f);
Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f);
Colors[ImGuiCol_CheckHovered] = ImVec4(0.60f, 0.40f, 0.40f, 0.45f);
Colors[ImGuiCol_CheckActive] = ImVec4(0.65f, 0.50f, 0.50f, 0.55f);
Colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);
@ -649,9 +650,11 @@ void ImGuiIO::AddInputCharacter(ImWchar c)
const float PI = 3.14159265358979323846f;
#ifdef INT_MAX
#define IM_INT_MAX INT_MAX
#define IM_INT_MIN INT_MIN
#define IM_INT_MAX INT_MAX
#else
#define IM_INT_MAX 2147483647
#define IM_INT_MIN (-2147483647-1)
#define IM_INT_MAX (2147483647)
#endif
// Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n.
@ -1138,6 +1141,9 @@ struct ImGuiState
ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
ImGuiStorage ColorEditModeStorage; // for user selection
ImGuiID ActiveComboID;
ImVec2 DragLastMouseDelta;
float DragSpeedScaleSlow;
float DragSpeedScaleFast;
float ScrollbarClickDeltaToGrabCenter; // distance between mouse and center of grab box, normalized in parent space
char Tooltip[1024];
char* PrivateClipboard; // if no custom clipboard handler is defined
@ -1189,6 +1195,9 @@ struct ImGuiState
ScalarAsInputTextId = 0;
ActiveComboID = 0;
DragLastMouseDelta = ImVec2(0.0f, 0.0f);
DragSpeedScaleSlow = 0.01f;
DragSpeedScaleFast = 10.0f;
ScrollbarClickDeltaToGrabCenter = 0.0f;
memset(Tooltip, 0, sizeof(Tooltip));
PrivateClipboard = NULL;
@ -3716,6 +3725,8 @@ const char* ImGui::GetStyleColName(ImGuiCol idx)
case ImGuiCol_Border: return "Border";
case ImGuiCol_BorderShadow: return "BorderShadow";
case ImGuiCol_FrameBg: return "FrameBg";
case ImGuiCol_FrameBgHovered: return "FrameBgHovered";
case ImGuiCol_FrameBgActive: return "FrameBgActive";
case ImGuiCol_TitleBg: return "TitleBg";
case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed";
case ImGuiCol_ScrollbarBg: return "ScrollbarBg";
@ -3723,8 +3734,6 @@ const char* ImGui::GetStyleColName(ImGuiCol idx)
case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered";
case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive";
case ImGuiCol_ComboBg: return "ComboBg";
case ImGuiCol_CheckHovered: return "CheckHovered";
case ImGuiCol_CheckActive: return "CheckActive";
case ImGuiCol_CheckMark: return "CheckMark";
case ImGuiCol_SliderGrab: return "SliderGrab";
case ImGuiCol_SliderGrabActive: return "SliderGrabActive";
@ -5207,11 +5216,11 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c
int decimal_precision = 3;
ParseFormat(display_format, decimal_precision);
const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id);
const bool is_finite = (v_min != -FLT_MAX && v_min != FLT_MAX && v_max != -FLT_MAX && v_max != FLT_MAX);
// Tabbing or CTRL-clicking through slider turns into an input box
// Tabbing or CTRL-clicking on Slider turns it into an input box
bool start_text_input = false;
const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id);
if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]))
{
SetActiveId(id);
@ -5427,6 +5436,138 @@ bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const
return SliderIntN(label, v, 4, v_min, v_max, display_format);
}
// FIXME-WIP: Work in progress. May change API / behavior.
static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_step, float v_min, float v_max)
{
ImGuiState& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
const ImGuiStyle& style = g.Style;
// Draw frame
const ImU32 frame_col = window->Color(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding);
bool value_changed = false;
// Process clicking on the slider
if (g.ActiveId == id)
{
if (g.IO.MouseDown[0])
{
const ImVec2 mouse_drag_delta = ImGui::GetMouseDragDelta(0);
if (fabsf(mouse_drag_delta.x - g.DragLastMouseDelta.x) > 0.0f)
{
float step = v_step;
if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f)
step = v_step * g.DragSpeedScaleFast;
if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f)
step = v_step * g.DragSpeedScaleSlow;
*v += (mouse_drag_delta.x - g.DragLastMouseDelta.x) * step;
*v = ImClamp(*v, v_min, v_max);
g.DragLastMouseDelta.x = mouse_drag_delta.x;
value_changed = true;
}
}
else
{
SetActiveId(0);
}
}
return value_changed;
}
bool ImGui::DragFloat(const char* label, float *v, float v_step, float v_min, float v_max, const char* display_format)
{
ImGuiState& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return false;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label);
const float w = ImGui::CalcItemWidth();
const ImVec2 label_size = CalcTextSize(label, NULL, true);
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f);
const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
// NB- we don't call ItemSize() yet because we may turn into a text edit box below
if (!ItemAdd(total_bb, &id))
{
ItemSize(total_bb, style.FramePadding.y);
return false;
}
const bool hovered = IsHovered(frame_bb, id);
if (hovered)
g.HoveredId = id;
if (!display_format)
display_format = "%.3f";
int decimal_precision = 3;
ParseFormat(display_format, decimal_precision);
// Tabbing or CTRL-clicking on Drag turns it into an input box
bool start_text_input = false;
const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id);
if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]))
{
SetActiveId(id);
FocusWindow(window);
g.DragLastMouseDelta = ImVec2(0.f, 0.f);
const bool is_ctrl_down = g.IO.KeyCtrl;
if (tab_focus_requested || is_ctrl_down)
{
start_text_input = true;
g.ScalarAsInputTextId = 0;
}
}
if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id))
return SliderFloatAsInputText(label, v, id, decimal_precision);
ItemSize(total_bb, style.FramePadding.y);
// Actual drag behavior
const bool value_changed = DragScalarBehavior(frame_bb, id, v, v_step, v_min, v_max);
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
char value_buf[64];
const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v);
const ImVec2 value_text_size = CalcTextSize(value_buf, value_buf_end, true);
RenderTextClipped(ImVec2(ImMax(frame_bb.Min.x + style.FramePadding.x, inner_bb.GetCenter().x - value_text_size.x*0.5f), frame_bb.Min.y + style.FramePadding.y), value_buf, value_buf_end, &value_text_size, frame_bb.Max);
if (label_size.x > 0.0f)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);
return value_changed;
}
bool ImGui::DragFloat(const char* label, float* v, float v_step, const char* display_format)
{
return ImGui::DragFloat(label, v, v_step, -FLT_MAX, FLT_MAX, display_format);
}
bool ImGui::DragInt(const char* label, int* v, int v_step, int v_min, int v_max, const char* display_format)
{
if (!display_format)
display_format = "%.0f";
float v_f = (float)*v;
bool value_changed = ImGui::DragFloat(label, &v_f, (float)v_step, (float)v_min, (float)v_max, display_format);
*v = (int)v_f;
return value_changed;
}
bool ImGui::DragInt(const char* label, int* v, int v_step, const char* display_format)
{
return ImGui::DragInt(label, v, v_step, IM_INT_MIN, IM_INT_MAX, display_format);
}
enum ImGuiPlotType
{
ImGuiPlotType_Lines,
@ -5598,7 +5739,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
if (pressed)
*v = !(*v);
RenderFrame(check_bb.Min, check_bb.Max, window->Color((held && hovered) ? ImGuiCol_CheckActive : hovered ? ImGuiCol_CheckHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
RenderFrame(check_bb.Min, check_bb.Max, window->Color((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
if (*v)
{
const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight());
@ -5659,7 +5800,7 @@ bool ImGui::RadioButton(const char* label, bool active)
bool hovered, held;
bool pressed = ButtonBehavior(total_bb, id, &hovered, &held, true);
window->DrawList->AddCircleFilled(center, radius, window->Color((held && hovered) ? ImGuiCol_CheckActive : hovered ? ImGuiCol_CheckHovered : ImGuiCol_FrameBg), 16);
window->DrawList->AddCircleFilled(center, radius, window->Color((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16);
if (active)
{
const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight());
@ -6866,7 +7007,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha)
ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
if (n + 1 == components)
ImGui::PushItemWidth(w_item_last);
value_changed |= ImGui::SliderInt(ids[n], &i[n], 0, 255, fmt[n]);
value_changed |= ImGui::DragInt(ids[n], &i[n], 1, 0, 255, fmt[n]);
}
ImGui::PopItemWidth();
ImGui::PopItemWidth();

12
imgui.h
View File

@ -300,6 +300,12 @@ namespace ImGui
IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), size_t stride = sizeof(float));
IMGUI_API void PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0));
// Widgets: Drags (tip: ctrl+click on a drag box to input text)
IMGUI_API bool DragFloat(const char* label, float* v, float v_step = 1.0f, float v_min = -FLT_MAX, float v_max = FLT_MAX, const char* display_format = "%.3f");
IMGUI_API bool DragFloat(const char* label, float* v, float v_step, const char* display_format);
IMGUI_API bool DragInt(const char* label, int* v, int v_step = 1, int v_min = -0x7fffffff-1, int v_max = 0x7fffffff, const char* display_format = "%.0f");
IMGUI_API bool DragInt(const char* label, int* v, int v_step, const char* display_format = "%.0f");
// Widgets: Sliders (tip: ctrl+click on a slider to input text)
IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); // adjust display_format to decorate the value with a prefix or a suffix. Use power!=1.0 for logarithmic sliders
IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f);
@ -484,6 +490,8 @@ enum ImGuiCol_
ImGuiCol_Border,
ImGuiCol_BorderShadow,
ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input
ImGuiCol_FrameBgHovered,
ImGuiCol_FrameBgActive,
ImGuiCol_TitleBg,
ImGuiCol_TitleBgCollapsed,
ImGuiCol_ScrollbarBg,
@ -491,8 +499,6 @@ enum ImGuiCol_
ImGuiCol_ScrollbarGrabHovered,
ImGuiCol_ScrollbarGrabActive,
ImGuiCol_ComboBg,
ImGuiCol_CheckHovered,
ImGuiCol_CheckActive,
ImGuiCol_CheckMark,
ImGuiCol_SliderGrab,
ImGuiCol_SliderGrabActive,
@ -553,7 +559,7 @@ enum ImGuiMouseCursor_
ImGuiMouseCursor_TextInput,
ImGuiMouseCursor_Move, // Unused by ImGui
ImGuiMouseCursor_ResizeNS, // Unused by ImGui
ImGuiMouseCursor_ResizeEW, // Unused by ImGui
ImGuiMouseCursor_ResizeEW,
ImGuiMouseCursor_ResizeNESW, // Unused by ImGui
ImGuiMouseCursor_ResizeNWSE,
ImGuiMouseCursor_Count_