View difference between Paste ID: 4eCwR0Dk and 8UJiuVsw
SHOW: | | - or go back to the newest paste.
1
--[[
2
The MIT License (MIT)
3
 
4
Copyright (c) 2013 Lyqyd
5
 
6
Permission is hereby granted, free of charge, to any person obtaining a copy
7
of this software and associated documentation files (the "Software"), to deal
8
in the Software without restriction, including without limitation the rights
9
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
copies of the Software, and to permit persons to whom the Software is
11
furnished to do so, subject to the following conditions:
12
 
13
The above copyright notice and this permission notice shall be included in
14
all copies or substantial portions of the Software.
15
 
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
THE SOFTWARE.
23
--]]
24
25
local function setupLabel(buttonLen, minY, maxY, name)
26
	local labelTable = {}
27
	if type(name) == "table" then
28
		for i = 1, #name do
29
			labelTable[i] = name[i]
30
		end
31
		name = name.label
32
	elseif type(name) == "string" then
33
		local buttonText = string.sub(name, 1, buttonLen - 2)
34
		if #buttonText < #name then
35
			buttonText = " "..buttonText.." "
36
		else
37
			local labelLine = string.rep(" ", math.floor((buttonLen - #buttonText) / 2))..buttonText
38
			buttonText = labelLine..string.rep(" ", buttonLen - #labelLine)
39
		end
40
		for i = 1, maxY - minY + 1 do
41
			if maxY == minY or i == math.floor((maxY - minY) / 2) + 1 then
42
				labelTable[i] = buttonText
43
			else
44
				labelTable[i] = string.rep(" ", buttonLen)
45
			end
46
		end
47
	end
48
	return labelTable, name
49
end
50
51
local Button = {
52
	draw = function(self)
53
		local old = term.redirect(self.mon)
54
		term.setTextColor(colors.white)
55
		term.setBackgroundColor(colors.black)
56
		term.clear()
57
		for name, buttonData in pairs(self.buttonList) do
58
			if buttonData.active then
59
				term.setBackgroundColor(buttonData.activeColor)
60
				term.setTextColor(buttonData.activeText)
61
			else
62
				term.setBackgroundColor(buttonData.inactiveColor)
63
				term.setTextColor(buttonData.inactiveText)
64
			end
65
			for i = buttonData.yMin, buttonData.yMax do
66
				term.setCursorPos(buttonData.xMin, i)
67
				term.write(buttonData.label[i - buttonData.yMin + 1])
68
			end
69
		end
70
		if old then
71
			term.redirect(old)
72
		else
73
			term.restore()
74
		end
75
	end,
76
	add = function(self, name, func, xMin, yMin, xMax, yMax, inactiveColor, activeColor, inactiveText, activeText)
77
		local label, name = setupLabel(xMax - xMin + 1, yMin, yMax, name)
78
		if self.buttonList[name] then error("button already exists", 2) end
79
		local x, y = self.mon.getSize()
80
		if xMin < 1 or yMin < 1 or xMax > x or yMax > y then error("button out of bounds", 2) end
81
		self.buttonList[name] = {
82
			func = func,
83
			xMin = xMin,
84
			yMin = yMin,
85
			xMax = xMax,
86
			yMax = yMax,
87
			active = false,
88
			inactiveColor = inactiveColor or colors.red,
89
			activeColor = activeColor or colors.lime,
90
			inactiveText = inactiveText or colors.white,
91
			activeText = activeText or colors.white,
92
			label = label,
93
		}
94
		for i = xMin, xMax do
95
			for j = yMin, yMax do
96
				if self.clickMap[i][j] ~= nil then
97
					--undo changes
98
					for k = xMin, xMax do
99
						for l = yMin, yMax do
100
							if self.clickMap[k][l] == name then
101
								self.clickMap[k][l] = nil
102
							end
103
						end
104
					end
105
					self.buttonList[name] = nil
106
					error("overlapping button", 2)
107
				end
108
				self.clickMap[i][j] = name
109
			end
110
		end
111
	end,
112
	remove = function(self, name)
113
		if self.buttonList[name] then
114
			local button = self.buttonList[name]
115
			for i = button.xMin, button.xMax do
116
				for j = button.yMin, button.yMax do
117
					self.clickMap[i][j] = nil
118
				end
119
			end
120
			self.buttonList[name] = nil
121
		end
122
	end,
123
	run = function(self)
124
		while true do
125
			self:draw()
126
			local event = {self:handleEvents(os.pullEvent(self.side == "term" and "mouse_click" or "monitor_touch"))}
127
			if event[1] == "button_click" then
128
				self.buttonList[event[2]].func()
129
			end
130
		end
131
	end,
132
	handleEvents = function(self, ...)
133
		local event = {...}
134
		if #event == 0 then event = {os.pullEvent()} end
135
		if (self.side == "term" and event[1] == "mouse_click") or (self.side ~= "term" and event[1] == "monitor_touch" and event[2] == self.side) then
136
			local clicked = self.clickMap[event[3]][event[4]]
137
			if clicked and self.buttonList[clicked] then
138
				return "button_click", clicked
139
			end
140
		end
141
		return unpack(event)
142
	end,
143
	toggleButton = function(self, name, noDraw)
144
		self.buttonList[name].active = not self.buttonList[name].active
145
		if not noDraw then self:draw() end
146
	end,
147
	setActive = function(self, name, noDraw)
148
		self.buttonList[name].active = true
149
		if not noDraw then self:draw() end
150
	end,
151
	setInactive = function(self, name, noDraw)
152
		self.buttonList[name].active = false
153
		if not noDraw then self:draw() end
154
	end,
155
	flash = function(self, name, duration)
156
		self:toggleButton(name)
157
		sleep(tonumber(duration) or 0.15)
158
		self:toggleButton(name)
159
	end,
160
	rename = function(self, name, newName)
161
		self.buttonList[name].label, newName = setupLabel(self.buttonList[name].xMax - self.buttonList[name].xMin + 1, self.buttonList[name].yMin, self.buttonList[name].yMax, newName)
162
		if not self.buttonList[name] then error("no such button", 2) end
163
		if name ~= newName then
164
			self.buttonList[newName] = self.buttonList[name]
165
			self.buttonList[name] = nil
166
			for i = self.buttonList[newName].xMin, self.buttonList[newName].xMax do
167
				for j = self.buttonList[newName].yMin, self.buttonList[newName].yMax do
168
					self.clickMap[i][j] = newName
169
				end
170
			end
171
		end
172
		self:draw()
173
	end,
174
 getState = function(self, name)
175-
function new(monSide)
175+
176
 end,
177
 clear = function(self)
178
  self.mon.setBackgroundColor(colors.black)
179
  self.mon.clear()
180
 end,
181
}
182
183
function new(monSide, textScale)
184
	local buttonInstance = {
185
		side = monSide or "term",
186
		mon = monSide and peripheral.wrap(monSide) or term.current(),
187
		buttonList = {},
188
		clickMap = {},
189
	}
190
	if monSide ~= nil and textScale ~= nil then
191
		buttonInstance.mon.setTextScale(textScale)
192
	end
193
	local x, y = buttonInstance.mon.getSize()
194
	for i = 1, x do
195
		buttonInstance.clickMap[i] = {}
196
	end
197
	setmetatable(buttonInstance, {__index = Button})
198
	return buttonInstance
199
end