Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Plan9k Desktop Environment
- Single file desktop.lua
- ]]
- local component = require("component")
- local computer = require("computer")
- local term = require("term")
- local event = require("event")
- local fs = require("filesystem")
- local unicode = require("unicode")
- -- Desktop Environment
- local Desktop = {
- windows = {},
- widgets = {},
- mouseX = 1,
- mouseY = 1,
- screenWidth = 0,
- screenHeight = 0,
- backgroundColor = 0x2D2D2D,
- foregroundColor = 0xFFFFFF,
- running = true
- }
- -- Initialize screen dimensions
- function Desktop:init()
- self.screenWidth, self.screenHeight = term.getViewport()
- term.clear()
- end
- -- Window class
- local Window = {}
- Window.__index = Window
- function Window:new(x, y, width, height, title)
- local window = {
- x = x or 5,
- y = y or 3,
- width = width or 30,
- height = height or 15,
- title = title or "Window",
- content = {},
- visible = true,
- active = false,
- borderColor = 0x444444,
- titleColor = 0x1E90FF
- }
- setmetatable(window, Window)
- return window
- end
- function Window:draw()
- if not self.visible then return end
- -- Draw border
- term.setBackground(self.borderColor)
- for i = 0, self.width + 1 do
- term.setCursor(self.x + i, self.y)
- term.write(" ")
- term.setCursor(self.x + i, self.y + self.height + 1)
- term.write(" ")
- end
- for i = 0, self.height + 1 do
- term.setCursor(self.x, self.y + i)
- term.write(" ")
- term.setCursor(self.x + self.width + 1, self.y + i)
- term.write(" ")
- end
- -- Draw title bar
- term.setBackground(self.titleColor)
- term.setForeground(0xFFFFFF)
- term.setCursor(self.x + 1, self.y)
- local titleText = string.sub(self.title, 1, self.width - 2)
- term.write(" " .. titleText .. string.rep(" ", self.width - #titleText - 1))
- -- Draw content area
- term.setBackground(0x000000)
- for y = 1, self.height do
- term.setCursor(self.x + 1, self.y + y)
- term.write(string.rep(" ", self.width))
- end
- -- Draw content
- term.setForeground(0xFFFFFF)
- for i, line in ipairs(self.content) do
- if i <= self.height then
- term.setCursor(self.x + 2, self.y + i)
- term.write(string.sub(line, 1, self.width - 2))
- end
- end
- end
- function Window:setContent(content)
- if type(content) == "string" then
- self.content = {}
- for line in content:gmatch("[^\r\n]+") do
- table.insert(self.content, line)
- end
- elseif type(content) == "table" then
- self.content = content
- end
- end
- -- Widget class
- local Widget = {}
- Widget.__index = Widget
- function Widget:new(x, y, width, height)
- local widget = {
- x = x or 1,
- y = y or 1,
- width = width or 10,
- height = height or 1,
- visible = true,
- backgroundColor = 0x333333,
- foregroundColor = 0xFFFFFF
- }
- setmetatable(widget, Widget)
- return widget
- end
- function Widget:draw()
- if not self.visible then return end
- term.setBackground(self.backgroundColor)
- term.setForeground(self.foregroundColor)
- end
- -- Clock widget
- local ClockWidget = {}
- ClockWidget.__index = setmetatable(ClockWidget, {__index = Widget})
- function ClockWidget:new(x, y)
- local widget = Widget:new(x, y, 8, 1)
- setmetatable(widget, ClockWidget)
- return widget
- end
- function ClockWidget:draw()
- Widget.draw(self)
- local time = os.date("%H:%M:%S")
- term.setCursor(self.x, self.y)
- term.write(time)
- end
- -- Taskbar widget
- local TaskbarWidget = {}
- TaskbarWidget.__index = setmetatable(TaskbarWidget, {__index = Widget})
- function TaskbarWidget:new()
- local widget = Widget:new(1, Desktop.screenHeight, Desktop.screenWidth, 1)
- widget.backgroundColor = 0x1E1E1E
- setmetatable(widget, TaskbarWidget)
- return widget
- end
- function TaskbarWidget:draw()
- Widget.draw(self)
- term.setCursor(1, self.y)
- term.write("_APPS_|_FILES_|_SETTINGS_|_EXIT_")
- end
- -- Desktop methods
- function Desktop:addWindow(window)
- table.insert(self.windows, window)
- end
- function Desktop:addWidget(widget)
- table.insert(self.widgets, widget)
- end
- function Desktop:drawBackground()
- term.setBackground(self.backgroundColor)
- term.clear()
- -- Draw wallpaper pattern
- term.setForeground(0x444444)
- for y = 1, self.screenHeight - 1 do
- for x = 1, self.screenWidth, 2 do
- term.setCursor(x, y)
- term.write("·")
- end
- end
- -- Draw title
- term.setForeground(0x1E90FF)
- term.setCursor(5, 2)
- term.write("PLAN9K DESKTOP")
- term.setForeground(0xAAAAAA)
- term.setCursor(5, 3)
- term.write("Click and drag windows, press 'q' to quit")
- end
- function Desktop:draw()
- self:drawBackground()
- -- Draw widgets
- for _, widget in ipairs(self.widgets) do
- widget:draw()
- end
- -- Draw windows (in reverse order for proper layering)
- for i = #self.windows, 1, -1 do
- self.windows[i]:draw()
- end
- end
- function Desktop:handleClick(x, y)
- -- Check if clicked on taskbar
- if y == self.screenHeight then
- if x >= 1 and x <= 6 then
- -- Apps button
- local appWindow = Window:new(10, 5, 25, 10, "Applications")
- appWindow:setContent({"File Manager", "Text Editor", "Terminal", "Calculator", "", "Click to launch..."})
- self:addWindow(appWindow)
- elseif x >= 8 and x <= 14 then
- -- Files button
- local fileWindow = Window:new(15, 8, 30, 12, "File Browser")
- appWindow:setContent({"/", "├── bin/", "├── etc/", "├── home/", "├── tmp/", "└── usr/"})
- self:addWindow(fileWindow)
- elseif x >= 16 and x <= 25 then
- -- Settings button
- local settingsWindow = Window:new(20, 6, 20, 8, "Settings")
- settingsWindow:setContent({"Display", "Network", "Sound", "Users"})
- self:addWindow(settingsWindow)
- elseif x >= 27 and x <= 32 then
- -- Exit button
- self.running = false
- end
- return
- end
- -- Check if clicked on window title bars
- for i, window in ipairs(self.windows) do
- if x >= window.x and x <= window.x + window.width + 2 and
- y >= window.y and y <= window.y + 1 then
- -- Move window to front
- table.remove(self.windows, i)
- table.insert(self.windows, 1, window)
- break
- end
- end
- end
- function Desktop:update()
- -- Update widgets
- for _, widget in ipairs(self.widgets) do
- if widget.update then
- widget:update()
- end
- end
- end
- function Desktop:run()
- self:init()
- -- Add default widgets
- self:addWidget(ClockWidget:new(self.screenWidth - 8, 1))
- self:addWidget(TaskbarWidget:new())
- -- Add sample windows
- local welcomeWindow = Window:new(5, 5, 35, 8, "Welcome")
- welcomeWindow:setContent({
- "Welcome to Plan9k Desktop!",
- "",
- "Features:",
- "• Window management",
- "• Clickable taskbar",
- "• Real-time clock",
- "• Interactive interface",
- "",
- "Press 'q' to quit"
- })
- self:addWindow(welcomeWindow)
- -- Main event loop
- while self.running do
- self:draw()
- self:update()
- local _, eventType, _, eventData, _, button = event.pull(0.1)
- if eventType == "touch" or eventType == "click" then
- local x, y = eventData, button
- self:handleClick(x, y)
- elseif eventType == "key_down" then
- if eventData == 16 then -- 'q' key
- self.running = false
- end
- elseif eventType == "interrupted" then
- self.running = false
- end
- end
- term.clear()
- term.setCursor(1, 1)
- print("Desktop exited.")
- end
- -- Run the desktop
- if ... == nil then
- Desktop:run()
- end
- return Desktop
Advertisement
Add Comment
Please, Sign In to add comment