Easy GUI System



EGS uses the LGPL license 3.0. Basically give me credit - Any fixes you make to my code; give me them too. You don't need to give me your code; though. I think it goes somewhat like that. [License details and stuff].

The license above does NOT APPLY TO the 'Tetris.mp3' sound included, not the debug.lua file included. Neither of those were made by me (See #Included)

Easy GUI System is an easy-to-use GUI system made by User:Trappingnoobs.

WARNING
Lots of the examples are not functional with the current release. A new release is coming within a few days.

General tutorial

Included

  • Ships with debug.lua by Kalle2990 from love2D forum.
  • Ships with class.lua by Trappingnoobs from love2D forum.
  • Ships with 'Tetris with DONK' by Jordan Snelling (Jordach) from newgrounds.

If any owner of an above file/product does not wish EGS to contain their products anymore; you can contact me via email (Ash2424@live.co.uk), or via the Love2D forum (Send a private message to 'Trappingnoobs' or post on the EGS thread.)

Class.lua by Trappingnoobs

My class system is incredibly simple to use. The following few tutorials will just teach you the basics.

Defining a class

Class "ClassName" {Properties}

There we have a basic class called 'ClassName'. It has ONE property, called "Properties", with a default value of an empty string (We didn't give it a default value).


Defining a class with multiple properties

Class "ClassName" {
	Property1,
	Property2,
}

Yet another very basic class. It literally just creates a class with two properties. If it wasn't obvious from #Defining a class, you pass in a table.


Defining a class with multiple properties with default values

Class "ClassName" {
	["Property1"] = 7,
	Property2,
}

To give a property a default value, just make it a key instead of a value, such as above, and give it a value of the default value.

Default values can be functions, tables, anything!


Instanciating a class

You only ever run new on a class. Do not type "ClassName.Property1 = ." because it WILL error. Only change instance's properties if that makes sense..
Class "ClassName" {
	["Property1"] = 7,
	Property2,
}

ClassName:new("InstanceName")
print(InstanceName.Property1)

>7

As you can see, and probably already noticed, we're passing in the names, rather than getting a return value, such as the above instead of

ClassName = Class {
	["Property1"] = 7,
	Property2,
}
InstanceName = ClassName:new()

The class function makes use of the 'getfenv()' function. This allows it to define variables in the calling environment. Classes are not local variables, they are global. So are instances.


Creating multiple intances of a class

Class "ClassName" {
	["Property1"] = 7,
	Property2,
}

ClassName:new("InstanceName")
InstanceName.Property2 = "Ohai world"
print("InstanceName1 says: "..InstanceName.Property2)
ClassName:new("InstanceName2")
print("InstanceName2 says: "..InstanceName2.Property2)

>InstanceName1 says: Ohai world
>InstanceName2 says:

Like I said earlier; if no default is set, a class property will get a default value of an empty string, not nil, so it doesn't error when you try to concatenate it.

Inheriting properties

Class "ClassName" {
	["eggs"] = true,
}

Class "ClassName2" ({
	["Property1"] = 7,
	Property2,
}, {ClassName})

ClassName2:new("InstanceName")
print(tostring(InstanceName.eggs))
>true

To inherit, instead of typing

Class "cName" {Properties}

We type

Class "cName" ({Properties}, {Which classes to inherit from})

As it's a table you can inherit from multiple classes.

If you have the same property in both classes, for example

Class "cName" {["Prop1"] = "LOLHAX5000"}
Class "cName2" ({["Prop1"] = "LOLHAX6000"}, {cName})

Like that, it inherits from an object with a property the same, the second class (cName2)'s Prop1 will become it's default, as it overrides the inherited value.

So if I instanced "cName", and printed it's Prop1, it'd print LOLHAX5000, but doing the same to cName2 would print LOLHAX6000. This allows you to make classes that inherit the majority of things from another, but change or completely destroy (just set it to nil) some, you can.


End of class tutorial

I hoped your understood; but if not, you don't need to understand it all. Only that you should know how to instance classes (ClassName:new("InstanceName).


Using my GUI library

By now you should be familiar with my class system.

My GUI library classes are organised into two sections: Structural and Non-Structural classes.

Events

Events are identical to those found on [Roblox].

Object.Event:connect(function)

For example:

CheckBox:new("Checkbox1")
Checkbox1.checkStateChanged:connect(function()
	print("Checkbox1's state was changed by the :changeState() function. It fires on mouse click automatically but can be fired manually.")
end)

What are Structural Classes?

In my GUI library, structural classes are classes that the only purpouse is for other classes to inherit from. Instancing them is a VERY bad idea.

For this reason, I didn't bother to document some of the structural classes.

What are Non-Structural Classes?

Non-Structural classes are things like Checkboxes. You can instance them, and they are mainly GUI items.

Terminology

Word Meaning
Structural Class #What are Structural Classes?
Non-Structural Class #What are Non-Structural Classes?
Superclasses Classes that a class inherits from (CheckBox's SuperClass is GUIElement.)
Derived Classes Classes that inherit from a class. (CheckBox is a derived class of GUIElement)
Dropped Properties/Events Properties/Events that usualy would've been inherited but were nilled in the class (Eg TextLabel drops mouseClicked, mousePressed, mouseReleased)

Examples

Rather than document every individual property; I'm going to give examples on how to do certain tasks!

Buttons

Making a TextLabel appear when a Button is hovered

Note that since TextLabel only drops the events 'mouseClicked', 'mousePressed', and 'mouseReleased', but not 'mouseEntered' and 'mouseExited', it's possible to do this with two TextLabels with identical results. However TextLabels were not made to be functional so it's not recommended.

First we need a TextLabel and a TextButton. Put these lines in love.load:

TextButton:new("HoverButton")
TextLabel:new("Display")

Now that we've got them we can define some variables. Also put these lines below the ones you just did in love.load:

HoverButton.text = "Hover me to see the TextLabel."
HoverButton.autoSize = false
HoverButton.size = {100,20}
HoverButton:centerText()--Aligns text to center on Y and X axis.
HoverButton.hasBorder = false
Display.text = ":o"
Display.visible = false
Display.size = {100,20}
Display:centerText()
Display.position = {0,20}
Display.hasBorder = false

Now we need #Events. These are also in love.load.

HoverButton.mouseEntered:connect(function()
	Display.visible = true
end)
HoverButton.mouseExited:connect(function()
	Display.visible = false
end)

Now if we run that, it's a functional example! :o

Most of that is realy straightforward, right?!

That's because EGS was made to be easy, and it is, but maintains a good range of customisability. For example, notice the shading when you hover on the button? See how it gets darker when we hold the mouse down? We can turn that off by just adding:

HoverButton.hasShading = false

Making a button respond to hovering

In this tutorial we'll make a button respond to hovering. The purpouse is to explore more properties of GUI elements. For example, all three color properties (textColor, borderColor, backgroundColor) are just a table with three values in, {R, G, B}, for example, {255, 0, 0} represents pure red.

I recommend you set the window backgroundColor to white for this tutorial! (love.graphic.setBackgroundColor(255,255,255))

First we make the button and initialise some values:

TextButton:new("TB")
TB.text = "Hover me!"
TB.autoSize = false
TB.size = {100,20}
TB.position = {10,10}
TB.backgroundColor = {0,200,255} --That's ROUGHLY skyblue.
TB:centerText()--Aligns text to center on Y and X axis.

Try that. Not so great; so far it just does the defaults; some shading. Let's mix it up a little.

TB.hasShading = false --Get rid of shading.
TB.borderWidth = 1 --Make the border thinner.
TB.mouseEntered:connect(function()
	TB.borderWidth = 2
end)
TB.mouseExited:connect(function()
	TB.borderWidth = 1
end)

Now THAT is cooler. It looks realy nice with the thinner border! We'll now try changing the color a little- not too much, just a tad. Replace those two events you did with this:

TB.mouseEntered:connect(function()
	TB.borderWidth = 2
	TB.backgroundColor = {0,150,255} --Less green!
end)
TB.mouseExited:connect(function()
	TB.borderWidth = 1
	TB.backgroundColor = {0,200,255} --Back to skyblue.
end)

Getting better, but still not perfect. How about making the borderColor and textColors change too?


TB.mouseEntered:connect(function()
	TB.borderWidth = 2
	TB.backgroundColor = {0,150,255} --Less green!
	TB.textColor = {50,100,50}
	TB.borderColor = TB.textColor
end)
TB.mouseExited:connect(function()
	TB.borderWidth = 1
	TB.backgroundColor = {0,200,255} --Back to skyblue.
	TB.textColor = {0,0,0}
	TB.borderColor = TB.textColor
end)

That's the end of the tutorial, but you might not like the above effect- It's realy in-your-face and end-users might find it annoying, try this:


TB.mouseEntered:connect(function()
	TB.backgroundColor = {0,150,255} --Less green!
end)
TB.mouseExited:connect(function()
	TB.backgroundColor = {0,200,255} --Back to skyblue.
end)


Making a TextLabel with a message when you hover

Now, to do this, you may wonder how this is relevant to teaching you about my GUI features, because this is mainly just math to make it follow the mouse, count the frames, but NO! There's no need to do ANY of this! :D

It's REALY simple to do this task, and ALL GUIElements have this feature, called Caption. Watch:

TextLabel:new("TL")
TL.text = "Hover me!"
TL.autoSize = false
TL.size = {100,20}
TL.position = {10,10}
TL.backgroundColor = {0,200,255}
TL:centerText()
TL.hasShading = false 
TL.borderWidth = 1

We're going to stick with the nice style we made in the last tutorial. But we need a few more variables for a caption. Add this:

TL.hasCaption = true
TL.caption = "This is a caption!"

Execute it, and huzzah!

If you want the caption to come up quicker or slower, there's a neat function for that, add this just below TL.caption = "This is a caption!":

TL:setSecondsForCaption(3) 
--Will wait 3 seconds of mouse hovering to display caption.