Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Desktop Module for SimpleOS
- local ui = require("os.ui")
- local apps = require("os.apps")
- local desktop = {}
- -- State
- local running = true
- local menuOpen = false
- local menuType = nil -- "start" or "context" or "appmenu"
- local menuX, menuY = 1, 1
- local selectedApp = nil
- local dialogOpen = false
- local dialogType = nil
- local dialogInputs = {}
- local activeInput = 1
- -- Icon grid settings
- local iconWidth = 7
- local iconHeight = 4
- local iconsPerRow = 6
- local iconStartX = 2
- local iconStartY = 2
- -- Get icon position
- local function getIconPos(index)
- local row = math.floor((index - 1) / iconsPerRow)
- local col = (index - 1) % iconsPerRow
- local x = iconStartX + col * iconWidth
- local y = iconStartY + row * iconHeight
- return x, y
- end
- -- Get icon at click position
- local function getIconAt(clickX, clickY)
- local appList = apps.getAll()
- for i, app in ipairs(appList) do
- local x, y = getIconPos(i)
- if ui.isInBounds(clickX, clickY, x, y, 5, 3) then
- return i
- end
- end
- return nil
- end
- -- Draw desktop background
- local function drawBackground()
- local w, h = ui.getSize()
- ui.drawBox(1, 1, w, h - 1, ui.colors.desktop)
- end
- -- Draw taskbar
- local function drawTaskbar()
- local w, h = ui.getSize()
- ui.drawBox(1, h, w, 1, ui.colors.taskbar)
- -- Start button
- term.setCursorPos(1, h)
- term.setBackgroundColor(colors.green)
- term.setTextColor(colors.white)
- term.write(" Start ")
- -- Clock
- local time = textutils.formatTime(os.time(), false)
- term.setCursorPos(w - #time, h)
- term.setBackgroundColor(ui.colors.taskbar)
- term.setTextColor(ui.colors.taskbarText)
- term.write(time)
- end
- -- Draw all icons
- local function drawIcons()
- local appList = apps.getAll()
- for i, app in ipairs(appList) do
- local x, y = getIconPos(i)
- ui.drawIcon(x, y, app.name, app.symbol)
- end
- end
- -- Draw start menu
- local function drawStartMenu()
- local w, h = ui.getSize()
- local menuWidth = 15
- local menuHeight = 6
- local x = 1
- local y = h - menuHeight
- ui.drawBox(x, y, menuWidth, menuHeight, ui.colors.menuBg)
- local items = {"New App", "Refresh", "Settings", "Shutdown"}
- term.setTextColor(ui.colors.menuText)
- for i, item in ipairs(items) do
- term.setBackgroundColor(ui.colors.menuBg)
- term.setCursorPos(x + 1, y + i)
- term.write(item)
- end
- menuX, menuY = x, y
- end
- -- Draw context menu (right-click on app)
- local function drawAppMenu(appIndex)
- local x, y = getIconPos(appIndex)
- local menuWidth = 12
- local menuHeight = 4
- -- Adjust position if menu would go off screen
- local w, h = ui.getSize()
- if x + menuWidth > w then x = w - menuWidth end
- if y + menuHeight > h - 1 then y = h - 1 - menuHeight end
- ui.drawBox(x, y, menuWidth, menuHeight, ui.colors.menuBg)
- local items = {"Run", "Edit", "Delete"}
- term.setTextColor(ui.colors.menuText)
- for i, item in ipairs(items) do
- term.setBackgroundColor(ui.colors.menuBg)
- term.setCursorPos(x + 1, y + i - 1)
- term.write(item)
- end
- menuX, menuY = x, y
- selectedApp = appIndex
- end
- -- Draw new app dialog
- local function drawNewAppDialog()
- local w, h = ui.getSize()
- local dialogWidth = 30
- local dialogHeight = 10
- local x = math.floor((w - dialogWidth) / 2)
- local y = math.floor((h - dialogHeight) / 2)
- ui.drawWindow(x, y, dialogWidth, dialogHeight, "New App")
- term.setBackgroundColor(ui.colors.window)
- term.setTextColor(colors.black)
- -- Name field
- term.setCursorPos(x + 2, y + 2)
- term.write("Name:")
- ui.drawInput(x + 9, y + 2, 18, dialogInputs.name or "", activeInput == 1)
- -- Symbol field
- term.setCursorPos(x + 2, y + 4)
- term.write("Icon:")
- ui.drawInput(x + 9, y + 4, 3, dialogInputs.symbol or "", activeInput == 2)
- -- Command field
- term.setCursorPos(x + 2, y + 6)
- term.write("Command:")
- ui.drawInput(x + 2, y + 7, 26, dialogInputs.command or "", activeInput == 3)
- -- Buttons
- ui.drawButton(x + 5, y + 9, 8, 1, "Save", colors.green, colors.white)
- ui.drawButton(x + 17, y + 9, 8, 1, "Cancel", colors.red, colors.white)
- return x, y, dialogWidth, dialogHeight
- end
- -- Draw edit app dialog
- local function drawEditAppDialog()
- return drawNewAppDialog() -- Same layout, different title handled in state
- end
- -- Refresh desktop
- local function refresh()
- drawBackground()
- drawTaskbar()
- drawIcons()
- if menuOpen then
- if menuType == "start" then
- drawStartMenu()
- elseif menuType == "appmenu" then
- drawAppMenu(selectedApp)
- end
- end
- if dialogOpen then
- if dialogType == "newapp" or dialogType == "editapp" then
- drawNewAppDialog()
- end
- end
- end
- -- Handle start menu click
- local function handleStartMenuClick(clickX, clickY)
- local w, h = ui.getSize()
- local menuHeight = 6
- local y = h - menuHeight
- local itemIndex = clickY - y
- if itemIndex >= 1 and itemIndex <= 4 then
- if itemIndex == 1 then
- -- New App
- dialogOpen = true
- dialogType = "newapp"
- dialogInputs = {name = "", symbol = "", command = ""}
- activeInput = 1
- elseif itemIndex == 2 then
- -- Refresh
- apps.load()
- elseif itemIndex == 3 then
- -- Settings (placeholder)
- elseif itemIndex == 4 then
- -- Shutdown
- running = false
- end
- end
- menuOpen = false
- end
- -- Handle app menu click
- local function handleAppMenuClick(clickX, clickY)
- local itemIndex = clickY - menuY + 1
- if itemIndex >= 1 and itemIndex <= 3 then
- if itemIndex == 1 then
- -- Run
- apps.run(selectedApp)
- elseif itemIndex == 2 then
- -- Edit
- local app = apps.get(selectedApp)
- dialogOpen = true
- dialogType = "editapp"
- dialogInputs = {
- name = app.name,
- symbol = app.symbol,
- command = app.command
- }
- activeInput = 1
- elseif itemIndex == 3 then
- -- Delete
- apps.remove(selectedApp)
- end
- end
- menuOpen = false
- selectedApp = nil
- end
- -- Handle dialog input
- local function handleDialogClick(clickX, clickY, dialogX, dialogY, dialogWidth, dialogHeight)
- -- Check input fields
- if ui.isInBounds(clickX, clickY, dialogX + 9, dialogY + 2, 18, 1) then
- activeInput = 1
- elseif ui.isInBounds(clickX, clickY, dialogX + 9, dialogY + 4, 3, 1) then
- activeInput = 2
- elseif ui.isInBounds(clickX, clickY, dialogX + 2, dialogY + 7, 26, 1) then
- activeInput = 3
- -- Check Save button
- elseif ui.isInBounds(clickX, clickY, dialogX + 5, dialogY + 9, 8, 1) then
- if dialogInputs.name ~= "" and dialogInputs.command ~= "" then
- if dialogType == "newapp" then
- apps.add(dialogInputs.name, dialogInputs.symbol, dialogInputs.command)
- elseif dialogType == "editapp" then
- apps.edit(selectedApp, dialogInputs.name, dialogInputs.symbol, dialogInputs.command)
- end
- end
- dialogOpen = false
- dialogInputs = {}
- selectedApp = nil
- -- Check Cancel button
- elseif ui.isInBounds(clickX, clickY, dialogX + 17, dialogY + 9, 8, 1) then
- dialogOpen = false
- dialogInputs = {}
- selectedApp = nil
- -- Check close button (X)
- elseif ui.isInBounds(clickX, clickY, dialogX + dialogWidth - 2, dialogY, 1, 1) then
- dialogOpen = false
- dialogInputs = {}
- selectedApp = nil
- end
- end
- -- Handle key input for dialog
- local function handleDialogKey(key)
- if key == keys.tab then
- activeInput = activeInput % 3 + 1
- elseif key == keys.enter then
- if dialogInputs.name ~= "" and dialogInputs.command ~= "" then
- if dialogType == "newapp" then
- apps.add(dialogInputs.name, dialogInputs.symbol, dialogInputs.command)
- elseif dialogType == "editapp" then
- apps.edit(selectedApp, dialogInputs.name, dialogInputs.symbol, dialogInputs.command)
- end
- end
- dialogOpen = false
- dialogInputs = {}
- selectedApp = nil
- elseif key == keys.escape then
- dialogOpen = false
- dialogInputs = {}
- selectedApp = nil
- end
- end
- -- Handle char input for dialog
- local function handleDialogChar(char)
- local field
- if activeInput == 1 then
- field = "name"
- if #dialogInputs.name < 10 then
- dialogInputs.name = dialogInputs.name .. char
- end
- elseif activeInput == 2 then
- field = "symbol"
- if #dialogInputs.symbol < 1 then
- dialogInputs.symbol = char
- end
- elseif activeInput == 3 then
- field = "command"
- if #dialogInputs.command < 50 then
- dialogInputs.command = dialogInputs.command .. char
- end
- end
- end
- -- Handle backspace for dialog
- local function handleDialogBackspace()
- if activeInput == 1 then
- dialogInputs.name = dialogInputs.name:sub(1, -2)
- elseif activeInput == 2 then
- dialogInputs.symbol = ""
- elseif activeInput == 3 then
- dialogInputs.command = dialogInputs.command:sub(1, -2)
- end
- end
- -- Main event handler
- local function handleEvent(event, p1, p2, p3)
- if event == "mouse_click" then
- local button, clickX, clickY = p1, p2, p3
- local w, h = ui.getSize()
- -- Handle dialog clicks
- if dialogOpen then
- local dialogWidth = 30
- local dialogHeight = 10
- local dialogX = math.floor((w - dialogWidth) / 2)
- local dialogY = math.floor((h - dialogHeight) / 2)
- handleDialogClick(clickX, clickY, dialogX, dialogY, dialogWidth, dialogHeight)
- return
- end
- -- Handle menu clicks
- if menuOpen then
- if menuType == "start" then
- handleStartMenuClick(clickX, clickY)
- elseif menuType == "appmenu" then
- handleAppMenuClick(clickX, clickY)
- end
- return
- end
- -- Check taskbar
- if clickY == h then
- -- Start button
- if clickX >= 1 and clickX <= 7 then
- menuOpen = true
- menuType = "start"
- end
- return
- end
- -- Check icons
- local iconIndex = getIconAt(clickX, clickY)
- if iconIndex then
- if button == 1 then
- -- Left click - run app
- apps.run(iconIndex)
- elseif button == 2 then
- -- Right click - show menu
- menuOpen = true
- menuType = "appmenu"
- selectedApp = iconIndex
- end
- else
- -- Click on empty space closes menus
- menuOpen = false
- end
- elseif event == "key" then
- if dialogOpen then
- handleDialogKey(p1)
- elseif p1 == keys.escape then
- menuOpen = false
- end
- elseif event == "char" then
- if dialogOpen then
- handleDialogChar(p1)
- end
- elseif event == "key_up" then
- -- Handle backspace
- if p1 == keys.backspace and dialogOpen then
- handleDialogBackspace()
- end
- end
- end
- -- Main run loop
- function desktop.run()
- running = true
- while running do
- refresh()
- local event, p1, p2, p3 = os.pullEvent()
- handleEvent(event, p1, p2, p3)
- end
- -- Clean exit
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- term.setCursorPos(1, 1)
- print("SimpleOS shutdown complete.")
- end
- return desktop
Advertisement
Add Comment
Please, Sign In to add comment