@ -362,9 +362,10 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- nav: patterns to make it possible for arrows key to update selection (see JustMovedTo in range_select branch)
- nav: restore/find nearest NavId when current one disappear (e.g. pressed a button that disappear, or perhaps auto restoring when current button change name)
- nav: SetItemDefaultFocus() level of priority, so widget like Selectable when inside a popup could claim a low-priority default focus on the first selected iem
- nav: NavFlattened: init requests don't work properly on flattened siblings.
- nav: NavFlattened: pageup/pagedown/home/end don't work properly on flattened siblings.
- nav: NavFlattened: ESC on a flattened child should select something.
- nav: NavFlattened: broken: in typical usage scenario, the items of a fully clipped child are currently not considered to enter into a NavFlattened child.
- nav: NavFlattened: init request doesn't select items that are part of a NavFlattened child
- nav: NavFlattened: cannot access menu-bar of a flattened child window with Alt/menu key (not a very common use case..).
- nav: simulate right-click or context activation? (SHIFT+F10)
- nav/tabbing: refactor old tabbing system and turn into navigation, should pass through all widgets (in submission order?).
// If mouse moved we re-enable mouse hovering in case it was disabled by gamepad/keyboard. In theory should use a >0.0f threshold but would need to reset in everywhere we set this to true.
// Tab stop handling (previously was using internal ItemFocusable() api)
// FIXME-NAV: We would now want to move this above the clipping test, but this would require being able to scroll and currently this would mean an extra frame. (#4079, #343)
if(flags &ImGuiItemAddFlags_Focusable)
ItemFocusable(window,id);
// [WIP] Tab stop handling (previously was using internal FocusableItemRegister() api)
// FIXME-NAV: We would now want to move this before the clipping test, but this would require being able to scroll and currently this would mean an extra frame. (#4079, #343)
if(extra_flags &ImGuiItemFlags_Inputable)
ItemInputable(window,id);
// We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them)
// Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.)
// Groups are currently a mishmash of functionalities which should perhaps be clarified and separated.
// FIXME-OPT: Could we safely early out on ->SkipItems?
constImRect&curr=g.NavScoringRect;// Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width)
g.NavScoringCount++;
// FIXME: Those are not good variables names
ImRectcand=g.LastItemData.NavRect;// Current item nav rectangle
constImRectcurr=g.NavScoringRect;// Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width)
g.NavScoringDebugCount++;
// When entering through a NavFlattened border, we consider child window items as fully clipped for scoring
// Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" items
// (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index),
// this is fairly easy. This rule ensures that all buttons with dx==dy==0 will end up being linked in order of appearance along the x axis.
if(((g.NavMoveDir==ImGuiDir_Up||g.NavMoveDir ==ImGuiDir_Down)?dby:dbx)<0.0f)// moving bj to the right/down decreases distance
if(((move_dir ==ImGuiDir_Up||move_dir ==ImGuiDir_Down)?dby:dbx)<0.0f)// moving bj to the right/down decreases distance
//if (!g.IO.NavActive) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag.
// FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRectScreen + scoring from a rect wrapped according to current wrapping policy)
window->NavRectRel[window->DC.NavLayerCurrent]=nav_bb_rel;// Store item bounding box (relative to window position)
window->NavRectRel[window->DC.NavLayerCurrent]=ImRect(nav_bb.Min-window->Pos,nav_bb.Max-window->Pos);// Store item bounding box (relative to window position)
// *Fallback* manual-scroll with Nav directional keys when window has no navigable item
ImGuiWindow*window=g.NavWindow;
constfloatscroll_speed=IM_ROUND(window->CalcFontSize()*100*io.DeltaTime);// We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
// In very rare cases g.NavWindow may be null (e.g. clearing focus after requesting an init request, which does happen when releasing Alt while clicking on void)
// Forwarding previous request (which has been modified, e.g. wrap around menus rewrite the requests with a starting rectangle at the other side of the window)
// (preserve most state, which were already set by the NavMoveRequestForward() function)
// If we initiate a movement request and have no current NavId, we initiate a InitDefaultRequest that will be used as a fallback if the direction fails to find a match
// When using gamepad, we project the reference nav bounding box into window visible area.
// This is to allow resuming navigation inside the visible area after doing a large amount of scrolling, since with gamepad every movements are relative
// (can't focus a visible object like we can with the mouse).
// For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items)
IM_ASSERT(!g.NavScoringRect.IsInverted());// Ensure if we have a finite, non-inverted bounding box here will allows us to remove extraneous ImFabs() calls in NavScoreItem().
IM_ASSERT(!scoring_rect.IsInverted());// Ensure if we have a finite, non-inverted bounding box here will allows us to remove extraneous ImFabs() calls in NavScoreItem().
// (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)
@ -148,8 +148,8 @@ struct ImGuiWindowSettings; // Storage for a window .ini settings (we ke
// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists.
typedefintImGuiDataAuthority;// -> enum ImGuiDataAuthority_ // Enum: for storing the source authority (dock node vs window) of a field
typedefintImGuiLayoutType;// -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical
typedefintImGuiActivateFlags;// -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later)
typedefintImGuiItemFlags;// -> enum ImGuiItemFlags_ // Flags: for PushItemFlag()
typedefintImGuiItemAddFlags;// -> enum ImGuiItemAddFlags_ // Flags: for ItemAdd()
typedefintImGuiItemStatusFlags;// -> enum ImGuiItemStatusFlags_ // Flags: for DC.LastItemStatusFlags
typedefintImGuiOldColumnFlags;// -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns()
typedefintImGuiNavHighlightFlags;// -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight()
@ -754,15 +754,8 @@ enum ImGuiItemFlags_
ImGuiItemFlags_NoNavDefaultFocus=1<<4,// false // Disable item being a candidate for default focus (e.g. used by title bar items)
ImGuiItemFlags_SelectableDontClosePopup=1<<5,// false // Disable MenuItem/Selectable() automatically closing their popup window
ImGuiItemFlags_MixedValue=1<<6,// false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
ImGuiItemFlags_ReadOnly=1<<7// false // [ALPHA] Allow hovering interactions but underlying value is not changed.
};
// Flags for ItemAdd()
// FIXME-NAV: _Focusable is _ALMOST_ what you would expect to be called '_TabStop' but because SetKeyboardFocusHere() works on items with no TabStop we distinguish Focusable from TabStop.
enumImGuiItemAddFlags_
{
ImGuiItemAddFlags_None=0,
ImGuiItemAddFlags_Focusable=1<<0// FIXME-NAV: In current/legacy scheme, Focusable+TabStop support are opt-in by widgets. We will transition it toward being opt-out, so this flag is expected to eventually disappear.
ImGuiItemFlags_ReadOnly=1<<7,// false // [ALPHA] Allow hovering interactions but underlying value is not changed.
ImGuiItemFlags_Inputable=1<<8// false // [WIP] Auto-activate item when focused. Currently only used and supported by a few items before it becomes a generic feature.
};
// Storage for LastItem data
@ -770,7 +763,7 @@ enum ImGuiItemStatusFlags_
{
ImGuiItemStatusFlags_None=0,
ImGuiItemStatusFlags_HoveredRect=1<<0,// Mouse position is within item rectangle (does NOT mean that the window is in correct z-order and can be hovered!, this is only one part of the most-common IsItemHovered test)
ImGuiItemStatusFlags_HasDisplayRect=1<<1,// window->DC.LastItemDisplayRect is valid
ImGuiItemStatusFlags_HasDisplayRect=1<<1,// g.LastItemData.DisplayRect is valid
ImGuiItemStatusFlags_Edited=1<<2,// Value exposed by item was edited in the current frame (should match the bool return value of most widgets)
ImGuiItemStatusFlags_ToggledSelection=1<<3,// Set when Selectable(), TreeNode() reports toggling a selection. We can't report "Selected", only state changes, in order to easily handle clipping with less issues.
ImGuiItemStatusFlags_ToggledOpen=1<<4,// Set when TreeNode() reports toggling their open state.
@ -1143,8 +1136,9 @@ struct ImGuiLastItemData
ImGuiIDID;
ImGuiItemFlagsInFlags;// See ImGuiItemFlags_
ImGuiItemStatusFlagsStatusFlags;// See ImGuiItemStatusFlags_
ImGuiActivateFlags_PreferInput=1<<0,// Favor activation that requires keyboard text input (e.g. for Slider/Drag). Default if keyboard is available.
ImGuiActivateFlags_PreferTweak=1<<1,// Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default if keyboard is not available.
ImGuiActivateFlags_TryToPreserveState=1<<2// Request widget to preserve state if it can (e.g. InputText will try to preserve cursor/selection)
};
enumImGuiNavHighlightFlags_
{
ImGuiNavHighlightFlags_None=0,
@ -1200,9 +1202,10 @@ enum ImGuiNavMoveFlags_
ImGuiNavMoveFlags_WrapX=1<<2,// On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left)
ImGuiNavMoveFlags_WrapY=1<<3,// This is not super useful but provided for completeness
ImGuiNavMoveFlags_AllowCurrentNavId=1<<4,// Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place)
ImGuiNavMoveFlags_AlsoScoreVisibleSet=1<<5,// Store alternate result in NavMoveResultLocalVisibleSet that only comprise elements that are already fully visible (used by PageUp/PageDown)
ImGuiNavMoveFlags_AlsoScoreVisibleSet=1<<5,// Store alternate result in NavMoveResultLocalVisible that only comprise elements that are already fully visible (used by PageUp/PageDown)
ImGuiNavMoveFlags_ScrollToEdge=1<<6,
ImGuiNavMoveFlags_Forwarded=1<<7
ImGuiNavMoveFlags_Forwarded=1<<7,
ImGuiNavMoveFlags_DebugNoResult=1<<8
};
enumImGuiNavLayer
@ -1686,34 +1689,40 @@ struct ImGuiContext
ImGuiIDNavActivateId;// ~~ (g.ActiveId == 0) && IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0, also set when calling ActivateItem()
ImGuiIDNavActivateInputId;// ~~ IsNavInputPressed(ImGuiNavInput_Input) ? NavId : 0; ImGuiActivateFlags_PreferInput will be set and NavActivateId will be 0.
ImGuiActivateFlagsNavActivateFlags;
ImGuiIDNavJustTabbedId;// Just tabbed to this id.
ImGuiIDNavJustMovedToId;// Just navigated to this id (result of a successfully MoveRequest).
ImGuiIDNavJustMovedToFocusScopeId;// Just navigated to this focus scope id (result of a successfully MoveRequest).
ImGuiKeyModFlagsNavJustMovedToKeyMods;
ImGuiIDNavNextActivateId;// Set by ActivateItem(), queued until next frame.
ImGuiActivateFlagsNavNextActivateFlags;
ImGuiInputSourceNavInputSource;// Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard.
ImRectNavScoringRect;// Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring.
intNavScoringCount;// Metrics for debugging
ImGuiNavLayerNavLayer;// Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later.
intNavIdTabCounter;// == NavWindow->DC.FocusIdxTabCounter at time of NavId processing
boolNavIdIsAlive;// Nav widget has been seen this frame ~~ NavRectRel is valid
boolNavMousePosDirty;// When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default)
boolNavDisableHighlight;// When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover)
boolNavDisableMouseHover;// When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again.
// Navigation: Init & Move Requests
boolNavAnyRequest;// ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()
boolNavInitRequest;// Init request for appearing window to select first item
boolNavInitRequestFromMove;
ImGuiIDNavInitResultId;// Init request result (first item of the window, or one for which SetItemDefaultFocus() was called)
ImRectNavInitResultRectRel;// Init request result rectangle (relative to parent window)
boolNavMoveRequest;// Move request for this frame
boolNavMoveRequestForwardToNextFrame;
ImGuiNavMoveFlagsNavMoveRequestFlags;
ImGuiKeyModFlagsNavMoveRequestKeyMods;
ImGuiDirNavMoveDir,NavMoveDirLast;// Direction of the move request (left/right/up/down), direction of the previous move request
boolNavMoveSubmitted;// Move request submitted, will process result on next NewFrame()
boolNavMoveScoringItems;// Move request submitted, still scoring incoming items
boolNavMoveForwardToNextFrame;
ImGuiNavMoveFlagsNavMoveFlags;
ImGuiKeyModFlagsNavMoveKeyMods;
ImGuiDirNavMoveDir;// Direction of the move request (left/right/up/down)
ImGuiDirNavMoveDirForDebug;
ImGuiDirNavMoveClipDir;// FIXME-NAV: Describe the purpose of this better. Might want to rename?
ImRectNavScoringRect;// Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring.
intNavScoringDebugCount;// Metrics for debugging
ImGuiNavItemDataNavMoveResultLocal;// Best move request candidate within NavWindow
ImGuiNavItemDataNavMoveResultLocalVisibleSet;// Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
ImGuiNavItemDataNavMoveResultLocalVisible;// Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
ImGuiNavItemDataNavMoveResultOther;// Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
@ -1771,7 +1780,7 @@ struct ImGuiContext
ImVector<ImGuiShrinkWidthItem>ShrinkWidthBuffer;
// Widget state
ImVec2 LastValidMousePos;
ImVec2MouseLastValidPos;
ImGuiInputTextStateInputTextState;
ImFontInputTextPasswordFont;
ImGuiIDTempInputId;// Temporary text input when CTRL+clicking on a slider, etc.
intCurrentTableIdx;// Current table index (into g.Tables)
ImGuiLayoutTypeLayoutType;
ImGuiLayoutTypeParentLayoutType;// Layout type of parent window at the time of Begin()
intFocusCounterRegular;// (Legacy Focus/Tabbing system) Sequential counter, start at -1 and increase as assigned via FocusableItemRegister() (FIXME-NAV: Needs redesign)
intFocusCounterRegular;// (Legacy Focus/Tabbing system) Sequential counter, start at -1 and increase when ImGuiItemFlags_Inputable (FIXME-NAV: Needs redesign)
intFocusCounterTabStop;// (Legacy Focus/Tabbing system) Same, but only count widgets which you can Tab through.
// If you have old/custom copy-and-pasted widgets that used FocusableItemRegister():
// (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool focused = FocusableItemRegister(...)'
// (New) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0'
// (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0'
// (New) IMGUI_VERSION_NUM >= 18411: using 'ItemAdd(..., ImGuiItemAddFlags_Inputable)' and 'bool focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0'
// Widget code are simplified as there's no need to call FocusableItemUnregister() while managing the transition from regular widget to TempInputText()
inlineboolFocusableItemRegister(ImGuiWindow*window,ImGuiIDid){IM_ASSERT(0);IM_UNUSED(window);IM_UNUSED(id);returnfalse;}// -> pass ImGuiItemAddFlags_Focusable flag to ItemAdd()
inlineboolFocusableItemRegister(ImGuiWindow*window,ImGuiIDid){IM_ASSERT(0);IM_UNUSED(window);IM_UNUSED(id);returnfalse;}// -> pass ImGuiItemAddFlags_Inputable flag to ItemAdd()
// Experimental: simple click (without moving) turns Drag into an InputText
// FIXME: Currently polling ImGuiConfigFlags_IsTouchScreen, may either poll an hypothetical ImGuiBackendFlags_HasKeyboard and/or an explicit drag settings.
// We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful.
// To do so we claim focus back, restore NavId and then process the movement request for yet another frame.
// This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth bothering)
floatextra=ImClamp(ImFabs(ta.x-tb.x)*0.30f,5.0f,30.0f);// add a bit of extra slack.
ta.x+=(window->Pos.x<child_menu_window->Pos.x)?-0.5f:+0.5f;// to avoid numerical issues
tb.y=ta.y+ImMax((tb.y-extra)-ta.y,-100.0f);// triangle is maximum 200 high to limit the slope and the bias toward large sub-menus // FIXME: Multiply by fb_scale?
tc.y=ta.y+ImMin((tc.y+extra)-ta.y,+100.0f);
floatextra=ImClamp(ImFabs(ta.x-tb.x)*0.30f,ref_unit*0.5f,ref_unit*2.5f);// add a bit of extra slack.
ta.x+=(window->Pos.x<child_menu_window->Pos.x)?-0.5f:+0.5f;// to avoid numerical issues (FIXME: ??)
tb.y=ta.y+ImMax((tb.y-extra)-ta.y,-ref_unit*8.0f);// triangle is maximum 200 high to limit the slope and the bias toward large sub-menus // FIXME: Multiply by fb_scale?