feat: reimplement on-screen keyboard for monitor search
UI.TextEntry requires keyboard input which monitors don't have. Replaced it with the original touch-friendly approach: - Search bar shows query text with toggle button (? / X) - Tapping the search row opens an on-screen keyboard overlay - 3-row QWERTY layout with Bksp, Done, Space, Clr keys - Keyboard overlays the bottom status bars when active - All key zones use touch hit-testing for monitor_touch events
This commit is contained in:
@@ -40,6 +40,7 @@ local smelterPage = nil
|
||||
local selectedAmount = 1
|
||||
local amountOptions = {1, 4, 8, 16, 32, 64}
|
||||
local searchQuery = ""
|
||||
local showKeyboard = false
|
||||
local smelterView = "status"
|
||||
|
||||
-------------------------------------------------
|
||||
@@ -263,17 +264,45 @@ local function buildMainPage()
|
||||
searchRow = UI.Window {
|
||||
x = 1, y = 6, ex = -1, height = 1,
|
||||
backgroundColor = colors.black,
|
||||
},
|
||||
|
||||
searchEntry = UI.TextEntry {
|
||||
x = 3, y = 6,
|
||||
ex = '45%',
|
||||
shadowText = "search...",
|
||||
backgroundColor = colors.black,
|
||||
backgroundFocusColor = colors.gray,
|
||||
textColor = colors.white,
|
||||
shadowTextColor = colors.gray,
|
||||
limit = 30,
|
||||
draw = function(self)
|
||||
self:clear(colors.black)
|
||||
-- Keyboard toggle button
|
||||
local kbLabel = showKeyboard and " X " or " ? "
|
||||
local kbBg = showKeyboard and colors.red or colors.purple
|
||||
self:write(1, 1, kbLabel, kbBg, colors.white)
|
||||
-- Search query display
|
||||
local fieldW = math.floor(self.width * 0.4)
|
||||
if fieldW < 10 then fieldW = 10 end
|
||||
local queryDisplay = searchQuery
|
||||
if showKeyboard then
|
||||
queryDisplay = queryDisplay .. "|"
|
||||
elseif queryDisplay == "" then
|
||||
queryDisplay = "search..."
|
||||
end
|
||||
local displayText = queryDisplay:sub(1, fieldW)
|
||||
displayText = displayText .. string.rep("_", math.max(0, fieldW - #displayText))
|
||||
local tc = (searchQuery == "" and not showKeyboard) and colors.gray or colors.white
|
||||
self:write(5, 1, displayText, colors.black, tc)
|
||||
end,
|
||||
eventHandler = function(self, event)
|
||||
if event.type == 'mouse_click' then
|
||||
showKeyboard = not showKeyboard
|
||||
local page = self:getPage()
|
||||
if showKeyboard then
|
||||
UI.Window.enable(page.keyboard)
|
||||
page.keyboard:draw()
|
||||
else
|
||||
page.keyboard:disable()
|
||||
page.alertBar:draw()
|
||||
page.footerBar:draw()
|
||||
page.bottomBar:draw()
|
||||
end
|
||||
self:draw()
|
||||
page:sync()
|
||||
return true
|
||||
end
|
||||
return UI.Window.eventHandler(self, event)
|
||||
end,
|
||||
},
|
||||
|
||||
refreshBtn = UI.Button {
|
||||
@@ -383,15 +412,118 @@ local function buildMainPage()
|
||||
end,
|
||||
},
|
||||
|
||||
-- On-screen keyboard overlay (bottom 3 rows; starts disabled)
|
||||
keyboard = UI.Window {
|
||||
x = 1, ex = -1, ey = -1, height = 3,
|
||||
backgroundColor = colors.black,
|
||||
enable = function() end, -- prevent auto-enable; toggled manually
|
||||
draw = function(self)
|
||||
self:clear(colors.black)
|
||||
local kbDefs = {
|
||||
{ keys = {"Q","W","E","R","T","Y","U","I","O","P"}, specials = {{ label = " Bksp ", bg = colors.red, action = "kb_bksp" }} },
|
||||
{ keys = {"A","S","D","F","G","H","J","K","L"}, specials = {{ label = " Done ", bg = colors.green, action = "kb_done" }} },
|
||||
{ keys = {"Z","X","C","V","B","N","M"}, specials = {
|
||||
{ label = " Space ", bg = colors.lightGray, action = "kb_space" },
|
||||
{ label = " Clr ", bg = colors.orange, action = "kb_clear" },
|
||||
}},
|
||||
}
|
||||
self._zones = {}
|
||||
local keyW = 3
|
||||
local keyGap = 1
|
||||
for rowIdx, def in ipairs(kbDefs) do
|
||||
local y = rowIdx
|
||||
local keysW = #def.keys * keyW + math.max(0, #def.keys - 1) * keyGap
|
||||
local specialsW = 0
|
||||
for _, sp in ipairs(def.specials) do
|
||||
specialsW = specialsW + keyGap + #sp.label
|
||||
end
|
||||
local rowW = keysW + specialsW
|
||||
local x = math.floor((self.width - rowW) / 2) + 1
|
||||
-- Draw letter keys
|
||||
for ki, key in ipairs(def.keys) do
|
||||
self:write(x, y, " " .. key .. " ", colors.gray, colors.white)
|
||||
table.insert(self._zones, { x1 = x, y1 = y, x2 = x + keyW - 1, y2 = y, action = "kb_key", data = key:lower() })
|
||||
x = x + keyW
|
||||
if ki < #def.keys then x = x + keyGap end
|
||||
end
|
||||
-- Draw special keys
|
||||
for _, sp in ipairs(def.specials) do
|
||||
x = x + keyGap
|
||||
self:write(x, y, sp.label, sp.bg, colors.white)
|
||||
table.insert(self._zones, { x1 = x, y1 = y, x2 = x + #sp.label - 1, y2 = y, action = sp.action })
|
||||
x = x + #sp.label
|
||||
end
|
||||
end
|
||||
end,
|
||||
eventHandler = function(self, event)
|
||||
if event.type == 'mouse_click' then
|
||||
if self._zones then
|
||||
for _, zone in ipairs(self._zones) do
|
||||
if event.x >= zone.x1 and event.x <= zone.x2
|
||||
and event.y >= zone.y1 and event.y <= zone.y2 then
|
||||
self:emit({ type = zone.action, data = zone.data, element = self })
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return true -- consume click even if no zone hit
|
||||
end
|
||||
return UI.Window.eventHandler(self, event)
|
||||
end,
|
||||
},
|
||||
|
||||
-- Notification overlay
|
||||
notification = UI.Notification {
|
||||
anchor = 'bottom',
|
||||
},
|
||||
|
||||
eventHandler = function(self, event)
|
||||
if event.type == 'text_change' then
|
||||
searchQuery = event.text or ""
|
||||
if event.type == 'kb_key' then
|
||||
if #searchQuery < 30 then
|
||||
searchQuery = searchQuery .. event.data
|
||||
end
|
||||
D.refreshItemGrid()
|
||||
self.searchRow:draw()
|
||||
self.footerBar:draw()
|
||||
self:sync()
|
||||
return true
|
||||
|
||||
elseif event.type == 'kb_bksp' then
|
||||
if #searchQuery > 0 then
|
||||
searchQuery = searchQuery:sub(1, -2)
|
||||
end
|
||||
D.refreshItemGrid()
|
||||
self.searchRow:draw()
|
||||
self.footerBar:draw()
|
||||
self:sync()
|
||||
return true
|
||||
|
||||
elseif event.type == 'kb_space' then
|
||||
if #searchQuery < 30 then
|
||||
searchQuery = searchQuery .. " "
|
||||
end
|
||||
D.refreshItemGrid()
|
||||
self.searchRow:draw()
|
||||
self.footerBar:draw()
|
||||
self:sync()
|
||||
return true
|
||||
|
||||
elseif event.type == 'kb_done' then
|
||||
showKeyboard = false
|
||||
self.keyboard:disable()
|
||||
self.searchRow:draw()
|
||||
self.alertBar:draw()
|
||||
self.footerBar:draw()
|
||||
self.bottomBar:draw()
|
||||
self:sync()
|
||||
return true
|
||||
|
||||
elseif event.type == 'kb_clear' then
|
||||
searchQuery = ""
|
||||
showKeyboard = false
|
||||
self.keyboard:disable()
|
||||
D.refreshItemGrid()
|
||||
self.searchRow:draw()
|
||||
self.alertBar:draw()
|
||||
self.footerBar:draw()
|
||||
self.bottomBar:draw()
|
||||
|
||||
Reference in New Issue
Block a user