ComputerCraft Archive

miniOS (well more of a window manager)

computer operating-system unknown forum

Description

Well I made a window manager in a day, because I was sooo bored :P/>/>It literally is only one file with about 360 (heh) lines :)/>/>Screenshots:Spoiler[attachment=2681:screenshot.PNG]Features:Press F...

Installation

Copy one of these commands into your ComputerCraft terminal:

Pastebin:pastebin get qXqg8Weg minios_(well_more_of_a_window_manager)
wget:wget https://pastebin.com/raw/qXqg8Weg minios_(well_more_of_a_window_manager)
Archive:wget https://cc.shobie.xyz/cc/get/pb-qXqg8Weg minios_(well_more_of_a_window_manager)
Quick Install: wget https://cc.shobie.xyz/cc/get/pb-qXqg8Weg miniOS (well more of a window manager)

Usage

Run the program after downloading

Tags

forumoperating-systems

Source

View Original Source

Code Preview

--[[

				miniOS

	As the name already says, this OS is not
	a real "OS", like you'd expect it to be.

	I think you can call it a window manager

	~Piorjade
]]--

--[[
			Variables
		(and minimal thread API)			
]]
tasks = {}
windows = {}
selected = ""

--define the thread api
local thread = {}

function thread.new(path)
	if not fs.exists(path) or fs.isDir(path) then
		return nil
	end
	local self = {}
	--load the file as function
	self.func, err = loadfile(path)
	if not self.func then
		return false, err
	end
	--create a new enviroment for the file and put it in there
	self.env = {}
	setmetatable(self.env, {})
	local function _copy(a, b)
		for k, v in pairs(a) do
			b[k] = v
		end
	end
	_copy(_G, self.env)
	setfenv(self.func, self.env)
	--defines variables
	if not tasks[path] then
		self.path = path
	else
		local kek = path
		local nkek = kek
		local counter = 1
		repeat
			nkek = kek..tostring(counter)
			counter = counter+1
		until not tasks[nkek]
		self.path = nkek
	end
	self.task = coroutine.create(self.func)
	self.dead = false
	self.paused = false
	self.filter = nil
	self.invisible = false
	--define resume function (--> runs the file)
	function self.resume(...)
		local fst = {...}
		if self.filter == nil and not self.paused or fst[1] == self.filter and not self.paused then
			local ok, err = coroutine.resume(self.task, unpack(fst))
			if ok then
				local stat = coroutine.status(self.task)
				if stat == "dead" then
					self.dead = true
				else
					self.filter = err
				end
			else
				self.dead = true
				printError(err)
			end
		end
	end
	tasks[self.path] = self
	--create a new window for the file
	--xA/yA = top left corner, xO/yO = bottom right corner
	local maxX, maxY = term.getSize()
	windows[self.path] = {}
	windows[self.path]['xA'] = 1
	windows[self.path]['yA'] = 1
	windows[self.path]['xO'] = maxX
	windows[self.path]['yO'] = maxY
	windows[self.path]['w'] = window.create(oldTerm, 1, 1, maxX, maxY)
	windows[self.path]['w'].setBackgroundColor(colors.gray)
	windows[self.path]['w'].setTextColor(colors.black)
	windows[self.path]['w'].clear()
	windows[self.path]['w'].setTextColor(colors.red)
	windows[self.path]['w'].setCursorPos(maxX, 1)
	windows[self.path]['w'].write("O")
	windows[self.path]['w'].setTextColor(colors.yellow)
	windows[self.path]['w'].setCursorPos(maxX-1, 1)
	windows[self.path]['w'].write("O")
	windows[self.path]['w'].setTextColor(colors.green)
	windows[self.path]['w'].setCursorPos(maxX-2, 1)
	windows[self.path]['w'].write("O")
	windows[self.path]['uw'] = window.create(windows[self.path]['w'], 2, 2, maxX-2, maxY-2)
	if #selected > 0 then
		--windows[selected]['w'].setVisible(false)
	end
	selected = self.path
	return true
end

--[[
		functions
]]
local function clear(bg, fg)
	term.setCursorPos(1,1)
	term.setBackgroundColor(bg)
	term.setTextColor(fg)
	term.clear()
end

local function redrawWindows()
	
	for each, task in pairs(tasks) do
		if not task.dead and not task.invisible then
			windows[task.path]['w'].redraw()
			windows[task.path]['uw'].redraw()
		end
	end
	if #selected > 0 and not tasks[selected].invisible then
		windows[selected]['w'].redraw()
		windows[selected]['uw'].redraw()
	end
end

local function drawSys()
	clear(colors.lightBlue, colors.black)
	local textBox = window.create(oldTerm, 1, 1, 20, 1, false)
	textBox.setBackgroundColor(colors.gray)
	textBox.setTextColor(colors.lime)
	textBox.clear()
	local evt = {}
	
	--start loop
	while true do
		
		evt = {os.pullEventRaw()}
		local event, button, x, y = unpack(evt)

		if event == "key" and button == keys.f1 then
			textBox.setVisible(true)
			term.redirect(textBox)
			clear(colors.gray, colors.lime)
			term.write("Path: ")
			local oprint = _G.print
			_G.print = function(t)
				return term.write(t)
			end
			local e = read()
			_G.print = oprint
			term.redirect(oldTerm)
			textBox.setVisible(false)
			clear(colors.lightBlue, colors.black)
			thread.new(e)
		elseif event == "mouse_click" then
			if button == 1 then
				if #selected > 0 and x == windows[selected]['xO'] and y == windows[selected]['yA'] then
					--close a window
					tasks[selected].dead = true
					--table.insert(queueRemove, selected)
					tasks[selected] = nil
					windows[selected] = nil
					selected = ""
					clear(colors.lightBlue, colors.black)
					redrawWindows()
				elseif #selected > 0 and x == windows[selected]['xO']-1 and y == windows[selected]['yA'] then
					--maximize a window
					local maxX, maxY = term.getSize()
					windows[selected]['w'].reposition(1, 1, maxX, maxY)
					windows[selected]['uw'].reposition(2, 2, maxX-2, maxY-2)
					windows[selected]['xA'] = 1
					windows[selected]['yA'] = 1
					windows[selected]['xO'] = maxX
					windows[selected]['yO'] = maxY
					windows[selected]['w'].setBackgroundColor(colors.gray)
					windows[selected]['w'].setTextColor(colors.black)
					windows[selected]['w'].clear()
					windows[selected]['w'].setTextColor(colors.red)
					windows[selected]['w'].setCursorPos(maxX, 1)
					windows[selected]['w'].write("O")
					windows[selected]['w'].setTextColor(colors.yellow)
					windows[selected]['w'].setCursorPos(maxX-1, 1)
					windows[selected]['w'].write("O")
					windows[selected]['w'].setTextColor(colors.green)
					windows[selected]['w'].setCursorPos(maxX-2, 1)
					windows[selected]['w'].write("O")
					clear(colors.lightBlue, colors.black)
					redrawWindows()
				elseif #selected > 0 and x == windows[selected]['xO']-2 and y == windows[selected]['yA'] then
					--minimize a window
					tasks[selected].invisible = true
					windows[selected]['w'].setVisible(false)
					selected = ""
					clear(colors.lightBlue, colors.black)
					redrawWindows()
				elseif #selected > 0 and x == windows[selected]['xO'] and y == windows[selected]['yO'] then
					--resize the window
					local nevt = {}
					local cx = x
					local cy = y
					local width, height = 1,1
					repeat
						nevt = {os.pullEvent()}
						if nevt[1] == "mouse_drag" and nevt[3] >= windows[selected]['xA']+2 and nevt[4] >= windows[selected]['yA']+2 then
							width = windows[selected]['xO']-windows[selected]['xA']+1
							height = windows[selected]['yO']-windows[selected]['yA']+1

							if width >= 3 and height >= 3 then
								windows[selected]['xO'] = nevt[3]
								windows[selected]['yO'] = nevt[4]
								local maxX = windows[selected]['xO']
								local maxY = windows[selected]['yO']
								width = windows[selected]['xO']-windows[selected]['xA']+1
								height = windows[selected]['yO']-windows[selected]['yA']+1
								windows[selected]['w'].reposition(windows[selected]['xA'], windows[selected]['yA'], width, height)
								windows[selected]['uw'].reposition(2, 2, width-2, height-2)
								windows[selected]['w'].setBackgroundColor(colors.gray)
								windows[selected]['w'].setTextColor(colors.black)
								windows[selected]['w'].clear()
								windows[selected]['w'].setTextColor(colors.red)
								windows[selected]['w'].setCursorPos(width, 1)
								windows[selected]['w'].write("O")
								windows[selected]['w'].setTextColor(colors.yellow)
								windows[selected]['w'].setCursorPos(width-1, 1)
								windows[selected]['w'].write("O")
								windows[selected]['w'].setTextColor(colors.green)
								windows[selected]['w'].setCursorPos(width-2, 1)
								windows[selected]['w'].write("O")
								clear(colors.lightBlue, colors.black)
								redrawWindows()
							end
						end
					until nevt[1] == "mouse_up"
					clear(colors.lightBlue, colors.black)
					redrawWindows()
				elseif #selected > 0 and x >= windows[selected]['xA'] and x <= windows[selected]['xO']-2 and y == windows[selected]['yA'] then
					--move the window
					local nevt = {}
					local abstand = x-windows[selected]['xA']
					local width, height = windows[selected]['w'].getSize()
					local cx = x
					local cy = y
					repeat
						nevt = {os.pullEvent()}
						
						if nevt[1] == "mouse_drag" then
							windows[selected]['xA'] = nevt[3]-abstand
							windows[selected]['yA'] = nevt[4]
							windows[selected]['xO'] = windows[selected]['xA']+width-1
							windows[selected]['yO'] = windows[selected]['yA']+height-1
							windows[selected]['w'].reposition(windows[selected]['xA'], windows[selected]['yA'], width, height)
							clear(colors.lightBlue, colors.black)
							redrawWindows()
						end
					until nevt[1] == "mouse_up"
					clear(colors.lightBlue, colors.black)
					redrawWindows()
				else
					if #selected > 0 then
						for each, window in pairs(windows) do
							if x < windows[selected]['xA'] or y > windows[selected]['yO'] or x > windows[selected]['xO'] or y < windows[selected]['yA'] then 
								if x >= window.xA and x <= window.xO and y >= window.yA and y <= window.yO then
									--windows[selected]['w'].setVisible(false)
									selected = each
									--windows[selected]['w'].setVisible(true)
									break
								end
							end
						end
					else
						for each, window in pairs(windows) do
							if x >= window.xA and x <= window.xO and y >= window.yA and y <= window.yO then
								selected = each
								--windows[selected]['w'].setVisible(true)
								break
							end
						end
					end
					clear(colors.lightBlue, colors.black)
					redrawWindows()
				end
			end
		end
	end
end
--[[
		code
]]
--catch the original terminal (for orientation)
oldTerm = term.current()
queueRemove = {}
--list every event that should only be passed to the selected window
ll = {
	"key",
	"char",
	"mouse_click",
	"mouse_down",
	"mouse_drag"
}
parallel.waitForAll(
	function()
		drawSys()
	end,
	function()
		local evt = {}
		while true do
			for task, a in pairs(tasks) do
				--resume all non-selected windows
				if not a.dead and not a.path == selected then
					local found = false
					--check if the current event is one of the listed. if yes, don't resume
					for _, a in ipairs(ll) do
						if evt[1] == a then
							found = true
							break
						else
							found = false
						end
					end
					if not found then
						term.redirect(windows[a.path]['uw'])
						a.resume(unpack(evt))
						term.redirect(oldTerm)
					end
				end
			end
			if tasks[selected] then
				if not tasks[selected].dead then
					if evt[1] == "mouse_click" or evt[1] == "mouse_up" or evt[1] == "mouse_down" or evt[1] == "mouse_drag" then
						if evt[3] > windows[selected]['xA'] and evt[3] < windows[selected]['xO'] and evt[4] > windows[selected]['yA'] and evt[4] < windows[selected]['yO'] then
							evt[3] = evt[3]-windows[selected]['xA']
							evt[4] = evt[4]-windows[selected]['yA']
							term.redirect(windows[selected]['uw'])
							tasks[selected].resume(unpack(evt))
							term.redirect(oldTerm)
						else
							term.redirect(windows[selected]['uw'])
							tasks[selected].resume({})
							term.redirect(oldTerm)
						end
					else
						term.redirect(windows[selected]['uw'])
						tasks[selected].resume(unpack(evt))
						term.redirect(oldTerm)
					end
				end
			end
			for each, entry in ipairs(queueRemove) do
				tasks[entry] = nil
				windows[entry] = nil
				table.remove(queueRemove, each)

			end
			evt = {os.pullEventRaw()}
		end
	end)