Advertisement
Ewgeniy

Untitled

Jul 1st, 2025
570
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.64 KB | None | 0 0
  1. -- tui.lua — Расширенная библиотека псевдографического интерфейса для OpenComputers
  2.  
  3. local component = require("component")
  4. local term = require("term")
  5. local event = require("event")
  6. local gpu = component.gpu
  7. local tui = {}
  8.  
  9. -- Цвета по умолчанию
  10. tui.bgColor = 0x000000
  11. tui.fgColor = 0xFFFFFF
  12.  
  13. function tui.setColors(fg, bg)
  14.   gpu.setForeground(fg or tui.fgColor)
  15.   gpu.setBackground(bg or tui.bgColor)
  16. end
  17.  
  18. function tui.clear(bg)
  19.   local w, h = gpu.getResolution()
  20.   tui.setColors(nil, bg or tui.bgColor)
  21.   gpu.fill(1, 1, w, h, " ")
  22. end
  23.  
  24. function tui.box(x, y, w, h, title)
  25.   gpu.set(x, y, "╔" .. string.rep("═", w - 2) .. "╗")
  26.   for i = 1, h - 2 do
  27.     gpu.set(x, y + i, "║" .. string.rep(" ", w - 2) .. "║")
  28.   end
  29.   gpu.set(x, y + h - 1, "╚" .. string.rep("═", w - 2) .. "╝")
  30.   if title then gpu.set(x + 2, y, title) end
  31. end
  32.  
  33. function tui.centerText(y, text)
  34.   local w = gpu.getResolution()
  35.   local x = math.floor((w - #text) / 2) + 1
  36.   gpu.set(x, y, text)
  37. end
  38.  
  39. function tui.button(x, y, label, active)
  40.   local pad = 2
  41.   local text = string.rep(" ", pad) .. label .. string.rep(" ", pad)
  42.   tui.setColors(active and 0x000000 or 0xFFFFFF, active and 0xFFFFFF or 0x444444)
  43.   gpu.set(x, y, text)
  44.   tui.setColors()
  45.   return {x = x, y = y, w = #text, h = 1, label = label}
  46. end
  47.  
  48. function tui.clicked(btn, x, y)
  49.   return x >= btn.x and x < btn.x + btn.w and y == btn.y
  50. end
  51.  
  52. function tui.input(x, y, w, default)
  53.   tui.setColors(0xFFFFFF, 0x000000)
  54.   gpu.fill(x, y, w, 1, " ")
  55.   gpu.set(x, y, default or "")
  56.   term.setCursor(x, y)
  57.   term.setCursorBlink(true)
  58.   local input = io.read()
  59.   term.setCursorBlink(false)
  60.   return input
  61. end
  62.  
  63. function tui.list(x, y, w, h, items, selected, keyControl)
  64.   selected = math.max(1, math.min(selected or 1, #items))
  65.   local offset = math.min(math.max(0, selected - math.floor(h / 2)), math.max(0, #items - h))
  66.  
  67.   local function drawList()
  68.     for i = 1, h do
  69.       local idx = offset + i
  70.       local item = items[idx]
  71.       if item then
  72.         local isSelected = (idx == selected)
  73.         tui.setColors(isSelected and 0x000000 or 0xFFFFFF, isSelected and 0xAAAAAA or 0x000000)
  74.         gpu.fill(x, y + i - 1, w, 1, " ")
  75.         gpu.set(x + 1, y + i - 1, item:sub(1, w - 2))
  76.       else
  77.         gpu.fill(x, y + i - 1, w, 1, " ")
  78.       end
  79.     end
  80.     tui.setColors()
  81.   end
  82.  
  83.   drawList()
  84.  
  85.   if keyControl then
  86.     while true do
  87.       local _, _, _, key = event.pull("key_down")
  88.       if key == 200 then -- up
  89.         if selected > 1 then selected = selected - 1 end
  90.       elseif key == 208 then -- down
  91.         if selected < #items then selected = selected + 1 end
  92.       elseif key == 28 then -- enter
  93.         break
  94.       end
  95.       offset = math.min(math.max(0, selected - math.floor(h / 2)), math.max(0, #items - h))
  96.       drawList()
  97.     end
  98.   end
  99.  
  100.   return selected
  101. end
  102.  
  103. function tui.toggle(x, y, label, state)
  104.   local onText = "Вкл"
  105.   local offText = "Выкл"
  106.   local status = state and onText or offText
  107.   local fullText = label .. ": [" .. status .. "]"
  108.   local width = #label + 2 + math.max(#onText, #offText) + 2
  109.   local bg = state and 0x00AA00 or 0xAA0000
  110.  
  111.   tui.setColors(0xFFFFFF, bg)
  112.   gpu.fill(x, y, width, 1, " ")
  113.   gpu.set(x + 1, y, fullText)
  114.   tui.setColors()
  115.  
  116.   return {x = x, y = y, w = width, h = 1, state = state}
  117. end
  118.  
  119. function tui.checkbox(x, y, label, checked)
  120.   local box = checked and "[x]" or "[ ]"
  121.   local text = box .. " " .. label
  122.   tui.setColors(0xFFFFFF, 0x000000)
  123.   gpu.set(x, y, text)
  124.   return {x = x, y = y, w = #text, h = 1, checked = checked, label = label}
  125. end
  126.  
  127. function tui.progressbar(x, y, w, percent)
  128.   local fill = math.floor((w - 2) * percent)
  129.   tui.setColors(0xFFFFFF, 0x222222)
  130.   gpu.set(x, y, "[")
  131.   gpu.set(x + w - 1, y, "]")
  132.   gpu.fill(x + 1, y, w - 2, 1, " ")
  133.   tui.setColors(0x00FF00, 0x00FF00)
  134.   gpu.fill(x + 1, y, fill, 1, " ")
  135.   tui.setColors()
  136. end
  137.  
  138. function tui.tabBar(x, y, tabs, current)
  139.   local tabPositions = {}
  140.   for i, name in ipairs(tabs) do
  141.     local active = (i == current)
  142.     tui.setColors(active and 0x000000 or 0xFFFFFF, active and 0xFFFFFF or 0x333333)
  143.     gpu.set(x, y, " " .. name .. " ")
  144.     table.insert(tabPositions, {x = x, w = #name + 2})
  145.     x = x + #name + 2
  146.   end
  147.   tui.setColors()
  148.   return tabPositions
  149. end
  150.  
  151. function tui.tabBarInteractive(x, y, tabs, current)
  152.   local w = gpu.getResolution()
  153.  
  154.   local function draw()
  155.     local cx = x
  156.     for i, name in ipairs(tabs) do
  157.       local active = (i == current)
  158.       tui.setColors(active and 0x000000 or 0xFFFFFF, active and 0xFFFFFF or 0x333333)
  159.       gpu.set(cx, y, " " .. name .. " ")
  160.       cx = cx + #name + 2
  161.     end
  162.     tui.setColors()
  163.   end
  164.  
  165.   while true do
  166.     draw()
  167.     local _, _, _, key = event.pull("key_down")
  168.     if key == 203 then -- влево
  169.       current = current > 1 and current - 1 or #tabs
  170.     elseif key == 205 then -- вправо
  171.       current = current < #tabs and current + 1 or 1
  172.     elseif key == 28 then -- Enter
  173.       break
  174.     end
  175.   end
  176.  
  177.   return current
  178. end
  179.  
  180. function tui.popup(x, y, w, h, lines)
  181.   tui.setColors(0xFFFFFF, 0x0000AA)
  182.   tui.box(x, y, w, h, " ")
  183.   for i, line in ipairs(lines) do
  184.     if i + y < y + h - 1 then
  185.       gpu.set(x + 1, y + i, line:sub(1, w - 2))
  186.     end
  187.   end
  188.   tui.setColors()
  189. end
  190.  
  191. function tui.toast(text, duration)
  192.   local w, h = gpu.getResolution()
  193.   local x = math.floor((w - #text) / 2)
  194.   local y = h
  195.   tui.setColors(0xFFFFFF, 0x880000)
  196.   gpu.set(x, y, text)
  197.   os.sleep(duration or 2)
  198.   gpu.fill(x, y, #text, 1, " ")
  199.   tui.setColors()
  200. end
  201.  
  202. -- Обработка переключения вкладок и списка по клавишам, без блокировки
  203. -- state = { currentTab = 1, selectedItem = 1, tabs = {...}, items = {...} }
  204. function tui.updateTabsAndList(state, key)
  205.   local tabsCount = #state.tabs
  206.   local listCount = #state.items
  207.  
  208.   if key == 203 then -- влево
  209.     state.currentTab = (state.currentTab - 2) % tabsCount + 1
  210.     if state.currentTab ~= 2 then
  211.       state.selectedItem = 1
  212.     end
  213.   elseif key == 205 then -- вправо
  214.     state.currentTab = state.currentTab % tabsCount + 1
  215.     if state.currentTab ~= 2 then
  216.       state.selectedItem = 1
  217.     end
  218.   elseif state.currentTab == 2 then
  219.     if key == 200 then -- вверх
  220.       if state.selectedItem > 1 then
  221.         state.selectedItem = state.selectedItem - 1
  222.       end
  223.     elseif key == 208 then -- вниз
  224.       if state.selectedItem < listCount then
  225.         state.selectedItem = state.selectedItem + 1
  226.       end
  227.     end
  228.   end
  229.  
  230.   return state
  231. end
  232.  
  233. -- Отрисовка вкладок и списка в зависимости от состояния
  234. function tui.drawTabsAndList(state, x, y, w, h)
  235.   tui.tabBar(x, y, state.tabs, state.currentTab)
  236.   if state.currentTab == 2 then
  237.     tui.list(x, y + 2, w, h, state.items, state.selectedItem)
  238.   else
  239.     tui.clear()
  240.     tui.centerText(y + 4, "Вкладка: " .. state.tabs[state.currentTab])
  241.   end
  242. end
  243.  
  244. function tui.confirmDialog(title, text)
  245.   local w, h = 40, 7
  246.   local sw, sh = gpu.getResolution()
  247.   local x = math.floor((sw - w) / 2)
  248.   local y = math.floor((sh - h) / 2)
  249.  
  250.   tui.box(x, y, w, h, title)
  251.   tui.setColors(0xFFFFFF, 0x000000)
  252.   gpu.set(x + 2, y + 2, text)
  253.  
  254.   local yesBtn = tui.button(x + 6, y + 4, "Да", true)
  255.   local noBtn = tui.button(x + w - 10, y + 4, "Нет", false)
  256.  
  257.   while true do
  258.     local _, _, cx, cy = event.pull("touch")
  259.     if tui.clicked(yesBtn, cx, cy) then
  260.       return true
  261.     elseif tui.clicked(noBtn, cx, cy) then
  262.       return false
  263.     end
  264.   end
  265. end
  266.  
  267.  
  268.  
  269. return tui
  270.  
Tags: tui
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement