Difference between revisions of "Easy GUI System"

(Rewrite to be more concise and mature. Additionally, add note that I'm considering maintaining this again.)
 
(One intermediate revision by one other user not shown)
Line 1: Line 1:
{{#set:Name=Easy GUI System (EGS)}}
+
Easy GUI System is an easy-to-use GUI system made by [https://github.com/ashleydavies Ashley Davies]. It is available on its [https://github.com/ashleydavies/EGS/ Github page]. EGS is not currently maintained, but functions on the current versions of LÖVE, thanks to contributions by buckle2000 on GitHub. Ashley is considering maintaining, tidying, and expanding on this library. If you would like for this to happen, please see further detail on the GitHub page for the repository.
{{#set:LOVE Version=0.7.2}}
 
{{#set:Description=EGS is a simple GUI system with events and multiple controls, without overcomplicating things too much.}}
 
{{#set:Keyword=GUI}}
 
  
Disclaimer: This library was written 4 years ago, so may not be functional with newer versions of Love2D. Additionally, some of the code may not be beautifully written.
 
 
It's, as the name says, still pretty easy to use but if you can find an alternative I'd recommend you go with that.
 
 
 
Easy GUI System is an easy-to-use GUI system made by [[User:Trappingnoobs]].
 
 
<div style="border:2px solid green;width:100%;text-align:center;background-color:skyblue">Download link:<br/>[[https://github.com/ashleydavies/EGS/]]</div>
 
  
 
__TOC__
 
__TOC__
Line 17: Line 6:
 
= General tutorial =
 
= General tutorial =
  
== Class.lua by Trappingnoobs ==
+
== Class.lua ==
  
My class system is incredibly simple to use. The following few tutorials will just teach you the basics.
+
My class system is simple to use. The following few tutorials will teach you the basics.
  
 
=== Defining a class ===
 
=== Defining a class ===
Line 26: Line 15:
 
Class "ClassName" {Properties}
 
Class "ClassName" {Properties}
 
</source>
 
</source>
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).
+
Here we have a basic class called 'ClassName'. It has a property called "Properties", with a default value of an empty string (We didn't give it a default value).
  
  
Line 37: Line 26:
 
}
 
}
 
</source>
 
</source>
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.
+
Here's another basic class. It just creates a class with two properties.
 
 
  
 
=== Defining a class with multiple properties with default values ===
 
=== Defining a class with multiple properties with default values ===
Line 48: Line 36:
 
}
 
}
 
</source>
 
</source>
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.
+
To give a property a default value, make it a key instead of a value, as above, and give it a value of the default value. Default values can be any type.
 
 
Default values can be functions, tables, anything!
 
 
 
  
=== Instanciating a class ===
 
  
<pre>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..</pre>
+
=== Instantiating a class ===
  
 
<source lang="lua">
 
<source lang="lua">
Line 64: Line 48:
  
 
ClassName:new("InstanceName")
 
ClassName:new("InstanceName")
 +
 
print(InstanceName.Property1)
 
print(InstanceName.Property1)
 
 
>7
 
>7
 
</source>
 
</source>
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
+
 
 +
As you can see, we pass in the names, rather than getting a return value, so we do the above, as opposed to:
  
 
<source lang="lua">
 
<source lang="lua">
Line 77: Line 62:
 
InstanceName = ClassName:new()
 
InstanceName = ClassName:new()
 
</source>
 
</source>
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.
+
 
 +
The class function makes use of the `getfenv()` function, which allows it to define variables in the calling environment. Classes are not local variables, they are global. So are instances.
  
  
Line 89: Line 75:
  
 
ClassName:new("InstanceName")
 
ClassName:new("InstanceName")
InstanceName.Property2 = "Ohai world"
+
InstanceName.Property2 = "Hello world"
print("InstanceName1 says: "..InstanceName.Property2)
+
print("InstanceName1 says: " .. InstanceName.Property2)
 
ClassName:new("InstanceName2")
 
ClassName:new("InstanceName2")
print("InstanceName2 says: "..InstanceName2.Property2)
+
print("InstanceName2 says: " .. InstanceName2.Property2)
  
>InstanceName1 says: Ohai world
+
>InstanceName1 says: Hello world
 
>InstanceName2 says:  
 
>InstanceName2 says:  
 
</source>
 
</source>
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.
+
 
 +
If no default is set, a class property will get a default value of an empty string, instead of nil, so it won't error if you try to concatenate it.
  
 
=== Inheriting properties ===
 
=== Inheriting properties ===
Line 103: Line 90:
 
<source lang="lua">
 
<source lang="lua">
 
Class "ClassName" {
 
Class "ClassName" {
["eggs"] = true,
+
["val"] = true,
 
}
 
}
  
Line 112: Line 99:
  
 
ClassName2:new("InstanceName")
 
ClassName2:new("InstanceName")
print(tostring(InstanceName.eggs))
+
print(tostring(InstanceName.val))
 
>true
 
>true
 
</source>
 
</source>
Line 132: Line 119:
  
 
<source lang="lua">
 
<source lang="lua">
Class "cName" {["Prop1"] = "LOLHAX5000"}
+
Class "cName" {["Prop1"] = "val1"}
Class "cName2" ({["Prop1"] = "LOLHAX6000"}, {cName})
+
Class "cName2" ({["Prop1"] = "val2"}, {cName})
 
</source>
 
</source>
  
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.
+
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.
+
So if I instanced "cName", and printed it's Prop1, it'd print val1, but doing the same to cName2 would print val2. This mean you can 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 ===
+
=== End note ===
 
 
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).
 
  
 +
You can get by without understanding this object system, so long as you understand the examples below.
  
 
== Using my GUI library ==
 
== Using my GUI library ==
  
By now you should be familiar with [[#Class.lua by Trappingnoobs|my class system.]]
+
By now you should be familiar with the class system.
  
 
My GUI library classes are organised into two sections: Structural and Non-Structural classes.
 
My GUI library classes are organised into two sections: Structural and Non-Structural classes.
Line 154: Line 140:
 
=== Events ===
 
=== Events ===
  
Events are identical to those found on [[http://roblox.com Roblox]].  
+
Events behave identically to those found on [[http://roblox.com Roblox]].  
 
<source lang="lua">
 
<source lang="lua">
 
Object.Event:connect(function)
 
Object.Event:connect(function)
Line 170: Line 156:
 
=== What are Structural Classes? ===
 
=== 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.
+
In this library, structural classes are classes whose only purpose is for other classes to inherit from. They are not all entirely documented as they should not be instanced.
 
 
For this reason, I didn't bother to document some of the structural classes.
 
  
 
=== What are Non-Structural Classes? ===
 
=== What are Non-Structural Classes? ===
  
 
Non-Structural classes are things like [[#Checkbox|Checkboxes.]] You can instance them, and they are mainly GUI items.
 
Non-Structural classes are things like [[#Checkbox|Checkboxes.]] You can instance them, and they are mainly GUI items.
 
=== Terminology ===
 
 
{|class="wikitable"
 
!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 =
 
= Examples =
 
Rather than document every individual property; I'm going to give examples on how to do certain tasks!
 
  
 
== Buttons ==
 
== Buttons ==
Line 208: Line 168:
 
=== Making a TextLabel appear when a Button is hovered ===
 
=== 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.
+
Note that since TextLabel only loses 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:
 
First we need a TextLabel and a TextButton. Put these lines in love.load:
Line 244: Line 204:
 
</source>
 
</source>
  
Now if we run that, it's a functional example! :o
+
Now if we run that, it's a functional example!
  
Most of that is realy straightforward, right?!
+
It is straightforward, as EGS was made to be easy, and achieves this while maintaining a good range of customisability. For example, the shading when you hover on the button can be turned off by just adding:
 
 
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:
 
  
 
<source lang="lua">
 
<source lang="lua">
Line 256: Line 214:
 
=== Making a button respond to hovering ===
 
=== 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.
+
In this tutorial we'll make a button respond to hovering. The purpose 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))
 
I recommend you set the window backgroundColor to white for this tutorial! (love.graphic.setBackgroundColor(255,255,255))
Line 268: Line 226:
 
TB.size = {100,20}
 
TB.size = {100,20}
 
TB.position = {10,10}
 
TB.position = {10,10}
TB.backgroundColor = {0,200,255} --That's ROUGHLY skyblue.
+
TB.backgroundColor = {0,200,255}
TB:centerText()--Aligns text to center on Y and X axis.
+
--Aligns text to center on Y and X axis.
 +
TB:centerText()
 
</source>
 
</source>
  
Try that. Not so great; so far it just does the defaults; some shading. Let's mix it up a little.
+
Let's mix it up a little.
  
 
<source lang="lua">
 
<source lang="lua">
Line 285: Line 244:
 
</source>
 
</source>
  
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:
+
It looks much nicer with the thinner border! We'll now try changing the color a little. Replace those two events you did with this:
  
 
<source lang="lua">
 
<source lang="lua">
Line 315: Line 274:
 
end)
 
end)
 
</source>
 
</source>
 
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:
 
 
 
<source lang="lua">
 
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)
 
</source>
 
 
  
 
=== Making a TextLabel with a message when you hover ===
 
=== 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 simple to achieve this, as ALL GUIElements have this feature, called ''Caption''.
 
 
It's REALY simple to do this task, and ALL GUIElements have this feature, called ''Caption''. Watch:
 
  
 
<source lang="lua">
 
<source lang="lua">
Line 359: Line 303:
  
 
<source lang="lua">
 
<source lang="lua">
TL:setSecondsForCaption(3)
 
 
--Will wait 3 seconds of mouse hovering to display caption.
 
--Will wait 3 seconds of mouse hovering to display caption.
 +
TL:setSecondsForCaption(3)
 
</source>
 
</source>
  
 
[[Category: Libraries]]
 
[[Category: Libraries]]
 +
{{#set:Name=Easy GUI System (EGS)}}
 +
{{#set:LOVE Version=0.10.x}}
 +
{{#set:Description=EGS is a simple GUI system with events and multiple controls, without over-complicating things.}}
 +
{{#set:Keyword=GUI}}

Latest revision as of 18:19, 17 August 2016

Easy GUI System is an easy-to-use GUI system made by Ashley Davies. It is available on its Github page. EGS is not currently maintained, but functions on the current versions of LÖVE, thanks to contributions by buckle2000 on GitHub. Ashley is considering maintaining, tidying, and expanding on this library. If you would like for this to happen, please see further detail on the GitHub page for the repository.


General tutorial

Class.lua

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

Defining a class

Class "ClassName" {Properties}

Here we have a basic class called 'ClassName'. It has a 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,
}

Here's another basic class. It just creates a class with two properties.

Defining a class with multiple properties with default values

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

To give a property a default value, make it a key instead of a value, as above, and give it a value of the default value. Default values can be any type.


Instantiating a class

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

ClassName:new("InstanceName")

print(InstanceName.Property1)
>7

As you can see, we pass in the names, rather than getting a return value, so we do the above, as opposed to:

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

The class function makes use of the `getfenv()` function, which 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 = "Hello world"
print("InstanceName1 says: " .. InstanceName.Property2)
ClassName:new("InstanceName2")
print("InstanceName2 says: " .. InstanceName2.Property2)

>InstanceName1 says: Hello world
>InstanceName2 says:

If no default is set, a class property will get a default value of an empty string, instead of nil, so it won't error if you try to concatenate it.

Inheriting properties

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

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

ClassName2:new("InstanceName")
print(tostring(InstanceName.val))
>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"] = "val1"}
Class "cName2" ({["Prop1"] = "val2"}, {cName})

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 val1, but doing the same to cName2 would print val2. This mean you can make classes that inherit the majority of things from another, but change or completely destroy (just set it to nil) some, you can.


End note

You can get by without understanding this object system, so long as you understand the examples below.

Using my GUI library

By now you should be familiar with the class system.

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

Events

Events behave identically 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 this library, structural classes are classes whose only purpose is for other classes to inherit from. They are not all entirely documented as they should not be instanced.

What are Non-Structural Classes?

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

Examples

Buttons

Making a TextLabel appear when a Button is hovered

Note that since TextLabel only loses 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!

It is straightforward, as EGS was made to be easy, and achieves this while maintaining a good range of customisability. For example, the shading when you hover on the button can be turned 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 purpose 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}
--Aligns text to center on Y and X axis.
TB:centerText()

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)

It looks much nicer with the thinner border! We'll now try changing the color a little. 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)

Making a TextLabel with a message when you hover

It's simple to achieve this, as ALL GUIElements have this feature, called Caption.

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!":

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