mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-25 21:17:01 +00:00
Internal: Tabbing: Tweaks to FocusableItemRegister and using the standard mechanism to allow/block Tab being interpreting by tabbing instead of InputText() widget.
This commit is contained in:
parent
1ed3c4cf4a
commit
ce4e62649a
21
imgui.cpp
21
imgui.cpp
@ -2895,19 +2895,21 @@ bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop)
|
bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
|
|
||||||
|
// Increment counters
|
||||||
const bool is_tab_stop = (window->DC.ItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
|
const bool is_tab_stop = (window->DC.ItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
|
||||||
window->FocusIdxAllCounter++;
|
window->FocusIdxAllCounter++;
|
||||||
if (is_tab_stop)
|
if (is_tab_stop)
|
||||||
window->FocusIdxTabCounter++;
|
window->FocusIdxTabCounter++;
|
||||||
|
|
||||||
// Process keyboard input at this point: TAB/Shift-TAB to tab out of the currently focused item.
|
// Process TAB/Shift-TAB to tab *OUT* of the currently focused item.
|
||||||
// Note that we can always TAB out of a widget that doesn't allow tabbing in.
|
// (Note that we can always TAB out of a widget that doesn't allow tabbing in)
|
||||||
if (tab_stop && (g.ActiveId == id) && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab))
|
if (g.ActiveId == id && g.FocusTabPressed && !(g.ActiveIdBlockNavInputFlags & (1 << ImGuiNavInput_KeyTab_)))
|
||||||
window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (is_tab_stop ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items.
|
if (window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX)
|
||||||
|
window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (is_tab_stop ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items.
|
||||||
|
|
||||||
if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent)
|
if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent)
|
||||||
return true;
|
return true;
|
||||||
@ -3513,7 +3515,9 @@ void ImGui::NewFrame()
|
|||||||
UpdateMouseWheel();
|
UpdateMouseWheel();
|
||||||
|
|
||||||
// Pressing TAB activate widget focus
|
// Pressing TAB activate widget focus
|
||||||
if (g.ActiveId == 0 && g.NavWindow != NULL && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab, false))
|
// (This code is old and will be redesigned for Nav. In the meanwhile we use g.NavTabRequest as storage but this doesn't need ImGuiConfigFlags_NavEnableKeyboard to work!)
|
||||||
|
g.FocusTabPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab));
|
||||||
|
if (g.ActiveId == 0 && g.FocusTabPressed)
|
||||||
{
|
{
|
||||||
if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX)
|
if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX)
|
||||||
g.NavWindow->FocusIdxTabRequestNext = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1);
|
g.NavWindow->FocusIdxTabRequestNext = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1);
|
||||||
@ -5167,8 +5171,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||||||
window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
|
window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
|
||||||
|
|
||||||
// Prepare for item focus requests
|
// Prepare for item focus requests
|
||||||
window->FocusIdxAllRequestCurrent = (window->FocusIdxAllRequestNext == INT_MAX || window->FocusIdxAllCounter == -1) ? INT_MAX : (window->FocusIdxAllRequestNext + (window->FocusIdxAllCounter+1)) % (window->FocusIdxAllCounter+1);
|
window->FocusIdxAllRequestCurrent = (window->FocusIdxAllRequestNext == INT_MAX || window->FocusIdxAllCounter == -1) ? INT_MAX : ImModPositive(window->FocusIdxAllRequestNext, window->FocusIdxAllCounter + 1);
|
||||||
window->FocusIdxTabRequestCurrent = (window->FocusIdxTabRequestNext == INT_MAX || window->FocusIdxTabCounter == -1) ? INT_MAX : (window->FocusIdxTabRequestNext + (window->FocusIdxTabCounter+1)) % (window->FocusIdxTabCounter+1);
|
window->FocusIdxTabRequestCurrent = (window->FocusIdxTabRequestNext == INT_MAX || window->FocusIdxTabCounter == -1) ? INT_MAX : ImModPositive(window->FocusIdxTabRequestNext, window->FocusIdxTabCounter + 1);
|
||||||
window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1;
|
window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1;
|
||||||
window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = INT_MAX;
|
window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = INT_MAX;
|
||||||
|
|
||||||
@ -7609,6 +7613,7 @@ static void ImGui::NavUpdate()
|
|||||||
NAV_MAP_KEY(ImGuiKey_RightArrow,ImGuiNavInput_KeyRight_);
|
NAV_MAP_KEY(ImGuiKey_RightArrow,ImGuiNavInput_KeyRight_);
|
||||||
NAV_MAP_KEY(ImGuiKey_UpArrow, ImGuiNavInput_KeyUp_ );
|
NAV_MAP_KEY(ImGuiKey_UpArrow, ImGuiNavInput_KeyUp_ );
|
||||||
NAV_MAP_KEY(ImGuiKey_DownArrow, ImGuiNavInput_KeyDown_ );
|
NAV_MAP_KEY(ImGuiKey_DownArrow, ImGuiNavInput_KeyDown_ );
|
||||||
|
NAV_MAP_KEY(ImGuiKey_Tab, ImGuiNavInput_KeyTab_ );
|
||||||
if (g.IO.KeyCtrl)
|
if (g.IO.KeyCtrl)
|
||||||
g.IO.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f;
|
g.IO.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f;
|
||||||
if (g.IO.KeyShift)
|
if (g.IO.KeyShift)
|
||||||
|
1
imgui.h
1
imgui.h
@ -967,6 +967,7 @@ enum ImGuiNavInput_
|
|||||||
// [Internal] Don't use directly! This is used internally to differentiate keyboard from gamepad inputs for behaviors that require to differentiate them.
|
// [Internal] Don't use directly! This is used internally to differentiate keyboard from gamepad inputs for behaviors that require to differentiate them.
|
||||||
// Keyboard behavior that have no corresponding gamepad mapping (e.g. CTRL+TAB) will be directly reading from io.KeysDown[] instead of io.NavInputs[].
|
// Keyboard behavior that have no corresponding gamepad mapping (e.g. CTRL+TAB) will be directly reading from io.KeysDown[] instead of io.NavInputs[].
|
||||||
ImGuiNavInput_KeyMenu_, // toggle menu // = io.KeyAlt
|
ImGuiNavInput_KeyMenu_, // toggle menu // = io.KeyAlt
|
||||||
|
ImGuiNavInput_KeyTab_, // tab // = Tab key
|
||||||
ImGuiNavInput_KeyLeft_, // move left // = Arrow keys
|
ImGuiNavInput_KeyLeft_, // move left // = Arrow keys
|
||||||
ImGuiNavInput_KeyRight_, // move right
|
ImGuiNavInput_KeyRight_, // move right
|
||||||
ImGuiNavInput_KeyUp_, // move up
|
ImGuiNavInput_KeyUp_, // move up
|
||||||
|
@ -248,6 +248,7 @@ static inline float ImLengthSqr(const ImVec4& lhs)
|
|||||||
static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / ImSqrt(d); return fail_value; }
|
static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / ImSqrt(d); return fail_value; }
|
||||||
static inline float ImFloor(float f) { return (float)(int)f; }
|
static inline float ImFloor(float f) { return (float)(int)f; }
|
||||||
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)v.x, (float)(int)v.y); }
|
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)v.x, (float)(int)v.y); }
|
||||||
|
static inline int ImModPositive(int a, int b) { return (a + b) % b; }
|
||||||
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
|
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
|
||||||
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
|
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
|
||||||
static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; }
|
static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; }
|
||||||
@ -891,6 +892,9 @@ struct ImGuiContext
|
|||||||
ImGuiNavMoveResult NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
|
ImGuiNavMoveResult NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
|
||||||
ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
|
ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
|
||||||
|
|
||||||
|
// Tabbing system (older than Nav, active when Nav is disabled. Probably needs a redesign)
|
||||||
|
bool FocusTabPressed; //
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
ImDrawData DrawData; // Main ImDrawData instance to pass render information to the user
|
ImDrawData DrawData; // Main ImDrawData instance to pass render information to the user
|
||||||
ImDrawDataBuilder DrawDataBuilder;
|
ImDrawDataBuilder DrawDataBuilder;
|
||||||
@ -1036,6 +1040,7 @@ struct ImGuiContext
|
|||||||
NavMoveRequestFlags = 0;
|
NavMoveRequestFlags = 0;
|
||||||
NavMoveRequestForward = ImGuiNavForward_None;
|
NavMoveRequestForward = ImGuiNavForward_None;
|
||||||
NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None;
|
NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None;
|
||||||
|
FocusTabPressed = false;
|
||||||
|
|
||||||
DimBgRatio = 0.0f;
|
DimBgRatio = 0.0f;
|
||||||
BackgroundDrawList._Data = &DrawListSharedData;
|
BackgroundDrawList._Data = &DrawListSharedData;
|
||||||
@ -1421,7 +1426,7 @@ namespace ImGui
|
|||||||
IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL);
|
IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL);
|
||||||
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
|
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
|
||||||
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged);
|
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged);
|
||||||
IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop = true); // Return true if focus is requested
|
IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id); // Return true if focus is requested
|
||||||
IMGUI_API void FocusableItemUnregister(ImGuiWindow* window);
|
IMGUI_API void FocusableItemUnregister(ImGuiWindow* window);
|
||||||
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y);
|
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y);
|
||||||
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
|
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
|
||||||
|
@ -3274,7 +3274,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
if (g.InputTextState.ID == id)
|
if (g.InputTextState.ID == id)
|
||||||
state = &g.InputTextState;
|
state = &g.InputTextState;
|
||||||
|
|
||||||
const bool focus_requested = FocusableItemRegister(window, id, (flags & (ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_AllowTabInput)) == 0); // Using completion callback disable keyboard tabbing
|
const bool focus_requested = FocusableItemRegister(window, id);
|
||||||
const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent);
|
const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent);
|
||||||
const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;
|
const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;
|
||||||
|
|
||||||
@ -3337,7 +3337,10 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||||||
SetActiveID(id, window);
|
SetActiveID(id, window);
|
||||||
SetFocusID(id, window);
|
SetFocusID(id, window);
|
||||||
FocusWindow(window);
|
FocusWindow(window);
|
||||||
|
IM_ASSERT(ImGuiNavInput_COUNT < 32);
|
||||||
g.ActiveIdBlockNavInputFlags = (1 << ImGuiNavInput_Cancel);
|
g.ActiveIdBlockNavInputFlags = (1 << ImGuiNavInput_Cancel);
|
||||||
|
if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out
|
||||||
|
g.ActiveIdBlockNavInputFlags |= (1 << ImGuiNavInput_KeyTab_);
|
||||||
if (!is_multiline && !(flags & ImGuiInputTextFlags_CallbackHistory))
|
if (!is_multiline && !(flags & ImGuiInputTextFlags_CallbackHistory))
|
||||||
g.ActiveIdAllowNavDirFlags = ((1 << ImGuiDir_Up) | (1 << ImGuiDir_Down));
|
g.ActiveIdAllowNavDirFlags = ((1 << ImGuiDir_Up) | (1 << ImGuiDir_Down));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user