Fingercomp 37 Posted July 10, 2017 Share Posted July 10, 2017 As an author of a few programs that heavily used different GUI libraries, I have found problems in your current library. The approach it going to work for really simple programs, but when someone uses it for bigger projects, it becomes really hard to use. Below are some of problems I've found. You wanted feedback, after all. Why not use OOP? So that GUI elements could be modified in some way by calling its method, like menu:addSeparator(). OOP is a really great choice when making GUI libraries. It's incredibly hard to add a custom element that would use your GUI system. Every program with GUI I've written needed some elements that were not provided by a GUI library I used. With proper OOP, it becomes a really easy thing. Without OOP or support for adding custom objects, it's often a pain. Your code exports some functions to the global environment. A user can accidentally override such functions and break the library. Use local whenever possible. Only export functions via the return statement. (Note, adding local when defining function in a table is a syntax error: local function tbl.func() end will not work.) GUIs quickly become more complex as more features are added. Using your library, it's hardly possible to change a button callback to another function. Ideally, it'd be something like button.callback = function() print("Now it does something else") end. You also can't switch a button to the pressed state, you can't add child objects (like a label on a frame in a container). Quote Link to post Share on other sites
Dustpuppy 16 Posted July 10, 2017 Author Share Posted July 10, 2017 The export of local functions i've solved. Functions can be changed on every element. Now a kind of custom element can be set by using the new element function directly. So, it's possible to make multiline label, taht acts like a button. But i have no clue about OOP. Never used it. Started coding when i used OC the first time ;-) Quote Link to post Share on other sites
Molinko 43 Posted July 10, 2017 Share Posted July 10, 2017 @Fingercomp makes a great point. 1 hour ago, Fingercomp said: Why not use OOP? So that GUI elements could be modified in some way by calling its method (...) Without trying to use too much jargon.. OOP or Object Oriented Programming is a style of program or library organization that pairs 'Classes' with 'Instances'. This is hard to explain so I'll use an example that hopefully will demonstrate why OOP can be a powerful paradigm and useful to learn. -- # Person. Our 'Base' class for a set of more complex classes. local Person = {} -- # Use Person(name, age, sex) to use as an instance constructor. Person.__index = Person setmetatable(Person, { __call = function(_, name, age, sex) local person = { name = name, age = age, sex = sex } return setmetatable(person, Person) end }) function Person:introduce() return ("Hello, my name is %s."):format(self.name) end function Person:greet(otherPerson) return self:introduce() .. (" Nice to meet you %s."):format(otherPerson.name) end -- # Now we can create 'Persons' or 'instances' of Persons as we call them in OOP. local bob = Person('Bob', 49, 'male') local jane = Person('Jane', 33, 'female') print( bob:greet(jane) ) -- # > "Hello, my name is Bob. Nice to meet you Jane." -- # This is where OOP really shines and why it would be recommeneded. 'Inheritance'. local Wizard = {} Wizard.__index = Wizard setmetatable(Wizard, { __call = function(_, name, age, sex, spells) local wizard = Person(name, age, sex) -- # create a wizard from the Person class. Wizards are people too. Not all People are Wizards. wizard.spells = spells -- # Wizard specific return setmetatable(wizard, Wizard) -- # bestow Wizard methods upon wizard instance. end, -- # inheritance __index = Person -- # If a method or field isn't within a 'Wizard' then fallback to the 'Base' which is 'Person'. i.e wizardInstance:greet(bob) }) -- # Sub-class method override. function Wizard:introduce() -- # Wizard introductions should state the prestige that they are Wizards! return ("Hello, my name is %s the wizard."):format(self.name) end -- # Wizard:greet is inherited from Person. function Wizard:cast(spell, target) assert(self.spells[spell], "Invalid spell. Your Wizard is weak.") return ("%s the wizard casts '%s' upon %s for %d damage."):format(self.name, spell, target.name, self.spells.damage) end local merlin = Wizard("Merlin", 61, "male", { ["Abbra"] = { name = "Abbra", damage = 12 } }) -- # Notice :greet() is inherited from Person class but uses the merlin instances version of :introduce() print( merlin:greet(bob) ) -- # > "Hello, my name is Merlin the wizard. Nice to meet you Bob." print( merlin:cast('Abbra', bob) ) -- # > "Merlin the wizard casts 'Abbra' upon Bob for 12 damage." -- # End I hope this example can illustrate to you the advantages of OOP design. Any questions? ask away Quote Link to post Share on other sites
Dustpuppy 16 Posted July 10, 2017 Author Share Posted July 10, 2017 OK, now i am fully lost. That's too much for my little brain at the moment. Don't you think it is too complicated for the normal user? Most people using lua in OC are beginners , not coders. Even it is complicated to me, i am talking about the normal player, who just want to put some information on his screen. Quote Link to post Share on other sites
Molinko 43 Posted July 11, 2017 Share Posted July 11, 2017 yeah.. I was worried it might just look like spaghetti... 3 hours ago, Dustpuppy said: Don't you think it is too complicated for the normal user? Most people using lua in OC are beginners , not coders. Even it is complicated to me, i am talking about the normal player, who just want to put some information on his screen. Yes and No. Yes. The user of the library doesn't need or want to know how the library works to be able to use it and shouldn't have to either. No, because anyone like @Fingercomp who might like to use your library, even if it lacks a specific element, might like to be able to integrate a custom element and not have to write an entire library to do it. A good example would be to think of how similar a 'Label' and a 'Button' object are to each other. They can share ~90% of their code, so why rewrite the other 90% of a button if its just like a label with a touch event listener. -- # ... more gui shit above.. local Label = {} Label.__index = Label function Label:draw(fg, bg) local ofg, obg = gpu.setForground(fg), gpu.setBackground(bg) -- # self here refers to the label instance. The specific label calling draw. Label:draw is really a shorcut for Label.draw(labelInstance, fg, bg) gpu.fill(self.x, self.y, self.width, self.height, " ") -- # draw the box gpu.set( math.floor((self.x + self.width - 1) / 2 + #self.text / 2 + .5), math.floor(self.height / 2 + .5), self.text ) -- # center the label text. ugly gpu.setForground(ofg) -- # reset the fg and bg colors gpu.setBackground(obg) end local function newLabel(x, y, text, w, h) return setmetatable({ x = x, y = y, text = text, width = w, height = h }, Label) end local Button = setmetatable({}, {__index = Label}) -- # look to Label for :draw method Button.__index = Button local function newButton(x, y, text, w, h, action) local button = newLabel(x, y, text, w, h) button.action = action local listener = function(...) local _, x, y = ... if x >= self.x and x <= self.x + self.width - 1 then if y >= self.y and y <= self.y + self.height - 1 then action() end end end event.listen('touch', listener) -- # this is easy for the demo here but can be a memory leak if left after the program ends... return setmetatable(button, Button) end -- # End I hope this example, although not much less complicated, will help convey the point. Quote Link to post Share on other sites
Fingercomp 37 Posted July 11, 2017 Share Posted July 11, 2017 When I was writing that response, I didn't really know, well, how experienced you are at Lua programming. OOP in general, not in Lua, isn't really advanced. Many languages allow to write in object-oriented style. To name a few: Java, Python, C++. If you don't know what OOP is, writing a few programs in these languages can help to understand the subject. OOP in Lua is really complicated. It requires using of metatables -- and that is advanced. In library, the code may quickly become complicated and hard to maintain. Instead of messing with metatables, I prefer to use libraries that nicely hide all the mess. It's just me searching for the greatest library possible, and someone would need quite a lot of Lua experience to create a library I would be satisfied with. So if you don't want to rewrite the whole GUI library once again and want to keep it as it is, I am not going to stop you. If you can't do OOP, do what you can, or you can easily lose the motivation. Create the library you want, not I. Your current way is very beginner-friendly, so Lua beginners might use it, while I would stick to using some other library. Quote Link to post Share on other sites
Molinko 43 Posted July 11, 2017 Share Posted July 11, 2017 7 minutes ago, Fingercomp said: When I was writing that response, I didn't really know, well, how experienced you are at Lua programming. Thanks, you're nice . It was my first language. 7 minutes ago, Fingercomp said: OOP in general, not in Lua, isn't really advanced. Many languages allow to write in object-oriented style. To name a few: Java, Python, C++. If you don't know what OOP is, writing a few programs in these languages can help to understand the subject. ^^^ THIS. So much yes. I had a hard time grasping the concept of OOP at first because Lua doesn't have many of the features an OO language like Java and so on.. Personally an OOP-like library is the only real practical way in my opinion to even use OO in Lua. Writing actual program logic doesn't work so well this way.. Gets bloated quick. BUT, an OO library is easy to extend for a use case should you need it. 13 minutes ago, Fingercomp said: It's just me searching for the greatest library possible, and someone would need quite a lot of Lua experience to create a library I would be satisfied with. Oh boy I've been trying forever to get this right. When I do I'll let you know . @Dustpuppy 15 minutes ago, Fingercomp said: If you can't do OOP, do what you can, or you can easily lose the motivation. Create the library you want, not I. Your current way is very beginner-friendly, so Lua beginners might use it I agree. I just wanted to show you how big the world is... lol. If you really want to twist your brain for the better check out Functional programming. Also, a useful mind-fuck. As for the intended style Lua was built for... I believe its intended to be Procedural with a dash of meta-programming. As I said earlier, Lua was my first and still my favorite. This has been a nice discussion . Quote Link to post Share on other sites
CocoVanChoco 0 Posted August 17, 2017 Share Posted August 17, 2017 Awesome Gui. Im very new to Lua but not to Programming at all. With this Gui i was able to do the stuff i wanted. Terrasteel Automation. Well my Program isnt finished yet, and needs some advanced stuff to do to like mana checks etc. but it works well for now and at least for me. Your Designer has some issues with List Creation it lacks beginning " and ending " in the List Title but its easy to fix it myself. I searched so much on youtube and reddit posts for some solutions to create it fully automated, but got only some hints and ideas. so i'll share the WIP Code here for someones needs. The Setup is kinda simple. its just a very Small Refined Storage system wich holds just the Credients needed for the Terrasteel Ingot. Then it needs just an Interface + OC Adapter without any Upgrade in it. Then there is 1 Chest wich gets the Items step by step with a 5 seconds sleep timer to get ready for the next one (this may be adjusted for slower mana flows so the steel can be made till the next items can put in place with the Open Crate. Another Chest with an Advanced Item Collector (Random Things mod with item filter) takes the Terrasteel only. (I personally take this chest into my AE2 ME System but you can work with whatever you want here. Hope this helps one or another. Keep in mind its still WIP, working but needs additional checks and things. But you get ideas as well. Cheers Coco <3 local component = require("component") local gpu = component.gpu gpu.setResolution(160,50) local gui = require("gui") local event = require("event") local sides = require("sides") local rsInterface = component.block_refinedstorage_interface gui.checkVersion(2,5) local prgName = "botanics" local version = "v1.0" local function getContentAmount(material) local allItems = rsInterface.getItems() for i, item in ipairs(allItems) do if(item.label == material) then --getContent = rsInterface.getItem(item, true) return (item.size) end end end local function getItemToCraft(material) local allItems = rsInterface.getItems() for s, item in ipairs(allItems) do if(item.label == material) then --local getCraftItem = rsInterface.getItem(item, true) rsInterface.extractItem(item, 1, sides.right) end end end -- Begin: Callbacks local function order_list_callback(guiID, listID, selected, text) -- Your code here if (text == 'Terrasteel') then material_label = 'Terrasteel' material_content_1 = 'Mana Pearl' material_content_2 = 'Manasteel Ingot' material_content_3 = 'Mana Diamond' material_amount_1 = getContentAmount(material_content_1) material_amount_2 = getContentAmount(material_content_2) material_amount_3 = getContentAmount(material_content_3) else material_label = 'Waehle aus' material_content_1 = '' material_content_2 = '' material_content_3 = '' end gui.newLabel(mainGui, 56, 2, ""..material_label.."", 0xc3c3c3, 0x0, 15) gui.newLabel(mainGui, 56, 4, ""..material_content_1.."", 0xc3c3c3, 0x0, 15) if (text == 'Terrasteel' and material_amount_1 > 0) then gui.newLabel(mainGui, 75, 4, ""..material_amount_1.."", 0xc3c3c3, 0x33ff00, 7) else gui.newLabel(mainGui, 75, 4, "missing", 0xc3c3c3, 0xff0000, 7) end gui.newLabel(mainGui, 56, 5, ""..material_content_2.."", 0xc3c3c3, 0x0, 15) if (text == 'Terrasteel' and material_amount_2 > 0) then gui.newLabel(mainGui, 75, 5, ""..material_amount_2.."", 0xc3c3c3, 0x33ff00, 7) else gui.newLabel(mainGui, 75, 5, "missing", 0xc3c3c3, 0xff0000, 7) end gui.newLabel(mainGui, 56, 6, ""..material_content_3.."", 0xc3c3c3, 0x0, 15) if (text == 'Terrasteel' and material_amount_3 > 0) then gui.newLabel(mainGui, 75, 6, ""..material_amount_3.."", 0xc3c3c3, 0x33ff00, 7) else gui.newLabel(mainGui, 75, 6, "missing", 0xc3c3c3, 0xff0000, 7) end gui.displayGui(mainGui) end local function text_menge_callback(guiID, textID, text) local toCraft = text return toCraft end local function button_start_callback(guiID, buttonID) local toCraft = guiID[3].text local counter = 0 local limiters = tonumber(toCraft) progress = gui.newProgress(guiID, 2, 18, 35, limiters, 0, nil, true) for i = 1, toCraft do -- print(toCraft, material_label, material_content_1, material_content_2, material_content_3) gui.displayGui(guiID) getItemToCraft(material_content_1) getItemToCraft(material_content_2) getItemToCraft(material_content_3) order_list_callback(guiID, nil, nil, material_label) counter = counter + 1 if counter <= limiters then gui.setValue(guiID, progress, counter) end if counter > limiters then counter = 0 end os.sleep(5) end end local function exitButtonCallback(guiID, id) local result = gui.getYesNo("", "Do you really want to exit?", "") if result == true then gui.exit() end gui.displayGui(mainGui) refresh() end -- End: Callbacks -- Begin: Menu definitions mainGui = gui.newGui(2, 2, 158, 48, true) order_list = gui.newList(mainGui, 1, 1, 50, 15, {}, order_list_callback, "Was soll hergestellt werden?") gui.insertList(mainGui, order_list, "Waehle aus") gui.insertList(mainGui, order_list, "Terrasteel") label_menge = gui.newLabel(mainGui, 54, 12, "Menge:", 0xc3c3c3, 0x0, 7) text_menge = gui.newText(mainGui, 54, 13, 10, "0", text_menge_callback, 20, false) button_start = gui.newButton(mainGui, 54, 15, "Starten", button_start_callback) frame_info = gui.newFrame(mainGui, 54, 1, 40, 10) exitButton = gui.newButton(mainGui, 151, 48, "exit", exitButtonCallback) -- End: Menu definitions gui.clearScreen() gui.setTop("Terrestrial Agglomeration Plate Automation") gui.setBottom("Made with Visual Gui v0.1a and Gui library v2.5") -- Main loop while true do gui.runGui(mainGui) end Quote Link to post Share on other sites
Ginkoe 0 Posted March 17, 2018 Share Posted March 17, 2018 Hi, i have a lil problem with the gui, whenever my chunk is unload, the computer shutdown, and when i comeback, i can't make it works again. Everything made with the lib doesn't work, it show the blue screen of the interface, but doesn't add any button or component, and just makes me return to the /home folder. any help please Quote Link to post Share on other sites
fmate2006 0 Posted December 16, 2018 Share Posted December 16, 2018 Quote Link to post Share on other sites
vratk0529 0 Posted January 3, 2019 Share Posted January 3, 2019 I have error: Code is: local component = require("component") local gpu = component.gpu gpu.setResolution(80,25) local gui = require("gui") local event = require("event") gui.checkVersion(2,5) local prgName = "security" local version = "v1.0" -- Begin: Callbacks local function fire(guiID, buttonID) -- Your code here end local function armoured-true(guiID, buttonID) -- Your code here end local function armoured-false(guiID, buttonID) -- Your code here end local function power-on(guiID, buttonID) -- Your code here end local function power-off(guiID, buttonID) -- Your code here end local function height(guiID, textID, text) -- Your code here end local function rotation(guiID, textID, text) -- Your code here end local function exitButtonCallback(guiID, id) local result = gui.getYesNo("", "Do you really want to exit?", "") if result == true then gui.exit() end gui.displayGui(mainGui) refresh() end -- End: Callbacks -- Begin: Menu definitions mainGui = gui.newGui(1, 2, 79, 23, true) Fire = gui.newButton(mainGui, 1, 1, "Fire!", fire) Rotaion-label = gui.newLabel(mainGui, 1, 3, "Rotation", 0xc0c0c0, 0x0, 7) Height-label = gui.newLabel(mainGui, 1, 5, "Height", 0xc0c0c0, 0x0, 7) Armoured-true = gui.newButton(mainGui, 27, 1, "Set ready", armoured-true) Armoured-false = gui.newButton(mainGui, 12, 1, "Not ready", armoured-false) Power-on = gui.newButton(mainGui, 42, 1, "Power on", power-on) Power-off = gui.newButton(mainGui, 56, 1, "Power off", power-off) Height-value = gui.newText(mainGui, 10, 5, 2, "", height, 10, false) Rotation-value = gui.newText(mainGui, 10, 3, 2, "", rotation, 10, false) exitButton = gui.newButton(mainGui, 73, 23, "exit", exitButtonCallback) -- End: Menu definitions gui.clearScreen() gui.setTop("Energy turret operation software") gui.setBottom("Made with Visual Gui v0.1a and Gui library v2.5") -- Main loop while true do gui.runGui(mainGui) end Quote Link to post Share on other sites
SpaceBeeGaming 3 Posted January 3, 2019 Share Posted January 3, 2019 @vratk0529 function names can't have (-) characters in them as it is interpreted as a minus. You have to use underscores (_). Quote Link to post Share on other sites
duz_holger 1 Posted February 2, 2019 Share Posted February 2, 2019 i don't know if its the guis fault but back space throws a symbol instead of working on 2 programs that clearly uses your gui editor btw I run micraft on a Mac OS X system Quote Link to post Share on other sites
Chaoschaot234 0 Posted August 31, 2019 Share Posted August 31, 2019 Is there a current valid link to the library? The latest link isn't available anymore Quote Link to post Share on other sites
CptMercury 6 Posted August 31, 2019 Share Posted August 31, 2019 @Chaoschaot234 I think this version is deprecated. Dustpuppy made a new guy lib with more features etc. Have a look at it. Here's the forum post Its installer link is working properly, I just checked. Quote Link to post Share on other sites
JackPS9 0 Posted March 6, 2020 Share Posted March 6, 2020 Have to admit the GUI editor and the GUI library are really handy. Was able to toss together a script that displays my bases power levels fairly quickly. My only real issue with the GUI Editor is the overwriting of code a person makes if they change the GUI later on using the editor. I overcame the issue though by doing a work around for it, just wrote my own library that requires the GUI one and do all my edits to the values/text of my UI in my library. All I have to do is pass the guiID, a progressbarID, labelID and address of the components I wish get my info from. Quote Link to post Share on other sites
the weirdmageddon 1 Posted October 23, 2021 Share Posted October 23, 2021 Hey, can you add some documentation for this? I want to use this for a OS I'm building bioscreeper 1 Quote Link to post Share on other sites
willowyknight76 0 Posted December 21, 2021 Share Posted December 21, 2021 this isn't working Quote Link to post Share on other sites
bioscreeper 0 Posted February 16, 2023 Share Posted February 16, 2023 Dustpuppy I can't delete characters in the text boxes within the options frame in your gui maker. It simply prints the delete control character Quote Link to post Share on other sites
cadergator10 1 Posted February 21, 2023 Share Posted February 21, 2023 On 2/16/2023 at 1:41 AM, bioscreeper said: Dustpuppy I can't delete characters in the text boxes within the options frame in your gui maker. It simply prints the delete control character Little late, but I doubt you'll get much help out of this. They have been offline for a very, very long time and haven't responded to any previous posts. If you need a GUI I would recommend the one here https://github.com/IgorTimofeev/GUI This is the legacy version of the one currently in MineOS and I believe it should work better (and look nicer and work better) than this one, although I don't have any experience with this one. Plus, the developer is active on their github. Hope this helps Edit: Now looking at it I'm unsure if you need the visual editor or if you are programming it manually. This GUI doesn't have any visual editor, but the documentation is thorough Edit 2: Scrolling up I also found that this is Dustpuppy's legacy GUI and the latest version is here This developer isn't online either way, so if you run into a problem again I don't really know how to fix it Quote Link to post Share on other sites
foxp552 0 Posted February 24, 2023 Share Posted February 24, 2023 yeup that's what we need (none programmer's) Quote Link to post Share on other sites