View difference between Paste ID: PUp9qZnE and dL3Nkv1i
SHOW: | | - or go back to the newest paste.
1-
--[[

1+
--[[
2-
The MIT License (MIT)

2+
3-
 

3+
The MIT License (MIT)
4-
Copyright (c) 2013 Lyqyd

4+
5-
 

5+
 
6-
Permission is hereby granted, free of charge, to any person obtaining a copy

6+
7-
of this software and associated documentation files (the "Software"), to deal

7+
Copyright (c) 2013 Lyqyd
8-
in the Software without restriction, including without limitation the rights

8+
9-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

9+
 
10-
copies of the Software, and to permit persons to whom the Software is

10+
11-
furnished to do so, subject to the following conditions:

11+
Permission is hereby granted, free of charge, to any person obtaining a copy
12-
 

12+
13-
The above copyright notice and this permission notice shall be included in

13+
of this software and associated documentation files (the "Software"), to deal
14-
all copies or substantial portions of the Software.

14+
15-
 

15+
in the Software without restriction, including without limitation the rights
16-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

16+
17-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

17+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

18+
19-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

19+
copies of the Software, and to permit persons to whom the Software is
20-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

20+
21-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

21+
furnished to do so, subject to the following conditions:
22-
THE SOFTWARE.

22+
23-
--]]

23+
 
24-
24+
25-
local function setupLabel(buttonLen, minY, maxY, name)

25+
The above copyright notice and this permission notice shall be included in
26-
	local labelTable = {}

26+
27-
	if type(name) == "table" then

27+
all copies or substantial portions of the Software.
28-
		for i = 1, #name do

28+
29-
			labelTable[i] = name[i]

29+
 
30-
		end

30+
31-
		name = name.label

31+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32-
	elseif type(name) == "string" then

32+
33-
		local buttonText = string.sub(name, 1, buttonLen - 2)

33+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34-
		if #buttonText < #name then

34+
35-
			buttonText = " "..buttonText.." "

35+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36-
		else

36+
37-
			local labelLine = string.rep(" ", math.floor((buttonLen - #buttonText) / 2))..buttonText

37+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38-
			buttonText = labelLine..string.rep(" ", buttonLen - #labelLine)

38+
39-
		end

39+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
40-
		for i = 1, maxY - minY + 1 do

40+
41-
			if maxY == minY or i == math.floor((maxY - minY) / 2) + 1 then

41+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
42-
				labelTable[i] = buttonText

42+
43-
			else

43+
THE SOFTWARE.
44-
				labelTable[i] = string.rep(" ", buttonLen)

44+
45-
			end

45+
--]]
46-
		end

46+
47-
	end

47+
48-
	return labelTable, name

48+
49-
end

49+
local function setupLabel(buttonLen, minY, maxY, name)
50-
50+
51-
local Button = {

51+
	local labelTable = {}
52-
	draw = function(self)

52+
53-
		local old = term.redirect(self.mon)

53+
	if type(name) == "table" then
54-
		term.setTextColor(colors.white)

54+
55-
		term.setBackgroundColor(colors.black)

55+
		for i = 1, #name do
56-
		term.clear()

56+
57-
		for name, buttonData in pairs(self.buttonList) do

57+
			labelTable[i] = name[i]
58-
			if buttonData.active then

58+
59-
				term.setBackgroundColor(buttonData.activeColor)

59+
		end
60-
				term.setTextColor(buttonData.activeText)

60+
61-
			else

61+
		name = name.label
62-
				term.setBackgroundColor(buttonData.inactiveColor)

62+
63-
				term.setTextColor(buttonData.inactiveText)

63+
	elseif type(name) == "string" then
64-
			end

64+
65-
			for i = buttonData.yMin, buttonData.yMax do

65+
		local buttonText = string.sub(name, 1, buttonLen - 2)
66-
				term.setCursorPos(buttonData.xMin, i)

66+
67-
				term.write(buttonData.label[i - buttonData.yMin + 1])

67+
		if #buttonText < #name then
68-
			end

68+
69-
		end

69+
			buttonText = " "..buttonText.." "
70-
		if old then

70+
71-
			term.redirect(old)

71+
		else
72-
		else

72+
73-
			term.restore()

73+
			local labelLine = string.rep(" ", math.floor((buttonLen - #buttonText) / 2))..buttonText
74-
		end

74+
75-
	end,

75+
			buttonText = labelLine..string.rep(" ", buttonLen - #labelLine)
76-
	add = function(self, name, func, xMin, yMin, xMax, yMax, inactiveColor, activeColor, inactiveText, activeText)

76+
77-
		local label, name = setupLabel(xMax - xMin + 1, yMin, yMax, name)

77+
		end
78-
		if self.buttonList[name] then error("button already exists", 2) end

78+
79-
		local x, y = self.mon.getSize()

79+
		for i = 1, maxY - minY + 1 do
80-
		if xMin < 1 or yMin < 1 or xMax > x or yMax > y then error("button out of bounds", 2) end

80+
81-
		self.buttonList[name] = {

81+
			if maxY == minY or i == math.floor((maxY - minY) / 2) + 1 then
82-
			func = func,

82+
83-
			xMin = xMin,

83+
				labelTable[i] = buttonText
84-
			yMin = yMin,

84+
85-
			xMax = xMax,

85+
			else
86-
			yMax = yMax,

86+
87-
			active = false,

87+
				labelTable[i] = string.rep(" ", buttonLen)
88-
			inactiveColor = inactiveColor or colors.red,

88+
89-
			activeColor = activeColor or colors.lime,

89+
			end
90-
			inactiveText = inactiveText or colors.white,

90+
91-
			activeText = activeText or colors.white,

91+
		end
92-
			label = label,

92+
93-
		}

93+
	end
94-
		for i = xMin, xMax do

94+
95-
			for j = yMin, yMax do

95+
	return labelTable, name
96-
				if self.clickMap[i][j] ~= nil then

96+
97-
					--undo changes

97+
end
98-
					for k = xMin, xMax do

98+
99-
						for l = yMin, yMax do

99+
100-
							if self.clickMap[k][l] == name then

100+
101-
								self.clickMap[k][l] = nil

101+
local Button = {
102-
							end

102+
103-
						end

103+
	draw = function(self)
104-
					end

104+
105-
					self.buttonList[name] = nil

105+
		local old = term.redirect(self.mon)
106-
					error("overlapping button", 2)

106+
107-
				end

107+
		term.setTextColor(colors.white)
108-
				self.clickMap[i][j] = name

108+
109-
			end

109+
		term.setBackgroundColor(colors.black)
110-
		end

110+
111-
	end,

111+
		term.clear()
112-
	remove = function(self, name)

112+
113-
		if self.buttonList[name] then

113+
		for name, buttonData in pairs(self.buttonList) do
114-
			local button = self.buttonList[name]

114+
115-
			for i = button.xMin, button.xMax do

115+
			if buttonData.active then
116-
				for j = button.yMin, button.yMax do

116+
117-
					self.clickMap[i][j] = nil

117+
				term.setBackgroundColor(buttonData.activeColor)
118-
				end

118+
119-
			end

119+
				term.setTextColor(buttonData.activeText)
120-
			self.buttonList[name] = nil

120+
121-
		end

121+
			else
122-
	end,

122+
123-
	run = function(self)

123+
				term.setBackgroundColor(buttonData.inactiveColor)
124-
		while true do

124+
125-
			self:draw()

125+
				term.setTextColor(buttonData.inactiveText)
126-
			local event = {self:handleEvents(os.pullEvent(self.side == "term" and "mouse_click" or "monitor_touch"))}

126+
127-
			if event[1] == "button_click" then

127+
			end
128-
				self.buttonList[event[2]].func()

128+
129-
			end

129+
			for i = buttonData.yMin, buttonData.yMax do
130-
		end

130+
131-
	end,

131+
				term.setCursorPos(buttonData.xMin, i)
132-
	handleEvents = function(self, ...)

132+
133-
		local event = {...}

133+
				term.write(buttonData.label[i - buttonData.yMin + 1])
134-
		if #event == 0 then event = {os.pullEvent()} end

134+
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

135+
			end
136-
			local clicked = self.clickMap[event[3]][event[4]]

136+
137-
			if clicked and self.buttonList[clicked] then

137+
		end
138-
				return "button_click", clicked

138+
139-
			end

139+
		if old then
140-
		end

140+
141-
		return unpack(event)

141+
			term.redirect(old)
142-
	end,

142+
143-
	toggleButton = function(self, name, noDraw)

143+
		else
144-
		self.buttonList[name].active = not self.buttonList[name].active

144+
145-
		if not noDraw then self:draw() end

145+
			term.restore()
146-
	end,

146+
147-
	flash = function(self, name, duration)

147+
		end
148-
		self:toggleButton(name)

148+
149-
		sleep(tonumber(duration) or 0.15)

149+
	end,
150-
		self:toggleButton(name)

150+
151-
	end,

151+
	add = function(self, name, func, xMin, yMin, xMax, yMax, inactiveColor, activeColor, inactiveText, activeText)
152-
	rename = function(self, name, newName)

152+
153-
		self.buttonList[name].label, newName = setupLabel(self.buttonList[name].xMax - self.buttonList[name].xMin + 1, self.buttonList[name].yMin, self.buttonList[name].yMax, newName)

153+
		local label, name = setupLabel(xMax - xMin + 1, yMin, yMax, name)
154-
		if not self.buttonList[name] then error("no such button", 2) end

154+
155-
		if name ~= newName then

155+
		if self.buttonList[name] then error("button already exists", 2) end
156-
			self.buttonList[newName] = self.buttonList[name]

156+
157-
			self.buttonList[name] = nil

157+
		local x, y = self.mon.getSize()
158-
			for i = self.buttonList[newName].xMin, self.buttonList[newName].xMax do

158+
159-
				for j = self.buttonList[newName].yMin, self.buttonList[newName].yMax do

159+
		if xMin < 1 or yMin < 1 or xMax > x or yMax > y then error("button out of bounds", 2) end
160-
					self.clickMap[i][j] = newName

160+
161-
				end

161+
		self.buttonList[name] = {
162-
			end

162+
163-
		end

163+
			func = func,
164-
		self:draw()

164+
165-
	end,

165+
			xMin = xMin,
166-
}

166+
167-
167+
			yMin = yMin,
168-
function new(monSide)

168+
169-
	local buttonInstance = {

169+
			xMax = xMax,
170-
		side = monSide or "term",

170+
171-
		mon = monSide and peripheral.wrap(monSide) or term.current(),

171+
			yMax = yMax,
172-
		buttonList = {},

172+
173-
		clickMap = {},

173+
			active = false,
174-
	}

174+
175-
	local x, y = buttonInstance.mon.getSize()

175+
			inactiveColor = inactiveColor or colors.red,
176-
	for i = 1, x do

176+
177-
		buttonInstance.clickMap[i] = {}

177+
			activeColor = activeColor or colors.lime,
178-
	end

178+
179-
	setmetatable(buttonInstance, {__index = Button})

179+
			inactiveText = inactiveText or colors.white,
180-
	return buttonInstance

180+
181
			activeText = activeText or colors.white,
182
183
			label = label,
184
185
		}
186
187
		for i = xMin, xMax do
188
189
			for j = yMin, yMax do
190
191
				if self.clickMap[i][j] ~= nil then
192
193
					--undo changes
194
195
					for k = xMin, xMax do
196
197
						for l = yMin, yMax do
198
199
							if self.clickMap[k][l] == name then
200
201
								self.clickMap[k][l] = nil
202
203
							end
204
205
						end
206
207
					end
208
209
					self.buttonList[name] = nil
210
211
					error("overlapping button", 2)
212
213
				end
214
215
				self.clickMap[i][j] = name
216
217
			end
218
219
		end
220
221
	end,
222
223
	remove = function(self, name)
224
225
		if self.buttonList[name] then
226
227
			local button = self.buttonList[name]
228
229
			for i = button.xMin, button.xMax do
230
231
				for j = button.yMin, button.yMax do
232
233
					self.clickMap[i][j] = nil
234
235
				end
236
237
			end
238
239
			self.buttonList[name] = nil
240
241
		end
242
243
	end,
244
245
	run = function(self)
246
247
		while true do
248
249
			self:draw()
250
251
			local event = {self:handleEvents(os.pullEvent(self.side == "term" and "mouse_click" or "monitor_touch"))}
252
253
			if event[1] == "button_click" then
254
255
				self.buttonList[event[2]].func()
256
257
			end
258
259
		end
260
261
	end,
262
263
	handleEvents = function(self, ...)
264
265
		local event = {...}
266
267
		if #event == 0 then event = {os.pullEvent()} end
268
269
		if (self.side == "term" and event[1] == "mouse_click") or (self.side ~= "term" and event[1] == "monitor_touch" and event[2] == self.side) then
270
271
			local clicked = self.clickMap[event[3]][event[4]]
272
273
			if clicked and self.buttonList[clicked] then
274
275
				return "button_click", clicked
276
277
			end
278
279
		end
280
281
		return unpack(event)
282
283
	end,
284
285
	toggleButton = function(self, name, noDraw)
286
287
		self.buttonList[name].active = not self.buttonList[name].active
288
289
		if not noDraw then self:draw() end
290
291
	end,
292
293
	flash = function(self, name, duration)
294
295
		self:toggleButton(name)
296
297
		sleep(tonumber(duration) or 0.15)
298
299
		self:toggleButton(name)
300
301
	end,
302
303
	rename = function(self, name, newName)
304
305
		self.buttonList[name].label, newName = setupLabel(self.buttonList[name].xMax - self.buttonList[name].xMin + 1, self.buttonList[name].yMin, self.buttonList[name].yMax, newName)
306
307
		if not self.buttonList[name] then error("no such button", 2) end
308
309
		if name ~= newName then
310
311
			self.buttonList[newName] = self.buttonList[name]
312
313
			self.buttonList[name] = nil
314
315
			for i = self.buttonList[newName].xMin, self.buttonList[newName].xMax do
316
317
				for j = self.buttonList[newName].yMin, self.buttonList[newName].yMax do
318
319
					self.clickMap[i][j] = newName
320
321
				end
322
323
			end
324
325
		end
326
327
		self:draw()
328
329
	end,
330
331
}
332
333
334
335
function new(monSide)
336
337
	local buttonInstance = {
338
339
		side = monSide or "term",
340
341
		mon = monSide and peripheral.wrap(monSide) or term.current(),
342
343
		buttonList = {},
344
345
		clickMap = {},
346
347
	}
348
349
	local x, y = buttonInstance.mon.getSize()
350
351
	for i = 1, x do
352
353
		buttonInstance.clickMap[i] = {}
354
355
	end
356
357
	setmetatable(buttonInstance, {__index = Button})
358
359
	return buttonInstance
360
361
end