Skip to content

Commit bd77a71

Browse files
CoreyRDeanclaude
andcommitted
Loom fix-up 2: bypass F-UI's broken Tab M_SETINDEX; reposition ribbon
Two remaining bugs after the first fix-up. Both surfaced clearly from the user's smoke test: 1. CROSS-REF / PALETTE / ATLAS: "the correct element is selected but the tab doesn't switch." F-UI's Tab `Case M_SETINDEX` handler does set `Tab\actTabPage` internally, but the visible tab does not switch when invoked from outside the click path. Suspected cause: the implementation has a nested-For-loop iterator with both loops named `tabp`: For tabp.TabPage = Each TabPage ' outer If Count = Param1 Tab\actTabPage = tabp For tabp.TabPage = Each TabPage ' inner, shadows outer ...rebuild every page... Next Exit In non-Strict Blitz, `For X = Each Type` implicitly declares X at function scope; the inner re-declaration likely corrupts state in a way that nullifies the assignment by the time the next FUI_Update renders. Bypass M_SETINDEX with `GUE_SetActiveTab(idx)` in CommandPalette.bb that does the same work but with distinct iterator names (`probe` for the search, `sib` for the rebuild pass), then call it from GUE_JumpToEntity in place of `FUI_SendMessage(TabMain, M_SETINDEX, tabIdx)`. Still fires the Case TabMain event afterward so the existing leave/enter dispatcher runs its hide/show logic. 2. CONSCIENCE RIBBON: Issues button at Y=24 is invisible. The tab title strip occupies Y=20..40 (TABPAGE_HEIGHT = 20), so Y=24 puts the button behind that strip and behind whatever the tabs render. Y=2 (previous attempt) was inside the menu bar's click-capture zone. There is no usable top strip in WMain that's free of both regions. Move to the bottom of WMain instead: rowY = sh - 22. The bottom strip is the only horizontal band that has nothing in it on any tab. Computed from GraphicsHeight() at Init so it works in any window size. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 9c937af commit bd77a71

2 files changed

Lines changed: 68 additions & 15 deletions

File tree

src/Modules/CommandPalette.bb

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,18 @@ Function GUE_JumpToEntity(kind$, refID)
357357

358358
If tabIdx = 0 Or picker = 0 Then Return
359359

360-
// Visible tab switch + ask the dispatcher to run its leave/enter logic.
361-
FUI_SendMessage(TabMain, M_SETINDEX, tabIdx)
360+
// Visible tab switch.
361+
//
362+
// F-UI's M_SETINDEX on Tab does set actTabPage internally, but in
363+
// practice the tab does NOT visibly switch when invoked from outside
364+
// the normal click path (suspected cause: nested-For-loop iterator
365+
// shadowing in F-UI's M_SETINDEX implementation). Bypass M_SETINDEX
366+
// and set the active page directly, then rebuild every page so the
367+
// visuals refresh on the next render.
368+
GUE_SetActiveTab(tabIdx)
369+
370+
// Ask the existing Case TabMain dispatcher to run its leave/enter
371+
// hide/show logic next frame.
362372
FUI_CreateEvent(TabMain, Str(tabIdx))
363373

364374
// Walk the picker items to find the one whose stored data matches.
@@ -381,3 +391,44 @@ Function GUE_JumpToEntity(kind$, refID)
381391
// Fire the picker-change event so the downstream handler runs.
382392
FUI_CreateEvent(picker, "")
383393
End Function
394+
395+
396+
// =============================================================================
397+
// GUE_SetActiveTab -- direct active-tab assignment, bypassing F-UI's
398+
// M_SETINDEX whose nested-For-loop iterator shadowing was preventing the
399+
// visible tab switch when called from outside the click path.
400+
//
401+
// Walks every TabPage looking for the (tabIdx)th page owned by TabMain (1-
402+
// indexed in the same order tabs were created with FUI_TabPage). Assigns it
403+
// to the Tab's actTabPage and rebuilds all sibling TabPage visuals so the
404+
// next render shows the new tab active and the others inactive.
405+
//
406+
// We use distinct iterator variable names (`probe` then `sib`) instead of
407+
// reusing one, which was the suspected cause of F-UI's M_SETINDEX failing.
408+
// =============================================================================
409+
Function GUE_SetActiveTab(tabIdx)
410+
Local TM.Tab = Object.Tab(TabMain)
411+
If TM = Null Then Return
412+
413+
Local count = 1
414+
Local target.TabPage = Null
415+
For probe.TabPage = Each TabPage
416+
If probe\Owner = TM
417+
If count = tabIdx
418+
target = probe
419+
Exit
420+
EndIf
421+
count = count + 1
422+
EndIf
423+
Next
424+
425+
If target = Null Then Return
426+
427+
TM\actTabPage = target
428+
429+
For sib.TabPage = Each TabPage
430+
If sib\Owner = TM
431+
FUI_BuildTabPage sib
432+
EndIf
433+
Next
434+
End Function

src/Modules/ConscienceRibbon.bb

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,13 @@ Global CR_Open = False
4747
// Layout
4848
Const CR_RIBBON_W = 460
4949
Const CR_RIBBON_H = 18
50-
// Y=24 sits just below the menu bar (which owns Y=0..20). Y=2 was inside the
51-
// menu bar's mouse-capture zone, which made the Issues button unclickable
52-
// even though it rendered. Y=24 overlays the right side of the tab title
53-
// strip, where no tab title extends, so there's no visual collision.
54-
Const CR_RIBBON_Y = 24
50+
// Placement history:
51+
// Y=2 -- inside menu bar's mouse-capture zone -> Issues button unclickable
52+
// Y=24 -- inside tab title strip (Y=20..40) -> button invisible behind it
53+
// Bottom -- the only horizontal strip in WMain with nothing in it on any tab.
54+
//
55+
// We compute the actual Y at Init time from GraphicsHeight() so this works
56+
// whether GUE is launched fullscreen or in a window of any size.
5557

5658
Const CR_FW_W = 600
5759
Const CR_FW_H = 380
@@ -87,19 +89,19 @@ Function Conscience_Init()
8789

8890
CR_Findings = CreateList()
8991

90-
// Place the status label in the top-right, in the menu bar's empty real
91-
// estate. Owned by WMain so it sits over the menu strip (the menu titles
92-
// start at the left and don't extend this far).
92+
// Bottom-right of WMain -- the only horizontal strip with nothing in it
93+
// on any tab (the menu bar Y=0..20 captures clicks, the tab title strip
94+
// Y=20..40 renders on top of overlays, the tab content area has gadgets).
9395
Local sw = GraphicsWidth()
96+
Local sh = GraphicsHeight()
97+
Local rowY = sh - CR_RIBBON_H - 4
9498
Local startX = sw - CR_RIBBON_W - 10
9599

96-
CR_LblStatus = FUI_Label(WMain, startX, CR_RIBBON_Y + 2, "World ready.", ALIGN_LEFT)
100+
CR_LblStatus = FUI_Label(WMain, startX, rowY + 2, "World ready.", ALIGN_LEFT)
97101

98102
// "Issues..." button -- shown at all times so users learn it exists. Use
99-
// CS_BORDER (the F-UI default) so the button is visibly clickable; passing
100-
// Flags=0 strips the border AND was the suspected cause of the click
101-
// hit-test failing.
102-
CR_BtnIssues = FUI_Button(WMain, sw - 90, CR_RIBBON_Y, 80, CR_RIBBON_H, "Issues...", "", 0, CS_BORDER)
103+
// CS_BORDER (the F-UI default) so the button is visibly clickable.
104+
CR_BtnIssues = FUI_Button(WMain, sw - 90, rowY, 80, CR_RIBBON_H, "Issues...", "", 0, CS_BORDER)
103105

104106
// Hidden findings modal.
105107
Local px = (sw - CR_FW_W) / 2

0 commit comments

Comments
 (0)