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

Alternate Way to Trigger Buttons

Started by callawh, 14 March 2014 - 03:23 AM
callawh #1
Posted 14 March 2014 - 04:23 AM
Hello, I'm this is my first post so I'll try to make it great. I've been making a program that would have many buttons to control random things. I've made a function that allows for easily creating buttons on the advanced monitors. The function has you enter several parameters such as the coordinates and the text, in order to create the button for you. I've successfully done that, but now I need the buttons to trigger events. I made the function return an array for each button with important values that tell the program what the "touch boundaries" are and the program the button will trigger. I would like to be able to just have all the buttons waiting to be triggered at the same time, but with an if statement, only one can wait at a time. It's difficult to explain but I don't want to set up all the arrays with a bunch of elseifs to trigger the buttons because I want to only create the button with the parameters and let the program take care of the rest. This way the program would be very flexible and easy to change around.

I'm no expert on programming and this is defiantly not the most efficient program, but here it is.


file = fs.open("/disk/info/side.dat", "r") -- find the side of the monitor
side = file:readLine()
m = peripheral.wrap(side)

function header()
  m.setBackgroundColor(colours.black)
  m.clear()
  m.setCursorPos(1,1)
  m.setBackgroundColor(colours.red)
  m.write("																				  ")
  m.setCursorPos(1,2)
  m.write("																				  ")
end

function button(x, y, width, length, xDistance, yDistance, fileName, text) -- point program starts, length and width, distance text is from side and top, file name this button will open, text on the button
  area = {}
  area[1] = x
  area[2] = y
  area[3] = x - 1 + width  -- store information for button touch perimeter and file it opens
  area[4] = y - 1 + length
  area[5] = fileName
  yy = length
  line = y
  m.setCursorPos(x,y)
  m.setBackgroundColor(colours.white)
  m.setTextColor(colours.black)
  while yy > 0 do -- drawing the button
	xx = width
	m.setCursorPos(x,line)
	while xx > 0 do
	  m.write(" ")
	  xx = xx - 1
	end
	line = line + 1
	yy = yy - 1
  end
  m.setCursorPos(x + xDistance, y + yDistance) -- writing the text
  m.write(text)
  return area
end

header()
rs.setOutput("left", true) -- turns on a redstone light in front of the monitor

area = button(5, 7, 7, 3, 1, 1, "temp", "Hello")
Lyqyd #2
Posted 14 March 2014 - 05:10 AM
The way I did this sort of event filtering for my Touchpoint API was to create a "click map" table as buttons are added, then check click coordinates in that table when a click event is received.

Detecting a click is then as simple as:


if event[1] == "monitor_touch" and event[2] == self.side then
        local clicked = self.clickMap[event[3]][event[4]]
        if clicked and self.buttonList[clicked] then
                return "button_click", clicked
        end
end

Setting up the click map isn't too complicated, this initializes a new empty click map:


for i = 1, x do  --# x is the width of the monitor, from .getSize().
    buttonInstance.clickMap[i] = {}
end

When adding a button, you simply have to fill in the appropriate coordinate entries. This set of loops adds the button, but reverses the changes and errors if it detects any overlaps with existing buttons in the click map:


for i = xMin, xMax do
    for j = yMin, yMax do
        if self.clickMap[i][j] ~= nil then
            --undo changes
            for k = xMin, xMax do
                for l = yMin, yMax do
                    if self.clickMap[k][l] == name then
                        self.clickMap[k][l] = nil
                    end
                end
            end
            self.buttonList[name] = nil
            error("overlapping button", 2)
        end
        self.clickMap[i][j] = name
    end
end

I'm not usually a fan of answering a question by simply dumping a bunch of code, but that should give you some ideas to work with. If you have any questions about this way of going about it, feel free to ask! If this isn't the route you want to take, some more details about what you do want it to do would help.
callawh #3
Posted 14 March 2014 - 11:38 AM
Thank you for responding so quickly and thanks for the help!