Orion09

desktop4plan9k

Oct 5th, 2025
20
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.16 KB | None | 0 0
  1. --[[
  2. Plan9k Desktop Environment
  3. Single file desktop.lua
  4. ]]
  5.  
  6. local component = require("component")
  7. local computer = require("computer")
  8. local term = require("term")
  9. local event = require("event")
  10. local fs = require("filesystem")
  11. local unicode = require("unicode")
  12.  
  13. -- Desktop Environment
  14. local Desktop = {
  15. windows = {},
  16. widgets = {},
  17. mouseX = 1,
  18. mouseY = 1,
  19. screenWidth = 0,
  20. screenHeight = 0,
  21. backgroundColor = 0x2D2D2D,
  22. foregroundColor = 0xFFFFFF,
  23. running = true
  24. }
  25.  
  26. -- Initialize screen dimensions
  27. function Desktop:init()
  28. self.screenWidth, self.screenHeight = term.getViewport()
  29. term.clear()
  30. end
  31.  
  32. -- Window class
  33. local Window = {}
  34. Window.__index = Window
  35.  
  36. function Window:new(x, y, width, height, title)
  37. local window = {
  38. x = x or 5,
  39. y = y or 3,
  40. width = width or 30,
  41. height = height or 15,
  42. title = title or "Window",
  43. content = {},
  44. visible = true,
  45. active = false,
  46. borderColor = 0x444444,
  47. titleColor = 0x1E90FF
  48. }
  49. setmetatable(window, Window)
  50. return window
  51. end
  52.  
  53. function Window:draw()
  54. if not self.visible then return end
  55.  
  56. -- Draw border
  57. term.setBackground(self.borderColor)
  58. for i = 0, self.width + 1 do
  59. term.setCursor(self.x + i, self.y)
  60. term.write(" ")
  61. term.setCursor(self.x + i, self.y + self.height + 1)
  62. term.write(" ")
  63. end
  64. for i = 0, self.height + 1 do
  65. term.setCursor(self.x, self.y + i)
  66. term.write(" ")
  67. term.setCursor(self.x + self.width + 1, self.y + i)
  68. term.write(" ")
  69. end
  70.  
  71. -- Draw title bar
  72. term.setBackground(self.titleColor)
  73. term.setForeground(0xFFFFFF)
  74. term.setCursor(self.x + 1, self.y)
  75. local titleText = string.sub(self.title, 1, self.width - 2)
  76. term.write(" " .. titleText .. string.rep(" ", self.width - #titleText - 1))
  77.  
  78. -- Draw content area
  79. term.setBackground(0x000000)
  80. for y = 1, self.height do
  81. term.setCursor(self.x + 1, self.y + y)
  82. term.write(string.rep(" ", self.width))
  83. end
  84.  
  85. -- Draw content
  86. term.setForeground(0xFFFFFF)
  87. for i, line in ipairs(self.content) do
  88. if i <= self.height then
  89. term.setCursor(self.x + 2, self.y + i)
  90. term.write(string.sub(line, 1, self.width - 2))
  91. end
  92. end
  93. end
  94.  
  95. function Window:setContent(content)
  96. if type(content) == "string" then
  97. self.content = {}
  98. for line in content:gmatch("[^\r\n]+") do
  99. table.insert(self.content, line)
  100. end
  101. elseif type(content) == "table" then
  102. self.content = content
  103. end
  104. end
  105.  
  106. -- Widget class
  107. local Widget = {}
  108. Widget.__index = Widget
  109.  
  110. function Widget:new(x, y, width, height)
  111. local widget = {
  112. x = x or 1,
  113. y = y or 1,
  114. width = width or 10,
  115. height = height or 1,
  116. visible = true,
  117. backgroundColor = 0x333333,
  118. foregroundColor = 0xFFFFFF
  119. }
  120. setmetatable(widget, Widget)
  121. return widget
  122. end
  123.  
  124. function Widget:draw()
  125. if not self.visible then return end
  126. term.setBackground(self.backgroundColor)
  127. term.setForeground(self.foregroundColor)
  128. end
  129.  
  130. -- Clock widget
  131. local ClockWidget = {}
  132. ClockWidget.__index = setmetatable(ClockWidget, {__index = Widget})
  133.  
  134. function ClockWidget:new(x, y)
  135. local widget = Widget:new(x, y, 8, 1)
  136. setmetatable(widget, ClockWidget)
  137. return widget
  138. end
  139.  
  140. function ClockWidget:draw()
  141. Widget.draw(self)
  142. local time = os.date("%H:%M:%S")
  143. term.setCursor(self.x, self.y)
  144. term.write(time)
  145. end
  146.  
  147. -- Taskbar widget
  148. local TaskbarWidget = {}
  149. TaskbarWidget.__index = setmetatable(TaskbarWidget, {__index = Widget})
  150.  
  151. function TaskbarWidget:new()
  152. local widget = Widget:new(1, Desktop.screenHeight, Desktop.screenWidth, 1)
  153. widget.backgroundColor = 0x1E1E1E
  154. setmetatable(widget, TaskbarWidget)
  155. return widget
  156. end
  157.  
  158. function TaskbarWidget:draw()
  159. Widget.draw(self)
  160. term.setCursor(1, self.y)
  161. term.write("_APPS_|_FILES_|_SETTINGS_|_EXIT_")
  162. end
  163.  
  164. -- Desktop methods
  165. function Desktop:addWindow(window)
  166. table.insert(self.windows, window)
  167. end
  168.  
  169. function Desktop:addWidget(widget)
  170. table.insert(self.widgets, widget)
  171. end
  172.  
  173. function Desktop:drawBackground()
  174. term.setBackground(self.backgroundColor)
  175. term.clear()
  176.  
  177. -- Draw wallpaper pattern
  178. term.setForeground(0x444444)
  179. for y = 1, self.screenHeight - 1 do
  180. for x = 1, self.screenWidth, 2 do
  181. term.setCursor(x, y)
  182. term.write("·")
  183. end
  184. end
  185.  
  186. -- Draw title
  187. term.setForeground(0x1E90FF)
  188. term.setCursor(5, 2)
  189. term.write("PLAN9K DESKTOP")
  190. term.setForeground(0xAAAAAA)
  191. term.setCursor(5, 3)
  192. term.write("Click and drag windows, press 'q' to quit")
  193. end
  194.  
  195. function Desktop:draw()
  196. self:drawBackground()
  197.  
  198. -- Draw widgets
  199. for _, widget in ipairs(self.widgets) do
  200. widget:draw()
  201. end
  202.  
  203. -- Draw windows (in reverse order for proper layering)
  204. for i = #self.windows, 1, -1 do
  205. self.windows[i]:draw()
  206. end
  207. end
  208.  
  209. function Desktop:handleClick(x, y)
  210. -- Check if clicked on taskbar
  211. if y == self.screenHeight then
  212. if x >= 1 and x <= 6 then
  213. -- Apps button
  214. local appWindow = Window:new(10, 5, 25, 10, "Applications")
  215. appWindow:setContent({"File Manager", "Text Editor", "Terminal", "Calculator", "", "Click to launch..."})
  216. self:addWindow(appWindow)
  217. elseif x >= 8 and x <= 14 then
  218. -- Files button
  219. local fileWindow = Window:new(15, 8, 30, 12, "File Browser")
  220. appWindow:setContent({"/", "├── bin/", "├── etc/", "├── home/", "├── tmp/", "└── usr/"})
  221. self:addWindow(fileWindow)
  222. elseif x >= 16 and x <= 25 then
  223. -- Settings button
  224. local settingsWindow = Window:new(20, 6, 20, 8, "Settings")
  225. settingsWindow:setContent({"Display", "Network", "Sound", "Users"})
  226. self:addWindow(settingsWindow)
  227. elseif x >= 27 and x <= 32 then
  228. -- Exit button
  229. self.running = false
  230. end
  231. return
  232. end
  233.  
  234. -- Check if clicked on window title bars
  235. for i, window in ipairs(self.windows) do
  236. if x >= window.x and x <= window.x + window.width + 2 and
  237. y >= window.y and y <= window.y + 1 then
  238. -- Move window to front
  239. table.remove(self.windows, i)
  240. table.insert(self.windows, 1, window)
  241. break
  242. end
  243. end
  244. end
  245.  
  246. function Desktop:update()
  247. -- Update widgets
  248. for _, widget in ipairs(self.widgets) do
  249. if widget.update then
  250. widget:update()
  251. end
  252. end
  253. end
  254.  
  255. function Desktop:run()
  256. self:init()
  257.  
  258. -- Add default widgets
  259. self:addWidget(ClockWidget:new(self.screenWidth - 8, 1))
  260. self:addWidget(TaskbarWidget:new())
  261.  
  262. -- Add sample windows
  263. local welcomeWindow = Window:new(5, 5, 35, 8, "Welcome")
  264. welcomeWindow:setContent({
  265. "Welcome to Plan9k Desktop!",
  266. "",
  267. "Features:",
  268. "• Window management",
  269. "• Clickable taskbar",
  270. "• Real-time clock",
  271. "• Interactive interface",
  272. "",
  273. "Press 'q' to quit"
  274. })
  275. self:addWindow(welcomeWindow)
  276.  
  277. -- Main event loop
  278. while self.running do
  279. self:draw()
  280. self:update()
  281.  
  282. local _, eventType, _, eventData, _, button = event.pull(0.1)
  283.  
  284. if eventType == "touch" or eventType == "click" then
  285. local x, y = eventData, button
  286. self:handleClick(x, y)
  287. elseif eventType == "key_down" then
  288. if eventData == 16 then -- 'q' key
  289. self.running = false
  290. end
  291. elseif eventType == "interrupted" then
  292. self.running = false
  293. end
  294. end
  295.  
  296. term.clear()
  297. term.setCursor(1, 1)
  298. print("Desktop exited.")
  299. end
  300.  
  301. -- Run the desktop
  302. if ... == nil then
  303. Desktop:run()
  304. end
  305.  
  306. return Desktop
  307.  
Advertisement
Add Comment
Please, Sign In to add comment