This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
men8's profile picture

TouchScreen button menu

Started by men8, 11 February 2014 - 03:51 PM
men8 #1
Posted 11 February 2014 - 04:51 PM
Ok, so I'm working on my little project, TouchScreen Button menu to operate my machines from one place. I'm using Direwolf20 buttonAPI which I edit a little bit to my personal use so now i can set different colors for all my buttons. I figured how to change pages with buttons on my monitor, but I want to add function to code that let me set two different functions. One when button is on, and one when button is off. So, this is the code I've got :
Spoiler

local mon = peripheral.wrap("top")
mon.setTextScale(1)
mon.setTextColor(colors.white)
local button={}
mon.setBackgroundColor(colors.blue)
function clearTable()
   button = {}
   mon.clear()
end
			
function setTable(name, func, xmin, xmax, ymin, ymax, btnOff, btnOn)
   button[name] = {}
   button[name]["func"] = func
   button[name]["active"] = false
   button[name]["xmin"] = xmin
   button[name]["ymin"] = ymin
   button[name]["xmax"] = xmax
   button[name]["ymax"] = ymax
   button[name]["btnOff"] = btnOff
   button[name]["btnOn"]  = btnOn
end
function funcName()
   print("You clicked buttonText")
end
	  
function fillTable()
   setTable("ButtonText", funcName, 5, 25, 4, 8)
end  
function fill(text, color, bData)
   mon.setBackgroundColor(color)
   local yspot = math.floor((bData["ymin"] + bData["ymax"]) /2)
   local xspot = math.floor((bData["xmax"] - bData["xmin"] - string.len(text)) /2) +1
   for j = bData["ymin"], bData["ymax"] do
	  mon.setCursorPos(bData["xmin"], j)
	  if j == yspot then
		 for k = 0, bData["xmax"] - bData["xmin"] - string.len(text) +1 do
			if k == xspot then
			   mon.write(text)
			else
			   mon.write(" ")
			end
		 end
	  else
		 for i = bData["xmin"], bData["xmax"] do
			mon.write(" ")
		 end
	  end
   end
   mon.setBackgroundColor(colors.blue)
end
  
function screen()
   local currColor
   for name,data in pairs(button) do
	  local on = data["active"]
	  if on == true then currColor = data["btnOn"] else currColor = data["btnOff"] end
	  fill(name, currColor, data)
   end
end
function toggleButton(name)
   button[name]["active"] = not button[name]["active"]
   screen()
end  
function flash(name)
   toggleButton(name)
   screen()
   sleep(0.15)
   toggleButton(name)
   screen()
end
										  
function checkxy(x, y)
   for name, data in pairs(button) do
	  if y>=data["ymin"] and  y <= data["ymax"] then
		 if x>=data["xmin"] and x<= data["xmax"] then
			data["func"]()
			return true
			--data["active"] = not data["active"]
			--print(name)
		 end
	  end
   end
   return false
end
  
function heading(text)
   w, h = mon.getSize()
   mon.setCursorPos((w-string.len(text))/2+1, 1)
   mon.write(text)
end
  
function label(w, h, text)
   mon.setCursorPos(w, h)
   mon.write(text)
end

I don't know is this posible but i think i must change function setTable and screen to this:
Spoiler

function setTable(name, func1, func2, xmin, xmax, ymin, ymax, btnOff, btnOn)
   button[name] = {}
   button[name]["func1"] = func1
   button[name]["func2"] = func2
   button[name]["active"] = false
   button[name]["xmin"] = xmin
   button[name]["ymin"] = ymin
   button[name]["xmax"] = xmax
   button[name]["ymax"] = ymax
   button[name]["btnOff"] = btnOff
   button[name]["btnOn"]  = btnOn
end

function screen()
   local currColor
   local currFunc
   for name,data in pairs(button) do
	  local on = data["active"]
	  if on == true then
		 currColor = data["btnOn"] and currFunc = data["func1"]
	  else
		 currColor = data["btnOff"] and currFunc = data["func2"]
	  end
	  fill(name, currColor, currFunc, data)
   end
end

This is the one thing left to do in my project so if anybody can help me with my problem, I'll be really happy. I'm really sorry if this post is in non "english" form, but it's not my main language. I also search for any results on this forum and on google and youtube and i can't find anything what can help me in my problem
surferpup #2
Posted 11 February 2014 - 07:04 PM
Your syntax is a bit off. Look at what I mean:


function setTable(name, func1, func2, xmin, xmax, ymin, ymax, btnOff, btnOn)
   button.name = {}
   button.name.func1 = func1
   button.name.func2 = func2
   button.name.active = false
   button.name.xmin = xmin
   button.name.ymin = ymin
   button.name.xmax = xmax
   button.name.ymax = ymax
   button.name.btnOff = btnOff
   button.name.btnOn  = btnOn
end
men8 #3
Posted 11 February 2014 - 08:00 PM
Yes @surferpup, I know, but it's working in this form. The thing is I don't know how to add secound functions to one button, so if I activate the button first function should work and if I deactivate it the secound function should work. I can stop editing code because it's working, but to start and end one thing i must use two buttons. This is the code of program that use this API.
Spoiler
rednet.open("bottom")
os.loadAPI("button")
m = peripheral.wrap("top")
m.clear()
————————————————————————-
function fillTable1()
button.setTable("Inne ON" , inneON , 2 ,14,3 ,5 ,colors.lime , colors.red)
button.setTable("Inne OFF" , inneOFF , 2 ,14,7 ,9 ,colors.lime , colors.red)
button.setTable("COS ON" , cosON , 2 ,14,11,13,colors.green , colors.red)
button.setTable("COS OFF" , cosOFF , 2 ,14,15,17,colors.green , colors.red)
button.setTable("test1" , test1 , 16,26,11,13,colors.lime , colors.red)
button.setTable("test2" , test2 , 16,26,15,17,colors.lime , colors.red)
button.setTable("test3" , test3 , 28,38,11,13,colors.green , colors.red)
button.setTable("test4" , test4 , 28,38,15,17,colors.green , colors.red)
button.setTable("Prev" , prev1 , 16,26,7 ,9 ,colors.magenta, colors.purple)
button.setTable("Next" , next1 , 28,38,7 ,9 ,colors.magenta, colors.purple)
button.screen()
end
————————————————————————-
function fillTable()
button.setTable("Swiatlo ON" , swON , 2 ,14,3 ,5 ,colors.lime , colors.red)
button.setTable("Swiatlo OFF", swOFF , 2 ,14,7 ,9 ,colors.lime , colors.red)
button.setTable("COM ON" , comON , 2 ,14,11,13,colors.green , colors.red)
button.setTable("COM OFF" , comOFF, 2 ,14,15,17,colors.green , colors.red)
button.setTable("Prev" , prev , 16,26,7 ,9 ,colors.magenta, colors.purple)
button.setTable("Next" , next , 28,38,7 ,9 ,colors.magenta, colors.purple)
button.screen()
end
————————————————————————-
–funkcje fillTable——————————————————
————————————————————————-
function swON()
button.flash("Swiatlo ON")
rednet.send(24, "swON")
rs.setOutput("back", false)
end

function swOFF()
button.flash("Swiatlo OFF")
rs.setOutput("back", true)
rednet.send(24, "swOFF")
end

function comON()
button.flash("COM ON")
rednet.send(18, "ON")
end

function comOFF()
button.flash("COM OFF")
rednet.send(18, "OFF")
end

function prev()
button.flash("Prev")
button.clearTable()
ramka()
button.label(30,5,"2")
fillTable1()
end

function next()
button.flash("Next")
button.clearTable()
ramka()
button.label(30,5,"2")
fillTable1()
end
————————————————————————-
–funkcje fillTable1—————————————————–
————————————————————————-
function inneON()
button.flash("Inne ON")
end

function inneOFF()
button.flash("Inne OFF")
end

function cosON()
button.flash("COS ON")
end

function cosOFF()
button.flash("COS OFF")
end

function prev1()
button.flash("Prev")
button.clearTable()
ramka()
button.label(30,5,"1")
fillTable()
end

function next1()
button.flash("Next")
button.clearTable()
ramka()
button.label(30,5,"1")
fillTable()
end
————————————————————————-
function ramka()
button.heading("Panel zdalnego sterowania men8")
button.label(1 ,2 ,"o————-o")
button.label(1 ,3 ,"|")
button.label(1 ,4 ,"|")
button.label(16,4 ," Wybor strony ")
button.label(16,5 ," Strona: ")
button.label(1 ,5 ,"|")
button.label(1 ,6 ,"|")
button.label(1 ,7 ,"|")
button.label(1 ,8 ,"|")
button.label(1 ,9 ,"|")
button.label(15,3 ,"|")
button.label(15,4 ,"|")
button.label(15,5 ,"|")
button.label(15,6 ,"|")
button.label(15,7 ,"|")
button.label(15,8 ,"|")
button.label(15,9 ,"|")
button.label(1 ,10,"o————-+")
button.label(1 ,11,"|")
button.label(1 ,12,"|")
button.label(1 ,13,"|")
button.label(1 ,14,"|")
button.label(1 ,15,"|")
button.label(1 ,16,"|")
button.label(1 ,17,"|")
button.label(15,11,"|")
button.label(15,12,"|")
button.label(15,13,"|")
button.label(15,14,"|")
button.label(15,15,"|")
button.label(15,16,"|")
button.label(15,17,"|")
button.label(1 ,18,"o————-o")
button.label(16,10,"———–o———–o")
button.label(27,11,"|")
button.label(27,12,"|")
button.label(27,13,"|")
button.label(27,14,"|")
button.label(27,15,"|")
button.label(27,16,"|")
button.label(27,17,"|")
button.label(16,2 ,"———————–o")
button.label(16,18,"———–o———–o")
button.label(39,11,"|")
button.label(39,12,"|")
button.label(39,13,"|")
button.label(39,14,"|")
button.label(39,15,"|")
button.label(39,16,"|")
button.label(39,17,"|")
button.label(39,3 ,"|")
button.label(39,4 ,"|")
button.label(39,5 ,"|")
button.label(39,6 ,"|")
button.label(39,7 ,"|")
button.label(39,8 ,"|")
button.label(39,9 ,"|")
end

function getClick()
event,side,x,y = os.pullEvent("monitor_touch")
button.checkxy(x,y)
end
————————————————————————-
fillTable()
button.heading("Panel zdalnego sterowania men8")
button.label(1 ,2 ,"o————-o")
button.label(1 ,3 ,"|")
button.label(1 ,4 ,"|")
button.label(16,4 ," Wybor strony ")
button.label(16,5 ," Strona: ")
button.label(1 ,5 ,"|")
button.label(1 ,6 ,"|")
button.label(1 ,7 ,"|")
button.label(1 ,8 ,"|")
button.label(1 ,9 ,"|")
button.label(15,3 ,"|")
button.label(15,4 ,"|")
button.label(15,5 ,"|")
button.label(15,6 ,"|")
button.label(15,7 ,"|")
button.label(15,8 ,"|")
button.label(15,9 ,"|")
button.label(1 ,10,"o————-+")
button.label(1 ,11,"|")
button.label(1 ,12,"|")
button.label(1 ,13,"|")
button.label(1 ,14,"|")
button.label(1 ,15,"|")
button.label(1 ,16,"|")
button.label(1 ,17,"|")
button.label(15,11,"|")
button.label(15,12,"|")
button.label(15,13,"|")
button.label(15,14,"|")
button.label(15,15,"|")
button.label(15,16,"|")
button.label(15,17,"|")
button.label(1 ,18,"o————-o")
button.label(16,10,"———–o———–o")
button.label(27,11,"|")
button.label(27,12,"|")
button.label(27,13,"|")
button.label(27,14,"|")
button.label(27,15,"|")
button.label(27,16,"|")
button.label(27,17,"|")
button.label(16,2 ,"———————–o")
button.label(16,18,"———–o———–o")
button.label(39,11,"|")
button.label(39,12,"|")
button.label(39,13,"|")
button.label(39,14,"|")
button.label(39,15,"|")
button.label(39,16,"|")
button.label(39,17,"|")
button.label(39,3 ,"|")
button.label(39,4 ,"|")
button.label(39,5 ,"|")
button.label(39,6 ,"|")
button.label(39,7 ,"|")
button.label(39,8 ,"|")
button.label(39,9 ,"|")

while true do
getClick()
end

This is not auto size screen so w=4 and h=3 monitors
Lyqyd #4
Posted 11 February 2014 - 08:35 PM
Your syntax is a bit off. Look at what I mean:


function setTable(name, func1, func2, xmin, xmax, ymin, ymax, btnOff, btnOn)
   button.name = {}
   button.name.func1 = func1
   button.name.func2 = func2
   button.name.active = false
   button.name.xmin = xmin
   button.name.ymin = ymin
   button.name.xmax = xmax
   button.name.ymax = ymax
   button.name.btnOff = btnOff
   button.name.btnOn  = btnOn
end

I'm really not sure what you're trying to say. This code you've posted is wrong, but what are you trying to say is wrong with his?
surferpup #5
Posted 11 February 2014 - 10:31 PM
I see, I was a bit quick there. I was trying to show that instead of using this syntax:


button.name.["func"] = func

He could do:


button.name.func = func

What I missed was that he does use the contents of name as a key, so it should be:


button[name].func = func

That is cleaner and easier to troubleshoot.
surferpup #6
Posted 11 February 2014 - 11:51 PM
So, now that I have actually looked over your code and more carefully read your question (sorry about that), this is what I am actually covering in Part II and Part III of my Monitor Button and Control Tutorial. Parts I and II are done, and Part III covers exactly what you are trying to do (it is in draft). Your approach is slightly different than mine.

Your approach is basically fine.

It appears that you want to use the fill() function to execute the action. The only thing you need to do then is modify your function prototype for fill and then call the function you pass.

So I'd suggest changing your fill prototype to


function fill(text, color, bData, func)

I put func on the end so you don't need to worry about changing all of your calls.

Then in the fill function, call it (note that I put some error checking in it).


if func and type(func) == "function" -- for error checking
  func()
end

Make sure to fix all of your function calls as well.
Edited on 11 February 2014 - 11:03 PM
Bomb Bloke #7
Posted 12 February 2014 - 01:01 AM
Just to be clear, this:

button.name.func = func

… won't work as desired under any circumstance. It'll create a new key called "name" inside the "button" table, ignoring the "name" variable passed to the "setTable" function. If a key called "name" already exists in that table (which WILL be the case after the first call to "setTable"), then it'll simply be overwritten.

This:

button.name.["func"] = func

… is also invalid, for the exact same reason and also due to that second period (which shouldn't be there).

The OP's code is indeed fine as-is, but this would be ever-so-slightly faster to execute:

button[name].func = func

In terms of human readability, it makes next to no difference. That comes down to taste.
Edited on 12 February 2014 - 12:02 AM
men8 #8
Posted 12 February 2014 - 06:36 AM
So, anybody can help with my problem, because I know my code is working but when I tried to edit buttonAPI in this functions
So, now that I have actually looked over your code and more carefully read your question (sorry about that), this is what I am actually covering in Part II and Part III of my Monitor Button and Control Tutorial. Parts I and II are done, and Part III covers exactly what you are trying to do (it is in draft). Your approach is slightly different than mine.

Your approach is basically fine.

It appears that you want to use the fill() function to execute the action. The only thing you need to do then is modify your function prototype for fill and then call the function you pass.

So I'd suggest changing your fill prototype to


function fill(text, color, bData, func)

I put func on the end so you don't need to worry about changing all of your calls.

Then in the fill function, call it (note that I put some error checking in it).


if func and type(func) == "function" -- for error checking
  func()
end

Make sure to fix all of your function calls as well.
I'm sorry but I think I don't understand this correcty. This code is for two different functions assigned to one button or what?
surferpup #9
Posted 13 February 2014 - 12:24 PM
You suggested doing the following to change functions:


function screen()
   local currColor
   local currFunc
   for name,data in pairs(button) do
		  local on = data["active"]
		  if on == true then
				 currColor = data["btnOn"] and currFunc = data["func1"]
		  else
				 currColor = data["btnOff"] and currFunc = data["func2"]
		  end
		  fill(name, currColor, currFunc, data)
   end
end

Your if … then code is slightly off:



if on == true then
  currColor = data["btnOn"]
  currFunc = data["func1"]
else
  currColor = data["btnOff"]
  currFunc = data["func2"]
end

currFunc will be assigned one of the two functions you store in data.func1 or data.func2

As long as data.func1 or data.func2 are functions, a call to currFunct(…) will succeed.

When I said your approach is correct for the most part, I am referring to your idea here.
Edited on 13 February 2014 - 11:25 AM