Removed support for legacy arithmetic operators (+*/) when inputing text into a slider/drag. (#4917, #3184)

This commit is contained in:
ocornut 2022-01-19 15:10:42 +01:00
parent 673f5e588d
commit 91ae56af45
7 changed files with 15 additions and 76 deletions

View File

@ -38,6 +38,9 @@ HOW TO UPDATE?
Breaking Changes: Breaking Changes:
- Removed support for pre-C++11 compilers. We'll stop supporting VS2010. (#4537) - Removed support for pre-C++11 compilers. We'll stop supporting VS2010. (#4537)
- Removed support for legacy arithmetic operators (+,+-,*,/) when inputing text into a slider/drag. (#4917, #3184)
This doesn't break any api/code but a feature that was accessible by end-users (which seemingly no one used).
(Instead you may implement custom expression evaluators to provide a better version of this).
- Reworked IO mouse input API: (#4858) [@thedmd, @ocornut] - Reworked IO mouse input API: (#4858) [@thedmd, @ocornut]
- Added io.AddMousePosEvent(), AddMouseButtonEvent(), AddMouseWheelEvent() functions, - Added io.AddMousePosEvent(), AddMouseButtonEvent(), AddMouseWheelEvent() functions,
obsoleting writing directly to io.MousePos, io.MouseDown[], io.MouseWheel, etc. obsoleting writing directly to io.MousePos, io.MouseDown[], io.MouseWheel, etc.
@ -102,6 +105,7 @@ Other Changes:
which would makes the draw operation of some backends assert (e.g. Metal with debugging). (#4857) which would makes the draw operation of some backends assert (e.g. Metal with debugging). (#4857)
- Tables, ImDrawListSplitter: Fixed erroneously stripping trailing ImDrawList::AddCallback() when submitted in - Tables, ImDrawListSplitter: Fixed erroneously stripping trailing ImDrawList::AddCallback() when submitted in
last column or last channel and when there are no other drawing operation. (#4843, #4844) [@hoffstadt] last column or last channel and when there are no other drawing operation. (#4843, #4844) [@hoffstadt]
- Sliders, Drags: Fixed text input of values with a leading sign, common when using a format enforcing sign. (#4917)
- Platform IME: changed io.ImeSetInputScreenPosFn() to io.SetPlatformImeDataFn() API, - Platform IME: changed io.ImeSetInputScreenPosFn() to io.SetPlatformImeDataFn() API,
now taking a ImGuiPlatformImeData structure which we can more easily extend in the future. now taking a ImGuiPlatformImeData structure which we can more easily extend in the future.
- Platform IME: moved io.ImeWindowHandle to GetMainViewport()->PlatformHandleRaw. - Platform IME: moved io.ImeWindowHandle to GetMainViewport()->PlatformHandleRaw.

View File

@ -113,7 +113,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- input number: optional range min/max for Input*() functions - input number: optional range min/max for Input*() functions
- input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled) - input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)
- input number: use mouse wheel to step up/down - input number: use mouse wheel to step up/down
- input number: applying arithmetics ops (+,-,*,/) messes up with text edit undo stack.
- layout: helper or a way to express ImGui::SameLine(ImGui::GetCursorStartPos().x + ImGui::CalcItemWidth() + ImGui::GetStyle().ItemInnerSpacing.x); in a simpler manner. - layout: helper or a way to express ImGui::SameLine(ImGui::GetCursorStartPos().x + ImGui::CalcItemWidth() + ImGui::GetStyle().ItemInnerSpacing.x); in a simpler manner.
- layout, font: horizontal tab support, A) text mode: forward only tabs (e.g. every 4 characters/N pixels from pos x1), B) manual mode: explicit tab stops acting as mini columns, no clipping (for menu items, many kind of uses, also vaguely relate to #267, #395) - layout, font: horizontal tab support, A) text mode: forward only tabs (e.g. every 4 characters/N pixels from pos x1), B) manual mode: explicit tab stops acting as mini columns, no clipping (for menu items, many kind of uses, also vaguely relate to #267, #395)

View File

@ -128,7 +128,6 @@ CODE
- CTRL+X,CTRL+C,CTRL+V to use OS clipboard/ - CTRL+X,CTRL+C,CTRL+V to use OS clipboard/
- CTRL+Z,CTRL+Y to undo/redo. - CTRL+Z,CTRL+Y to undo/redo.
- ESCAPE to revert text to its original value. - ESCAPE to revert text to its original value.
- You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!)
- Controls are automatically adjusted for OSX to match standard OSX text editing operations. - Controls are automatically adjusted for OSX to match standard OSX text editing operations.
- General Keyboard controls: enable with ImGuiConfigFlags_NavEnableKeyboard. - General Keyboard controls: enable with ImGuiConfigFlags_NavEnableKeyboard.
- General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at http://dearimgui.org/controls_sheets - General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at http://dearimgui.org/controls_sheets
@ -386,6 +385,7 @@ CODE
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
You can read releases logs https://github.com/ocornut/imgui/releases for more details. You can read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2022/01/19 (1.87) - sliders, drags: removed support for legacy arithmetic operators (+,+-,*,/) when inputing text. This doesn't break any api/code but a feature that used to be accessible by end-users (which seemingly no one used).
- 2022/01/17 (1.87) - inputs: reworked mouse IO. - 2022/01/17 (1.87) - inputs: reworked mouse IO.
- Backend writing to io.MousePos -> backend should call io.AddMousePosEvent() - Backend writing to io.MousePos -> backend should call io.AddMousePosEvent()
- Backend writing to io.MouseDown[] -> backend should call io.AddMouseButtonEvent() - Backend writing to io.MouseDown[] -> backend should call io.AddMouseButtonEvent()

View File

@ -65,7 +65,7 @@ Index of this file:
// Version // Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.87 WIP" #define IMGUI_VERSION "1.87 WIP"
#define IMGUI_VERSION_NUM 18608 #define IMGUI_VERSION_NUM 18609
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE

View File

@ -229,7 +229,6 @@ void ImGui::ShowUserGuide()
ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste."); ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste.");
ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo."); ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
ImGui::BulletText("ESCAPE to revert."); ImGui::BulletText("ESCAPE to revert.");
ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
ImGui::Unindent(); ImGui::Unindent();
ImGui::BulletText("With keyboard navigation enabled:"); ImGui::BulletText("With keyboard navigation enabled:");
ImGui::Indent(); ImGui::Indent();
@ -676,10 +675,6 @@ static void ShowDemoWindowWidgets()
IMGUI_DEMO_MARKER("Widgets/Basic/InputInt, InputFloat"); IMGUI_DEMO_MARKER("Widgets/Basic/InputInt, InputFloat");
static int i0 = 123; static int i0 = 123;
ImGui::InputInt("input int", &i0); ImGui::InputInt("input int", &i0);
ImGui::SameLine(); HelpMarker(
"You can apply arithmetic operators +,*,/ on numerical values.\n"
" e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\n"
"Use +- to subtract.");
static float f0 = 0.001f; static float f0 = 0.001f;
ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f"); ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f");

View File

@ -2805,7 +2805,7 @@ namespace ImGui
IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type); IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type);
IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format); IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format);
IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg_1, const void* arg_2); IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg_1, const void* arg_2);
IMGUI_API bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format); IMGUI_API bool DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void* p_data, const char* format);
IMGUI_API int DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2); IMGUI_API int DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2);
IMGUI_API bool DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max); IMGUI_API bool DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max);

View File

@ -1992,24 +1992,10 @@ void ImGui::DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const
// User can input math operators (e.g. +100) to edit a numerical values. // User can input math operators (e.g. +100) to edit a numerical values.
// NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess.. // NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess..
bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format) bool ImGui::DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void* p_data, const char* format)
{ {
while (ImCharIsBlankA(*buf)) while (ImCharIsBlankA(*buf))
buf++; buf++;
// We don't support '-' op because it would conflict with inputing negative value.
// Instead you can use +-100 to subtract from an existing value
char op = buf[0];
if (op == '+' || op == '*' || op == '/')
{
buf++;
while (ImCharIsBlankA(*buf))
buf++;
}
else
{
op = 0;
}
if (!buf[0]) if (!buf[0])
return false; return false;
@ -2021,54 +2007,11 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b
if (format == NULL) if (format == NULL)
format = type_info->ScanFmt; format = type_info->ScanFmt;
// FIXME-LEGACY: The aim is to remove those operators and write a proper expression evaluator at some point.. if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32 || data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64 || data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
int arg1i = 0;
if (data_type == ImGuiDataType_S32)
{ {
int* v = (int*)p_data; // For float/double we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in, so force them into %f and %lf
int arg0i = *v; if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
float arg1f = 0.0f; format = type_info->ScanFmt;
if (op && sscanf(initial_value_buf, format, &arg0i) < 1)
return false;
// Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision
if (op == '+') { if (sscanf(buf, "%d", &arg1i)) *v = (int)(arg0i + arg1i); } // Add (use "+-" to subtract)
else if (op == '*') { if (sscanf(buf, "%f", &arg1f)) *v = (int)(arg0i * arg1f); } // Multiply
else if (op == '/') { if (sscanf(buf, "%f", &arg1f) && arg1f != 0.0f) *v = (int)(arg0i / arg1f); } // Divide
else { if (sscanf(buf, format, &arg1i) == 1) *v = arg1i; } // Assign constant
}
else if (data_type == ImGuiDataType_Float)
{
// For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in
format = "%f";
float* v = (float*)p_data;
float arg0f = *v, arg1f = 0.0f;
if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
return false;
if (sscanf(buf, format, &arg1f) < 1)
return false;
if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract)
else if (op == '*') { *v = arg0f * arg1f; } // Multiply
else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
else { *v = arg1f; } // Assign constant
}
else if (data_type == ImGuiDataType_Double)
{
format = "%lf"; // scanf differentiate float/double unlike printf which forces everything to double because of ellipsis
double* v = (double*)p_data;
double arg0f = *v, arg1f = 0.0;
if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
return false;
if (sscanf(buf, format, &arg1f) < 1)
return false;
if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract)
else if (op == '*') { *v = arg0f * arg1f; } // Multiply
else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
else { *v = arg1f; } // Assign constant
}
else if (data_type == ImGuiDataType_U32 || data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64)
{
// All other types assign constant
// We don't bother handling support for legacy operators since they are a little too crappy. Instead we will later implement a proper expression evaluator in the future.
if (sscanf(buf, format, p_data) < 1) if (sscanf(buf, format, p_data) < 1)
return false; return false;
} }
@ -3387,8 +3330,6 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char*
// However this may not be ideal for all uses, as some user code may break on out of bound values. // However this may not be ideal for all uses, as some user code may break on out of bound values.
bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max) bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max)
{ {
ImGuiContext& g = *GImGui;
char fmt_buf[32]; char fmt_buf[32];
char data_buf[32]; char data_buf[32];
format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf)); format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf));
@ -3406,7 +3347,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
memcpy(&data_backup, p_data, data_type_size); memcpy(&data_backup, p_data, data_type_size);
// Apply new value (or operations) then clamp // Apply new value (or operations) then clamp
DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, p_data, NULL); DataTypeApplyFromText(data_buf, data_type, p_data, NULL);
if (p_clamp_min || p_clamp_max) if (p_clamp_min || p_clamp_max)
{ {
if (p_clamp_min && p_clamp_max && DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0) if (p_clamp_min && p_clamp_max && DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0)
@ -3453,7 +3394,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
PushID(label); PushID(label);
SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2)); SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format); value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
// Step buttons // Step buttons
const ImVec2 backup_frame_padding = style.FramePadding; const ImVec2 backup_frame_padding = style.FramePadding;
@ -3490,7 +3431,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
else else
{ {
if (InputText(label, buf, IM_ARRAYSIZE(buf), flags)) if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format); value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
} }
if (value_changed) if (value_changed)
MarkItemEdited(g.LastItemData.ID); MarkItemEdited(g.LastItemData.ID);