mirror of
https://github.com/ocornut/imgui.git
synced 2024-11-24 15:50:25 +01:00
Added ImGuiInputTextFlags_ReadOnly flag for InputText()/InputTextMultiline() (#211)
This commit is contained in:
parent
f5fb5f0c1e
commit
b4f1e88860
52
imgui.cpp
52
imgui.cpp
@ -452,7 +452,8 @@
|
|||||||
- settings: write more decent code to allow saving/loading new fields
|
- settings: write more decent code to allow saving/loading new fields
|
||||||
- settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file
|
- settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file
|
||||||
- style: store rounded corners in texture to use 1 quad per corner (filled and wireframe). so rounding have minor cost.
|
- style: store rounded corners in texture to use 1 quad per corner (filled and wireframe). so rounding have minor cost.
|
||||||
- style: colorbox not always square?
|
- style: color-box not always square?
|
||||||
|
- style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps that other settings?
|
||||||
- text: simple markup language for color change?
|
- text: simple markup language for color change?
|
||||||
- log: LogButtons() options for specifying depth and/or hiding depth slider
|
- log: LogButtons() options for specifying depth and/or hiding depth slider
|
||||||
- log: have more control over the log scope (e.g. stop logging when leaving current tree node scope)
|
- log: have more control over the log scope (e.g. stop logging when leaving current tree node scope)
|
||||||
@ -7032,6 +7033,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
|
|
||||||
const ImGuiID id = window->GetID(label);
|
const ImGuiID id = window->GetID(label);
|
||||||
const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0;
|
const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0;
|
||||||
|
const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0;
|
||||||
|
|
||||||
ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
|
ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
|
||||||
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), is_multiline ? ImGui::GetTextLineHeight() * 8.0f : label_size.y); // Arbitrary default of 8 lines high for multi-line
|
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), is_multiline ? ImGui::GetTextLineHeight() * 8.0f : label_size.y); // Arbitrary default of 8 lines high for multi-line
|
||||||
@ -7163,7 +7165,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
if (g.IO.InputCharacters[0])
|
if (g.IO.InputCharacters[0])
|
||||||
{
|
{
|
||||||
// Process text input (before we check for Return because using some IME will effectively send a Return?)
|
// Process text input (before we check for Return because using some IME will effectively send a Return?)
|
||||||
if (!is_ctrl_down && !is_alt_down)
|
if (!is_ctrl_down && !is_alt_down && is_editable)
|
||||||
{
|
{
|
||||||
for (int n = 0; n < IM_ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++)
|
for (int n = 0; n < IM_ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++)
|
||||||
if (unsigned int c = (unsigned int)g.IO.InputCharacters[n])
|
if (unsigned int c = (unsigned int)g.IO.InputCharacters[n])
|
||||||
@ -7187,8 +7189,8 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
else if (is_multiline && IsKeyPressedMap(ImGuiKey_DownArrow)) { if (is_ctrl_down) SetWindowScrollY(draw_window, draw_window->Scroll.y + g.FontSize); else edit_state.OnKeyPressed(STB_TEXTEDIT_K_DOWN| k_mask); }
|
else if (is_multiline && IsKeyPressedMap(ImGuiKey_DownArrow)) { if (is_ctrl_down) SetWindowScrollY(draw_window, draw_window->Scroll.y + g.FontSize); else edit_state.OnKeyPressed(STB_TEXTEDIT_K_DOWN| k_mask); }
|
||||||
else if (IsKeyPressedMap(ImGuiKey_Home)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
|
else if (IsKeyPressedMap(ImGuiKey_Home)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
|
||||||
else if (IsKeyPressedMap(ImGuiKey_End)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
|
else if (IsKeyPressedMap(ImGuiKey_End)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
|
||||||
else if (IsKeyPressedMap(ImGuiKey_Delete)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
|
else if (IsKeyPressedMap(ImGuiKey_Delete) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
|
||||||
else if (IsKeyPressedMap(ImGuiKey_Backspace)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); }
|
else if (IsKeyPressedMap(ImGuiKey_Backspace) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); }
|
||||||
else if (IsKeyPressedMap(ImGuiKey_Enter))
|
else if (IsKeyPressedMap(ImGuiKey_Enter))
|
||||||
{
|
{
|
||||||
bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;
|
bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;
|
||||||
@ -7197,24 +7199,24 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
SetActiveID(0);
|
SetActiveID(0);
|
||||||
enter_pressed = true;
|
enter_pressed = true;
|
||||||
}
|
}
|
||||||
else // New line
|
else if (is_editable) // New line
|
||||||
{
|
{
|
||||||
unsigned int c = '\n';
|
unsigned int c = '\n';
|
||||||
if (InputTextFilterCharacter(&c, flags, callback, user_data))
|
if (InputTextFilterCharacter(&c, flags, callback, user_data))
|
||||||
edit_state.OnKeyPressed((int)c);
|
edit_state.OnKeyPressed((int)c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !is_ctrl_down && !is_shift_down && !is_alt_down)
|
else if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !is_ctrl_down && !is_shift_down && !is_alt_down && is_editable)
|
||||||
{
|
{
|
||||||
unsigned int c = '\t';
|
unsigned int c = '\t';
|
||||||
if (InputTextFilterCharacter(&c, flags, callback, user_data))
|
if (InputTextFilterCharacter(&c, flags, callback, user_data))
|
||||||
edit_state.OnKeyPressed((int)c);
|
edit_state.OnKeyPressed((int)c);
|
||||||
}
|
}
|
||||||
else if (IsKeyPressedMap(ImGuiKey_Escape)) { SetActiveID(0); cancel_edit = true; }
|
else if (IsKeyPressedMap(ImGuiKey_Escape)) { SetActiveID(0); cancel_edit = true; }
|
||||||
else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_Z)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); }
|
else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); }
|
||||||
else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_Y)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); }
|
else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); }
|
||||||
else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); edit_state.CursorFollow = true; }
|
else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); edit_state.CursorFollow = true; }
|
||||||
else if (is_ctrl_only && (IsKeyPressedMap(ImGuiKey_X) || IsKeyPressedMap(ImGuiKey_C)) && (!is_multiline || edit_state.HasSelection()))
|
else if (is_ctrl_only && ((IsKeyPressedMap(ImGuiKey_X) && is_editable) || IsKeyPressedMap(ImGuiKey_C)) && (!is_multiline || edit_state.HasSelection()))
|
||||||
{
|
{
|
||||||
// Cut, Copy
|
// Cut, Copy
|
||||||
const bool cut = IsKeyPressedMap(ImGuiKey_X);
|
const bool cut = IsKeyPressedMap(ImGuiKey_X);
|
||||||
@ -7236,7 +7238,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
stb_textedit_cut(&edit_state, &edit_state.StbState);
|
stb_textedit_cut(&edit_state, &edit_state.StbState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_V))
|
else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_V) && is_editable)
|
||||||
{
|
{
|
||||||
// Paste
|
// Paste
|
||||||
if (g.IO.GetClipboardTextFn)
|
if (g.IO.GetClipboardTextFn)
|
||||||
@ -7271,8 +7273,11 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
if (cancel_edit)
|
if (cancel_edit)
|
||||||
{
|
{
|
||||||
// Restore initial value
|
// Restore initial value
|
||||||
ImFormatString(buf, buf_size, "%s", edit_state.InitialText.Data);
|
if (is_editable)
|
||||||
value_changed = true;
|
{
|
||||||
|
ImFormatString(buf, buf_size, "%s", edit_state.InitialText.Data);
|
||||||
|
value_changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -7280,8 +7285,11 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
// Note that as soon as we can focus into the input box, the in-widget value gets priority over any underlying modification of the input buffer
|
// Note that as soon as we can focus into the input box, the in-widget value gets priority over any underlying modification of the input buffer
|
||||||
// FIXME: We actually always render 'buf' in RenderTextScrolledClipped
|
// FIXME: We actually always render 'buf' in RenderTextScrolledClipped
|
||||||
// FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks
|
// FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks
|
||||||
edit_state.TempTextBuffer.resize(edit_state.Text.Size * 4);
|
if (is_editable)
|
||||||
ImTextStrToUtf8(edit_state.TempTextBuffer.Data, edit_state.TempTextBuffer.Size, edit_state.Text.Data, NULL);
|
{
|
||||||
|
edit_state.TempTextBuffer.resize(edit_state.Text.Size * 4);
|
||||||
|
ImTextStrToUtf8(edit_state.TempTextBuffer.Data, edit_state.TempTextBuffer.Size, edit_state.Text.Data, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
// User callback
|
// User callback
|
||||||
if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackAlways)) != 0)
|
if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackAlways)) != 0)
|
||||||
@ -7311,12 +7319,14 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
{
|
{
|
||||||
ImGuiTextEditCallbackData callback_data;
|
ImGuiTextEditCallbackData callback_data;
|
||||||
callback_data.EventFlag = event_flag;
|
callback_data.EventFlag = event_flag;
|
||||||
|
callback_data.Flags = flags;
|
||||||
|
callback_data.UserData = user_data;
|
||||||
|
callback_data.ReadOnly = !is_editable;
|
||||||
|
|
||||||
callback_data.EventKey = event_key;
|
callback_data.EventKey = event_key;
|
||||||
callback_data.Buf = edit_state.TempTextBuffer.Data;
|
callback_data.Buf = edit_state.TempTextBuffer.Data;
|
||||||
callback_data.BufSize = edit_state.BufSizeA;
|
callback_data.BufSize = edit_state.BufSizeA;
|
||||||
callback_data.BufDirty = false;
|
callback_data.BufDirty = false;
|
||||||
callback_data.Flags = flags;
|
|
||||||
callback_data.UserData = user_data;
|
|
||||||
|
|
||||||
// We have to convert from position from wchar to UTF-8 positions
|
// We have to convert from position from wchar to UTF-8 positions
|
||||||
ImWchar* text = edit_state.Text.Data;
|
ImWchar* text = edit_state.Text.Data;
|
||||||
@ -7343,7 +7353,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(edit_state.TempTextBuffer.Data, buf) != 0)
|
if (is_editable && strcmp(edit_state.TempTextBuffer.Data, buf) != 0)
|
||||||
{
|
{
|
||||||
ImFormatString(buf, buf_size, "%s", edit_state.TempTextBuffer.Data);
|
ImFormatString(buf, buf_size, "%s", edit_state.TempTextBuffer.Data);
|
||||||
value_changed = true;
|
value_changed = true;
|
||||||
@ -7366,7 +7376,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
// - Display the text (this can be more easily clipped)
|
// - Display the text (this can be more easily clipped)
|
||||||
// - Handle scrolling, highlight selection, display cursor (those all requires some form of 1d->2d cursor position calculation)
|
// - Handle scrolling, highlight selection, display cursor (those all requires some form of 1d->2d cursor position calculation)
|
||||||
// - Measure text height (for scrollbar)
|
// - Measure text height (for scrollbar)
|
||||||
// We are attempting to do most of that in one main pass to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort)
|
// We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort)
|
||||||
const ImWchar* text_begin = edit_state.Text.Data;
|
const ImWchar* text_begin = edit_state.Text.Data;
|
||||||
const ImWchar* text_end = text_begin + edit_state.CurLenW;
|
const ImWchar* text_end = text_begin + edit_state.CurLenW;
|
||||||
ImVec2 cursor_offset, select_start_offset;
|
ImVec2 cursor_offset, select_start_offset;
|
||||||
@ -7485,7 +7495,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
draw_window->DrawList->AddLine(cursor_screen_pos + ImVec2(0.0f,-g.FontSize+0.5f), cursor_screen_pos + ImVec2(0.0f,-1.5f), window->Color(ImGuiCol_Text));
|
draw_window->DrawList->AddLine(cursor_screen_pos + ImVec2(0.0f,-g.FontSize+0.5f), cursor_screen_pos + ImVec2(0.0f,-1.5f), window->Color(ImGuiCol_Text));
|
||||||
|
|
||||||
// Notify OS of text input position for advanced IME
|
// Notify OS of text input position for advanced IME
|
||||||
if (io.ImeSetInputScreenPosFn && ImLengthSqr(edit_state.InputCursorScreenPos - cursor_screen_pos) > 0.0001f)
|
if (is_editable && io.ImeSetInputScreenPosFn && ImLengthSqr(edit_state.InputCursorScreenPos - cursor_screen_pos) > 0.0001f)
|
||||||
io.ImeSetInputScreenPosFn((int)cursor_screen_pos.x - 1, (int)(cursor_screen_pos.y - g.FontSize)); // -1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.
|
io.ImeSetInputScreenPosFn((int)cursor_screen_pos.x - 1, (int)(cursor_screen_pos.y - g.FontSize)); // -1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.
|
||||||
|
|
||||||
edit_state.InputCursorScreenPos = cursor_screen_pos;
|
edit_state.InputCursorScreenPos = cursor_screen_pos;
|
||||||
|
2
imgui.h
2
imgui.h
@ -487,6 +487,7 @@ enum ImGuiInputTextFlags_
|
|||||||
ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11, // In multi-line mode, allow exiting edition by pressing Enter. Ctrl+Enter to add new line (by default adds new lines with Enter).
|
ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11, // In multi-line mode, allow exiting edition by pressing Enter. Ctrl+Enter to add new line (by default adds new lines with Enter).
|
||||||
ImGuiInputTextFlags_NoHorizontalScroll = 1 << 12, // Disable following the cursor horizontally
|
ImGuiInputTextFlags_NoHorizontalScroll = 1 << 12, // Disable following the cursor horizontally
|
||||||
ImGuiInputTextFlags_AlwaysInsertMode = 1 << 13, // Insert mode
|
ImGuiInputTextFlags_AlwaysInsertMode = 1 << 13, // Insert mode
|
||||||
|
ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode
|
||||||
// [Internal]
|
// [Internal]
|
||||||
ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline()
|
ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline()
|
||||||
};
|
};
|
||||||
@ -939,6 +940,7 @@ struct ImGuiTextEditCallbackData
|
|||||||
ImGuiInputTextFlags EventFlag; // One of ImGuiInputTextFlags_Callback* // Read-only
|
ImGuiInputTextFlags EventFlag; // One of ImGuiInputTextFlags_Callback* // Read-only
|
||||||
ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only
|
ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only
|
||||||
void* UserData; // What user passed to InputText() // Read-only
|
void* UserData; // What user passed to InputText() // Read-only
|
||||||
|
bool ReadOnly; // Read-only mode // Read-only
|
||||||
|
|
||||||
// CharFilter event:
|
// CharFilter event:
|
||||||
ImWchar EventChar; // Character input // Read-write (replace character or set to zero)
|
ImWchar EventChar; // Character input // Read-write (replace character or set to zero)
|
||||||
|
@ -422,8 +422,12 @@ void ImGui::ShowTestWindow(bool* opened)
|
|||||||
|
|
||||||
if (ImGui::TreeNode("Multi-line Text Input"))
|
if (ImGui::TreeNode("Multi-line Text Input"))
|
||||||
{
|
{
|
||||||
|
static bool read_only = false;
|
||||||
static char text[1024*16] = "// F00F bug\nlabel:\n\tlock cmpxchg8b eax\n";
|
static char text[1024*16] = "// F00F bug\nlabel:\n\tlock cmpxchg8b eax\n";
|
||||||
ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_AllowTabInput);
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
|
||||||
|
ImGui::Checkbox("Read-only", &read_only);
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0));
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user