jalovatt / scythe

Lua GUI library and utility framework for Reaper scripts (formerly Lokasenna_GUI)
https://jalovatt.github.io/scythe
MIT License
26 stars 5 forks source link

implementing tab between Textbox #168

Open jamesb93 opened 3 years ago

jamesb93 commented 3 years ago

Hi @jalovatt,

I realise that the project is on an indefinite hiatus but I wanted to see if you could offer any help with a feature I'd like to implement on my own fork of the library. As it stands textbox's can not be navigated with tabs. So far, I've implemented this:

  [Const.chars.TAB] = function(self, state)
    -- Store the state of another tab and then defocus this one and focus that one
    -- self.focus = false
    -- self.next.focus = true
    -- tab functionality has been temporarily removed because it was broken anyway
    -- GUI.tab_to_next(self)
    state.shouldLoseFocus = self
    self:redraw()
    self.focus = false
    if self.next then self.next.focus = true end
  end,

Which actually works in part by passing another textbox to a value I've created called next. That way you can create quasi-links between objects. When you press tab ideally it shifts the focus to whatever is stored in next. The problem with this is that the focus logic seems to be broken for typing and when pressing tab then de-selecting.

image

I can see in the comments that you had this implemented but it wasn't working so I'd be curious what work you did on it so that I might iterate on that.

jalovatt commented 3 years ago

If you look at v2 you can see what I had working there. If memory serves you had to manually set a tab index on the elements you wanted to be tabbable, then it would just increment through those.

I took it out for v3 because a) I wanted to have it determined automatically, to some extent, but b) most elements don't support the keyboard so that would have to be sorted out first so that the entire UI could be keyboard-friendly.

Looking at your code, I think you might want to look at how the UI manages focus, starting here: https://github.com/jalovatt/scythe/blob/86dfe4ea2fb20812cde67b447ae54ea254235174/library/gui/window.lua#L375 . Just setting state.elementToFocus will update the focus on the next loop, including any event handlers for losing focus, etc like the text box has.

jamesb93 commented 3 years ago

This is very helpful, thanks.

From what I can gather this should be enough:

  [Const.chars.TAB] = function(self, state)
    -- Store the state of another tab and then defocus this one and focus that one
    -- self.focus = false
    -- self.next.focus = true
    -- tab functionality has been temporarily removed because it was broken anyway
    -- GUI.tab_to_next(self)
    state.shouldLoseFocus = self
    self:redraw()
    -- self.focus = false
    if self.next then
      -- self.next.focus = true
      state.elementToFocus = self.next
    end
  end,

The right box drops focus but nothing gets focused anymore so I assume I need to dig deeper into the window.lua code to see where it's not getting the focus right.

jalovatt commented 3 years ago

state.elementToFocus doesn't exist. Looking at the code now, I don't think there actually is a way to focus a new element; just losing focus on one.

I think you just need to add:

  -- window.lua, line 491
  if state.shouldLoseFocus then elementToLoseFocus = state.shouldLoseFocus end
+ if state.elementToFocus then elementToFocus = state.elementToFocus end