Manual:Geyser

From Mudlet
Jump to navigation Jump to search

The Geyser Layout Manager

Introduction

Geyser is an object oriented framework for creating, updating and organizing GUI elements within Mudlet - it allows you to make your UI easier on Mudlet, and makes it easier for the UI to be compatible with different screen sizes.

Motivation

Mudlet makes the creation of label, miniconsoles and gauges a quick and easy thing. Mudlet provides a nice signal when window resize events happen. Mudlet does not provide a good framework for complex window management, which Geyser attempts to address.

Main Geyser Features

Geyser is based on traditional GUI concepts and should feel similar to using Java's Swing. The biggest difference is in how positions are specified.

  • All window positions are specified relative to their container - nothing new there. However, window positions can also take on percentages and negative pixel and character values. For instance, a window could be constrained to have a height of 50% of its container and a width such that the window's right edge is always 20 characters from its container's right edge. See examples below and the demos/tests that come with Geyser.
  • All windows under Geyser control are automatically resized as necessary when the main Mudlet window is resized. Once you create a window and assign it to a container, you never have to worry about positioning it again. Nonetheless, it's very easy to shift the container that a window is in, maintaining its constraints so that it resizes as needed according to the dimensions of the new container.
  • Due to the container hierarchy, hiding a container window automatically hides all its contained windows too. The same for show. With clever construction and labels with callbacks, this lets one make complex GUI elements that are minimizable or maximizable or ...
  • However, there is always some overhead for automation systems and Geyser is no exception. Fortunately, most of the overhead is during window creation and resize events - not things that happen frequently.

Constraints format

Geyser position constraints are a string composed of a number and a format type. For example, "10px" means 10 pixels, either pixels from the origin (e.g. x or y) or a value for the width or height. A negative number indicates distance from a container's right or bottom border depending on whether is a constraint for x/width or y/height, respectively. Percentages for width and height are in terms of the container's dimensions and negative values are converted to the equivalent positive value. A 100% width subwindow with an x-coordinate of 10 will have part of itself displayed outside the confines of its container. There is no hard limit on maximum window size, just as with regular Mudlet windows. If a number, n, is passed as a constraint instead of a string, it is assumed to be equivalent to "npx". Any Lua table that contains entries for x, y, width and height in the proper format can be used for Geyser constructors and setting constraints. Just like in Mudlet, 0,0 coordinates mean the top-left corner.

The following is a valid example for coordinates of a Geyser object:

<lua> {x = "20px", y = "-10c", width = "40%", height = 30} </lua>

Geyser elements

The purpose of this document is to go through every Geyser element and provide practical examples on how they are used. Read it from top to bottom, preferably doing all of the examples to understand how they work!

Geyser.Container

An invisible, organizing object in Geyser - use it to divide your screen and position elements accordingly. See here for all of the functions that are available to you to use.

A container is also the base class - which means that everything (labels, miniconsoles and gauges) can use its functions, since everything else is at heart a container.

Creating a container

To get started with a container, here's an example that'll create a 200px border on the left side of Mudlet for you, and make a container cover all of it - so you can place other visual elements inside it:

<lua> setBorderLeft(200) left_container = Geyser.Container:new({

 name = "left_container",    -- give it a unique name here
 x=0, y=0,                   -- have it start at the top-left corner of mudlet
 width = 200, height="100%", -- with a width of 200, and a height of the full screen, hence 100%

}) </lua>

Right away, you'll see space appear on the left side. It'll be black, as the container is an invisible unit by itself. You can make sure it's there by making it flash - having obtained the Run Lua code alias, doing: lua left_container:flash() will cause it to flash for a moment for you, revealing itself.

Container within a container

You can place containers within other containers by specifying which "parent" the new container should have when you create one. Given our previous example, you can split the left side into two halves like this:

<lua> left_container_top = Geyser.Container:new({

 name = "left_container_top",
 x=0, y=0,                     -- this container occupies the top, so it starts top-left as well
 width = "100%", height="50%", -- but only uses up half of the height

}, left_container) -- this is the important bit - it says that left_container_top should be inside left_container

left_container_bottom = Geyser.Container:new({

 name = "left_container_bottom",
 x=0, y="50%",                 -- this container starts halfway down the first one
 width = "100%", height="50%", -- and has the same half height of the original container

}, left_container) </lua>

Aligning relative to bottom or right sides

The aligning point within Mudlet is the top-left corner, and it's the same for the elements they are aligned - the position you specify is used by the top-left corner of the element.

Using Geyser, you can align to the opposite side as well, using the coordinates in negatives, while keeping the dimensions of the object in mind. For example, if you want to align a box that's 20px wide on the usual left side, you'd give it a width of 20 and an x value of 0. If you'd like to align it on the right side, then you'd give it an x value of -20. The box will spawn 20px away from the right side and "grow" to the right by 20px.

<lua> right_container = Geyser.Container:new({

 name = "right_container",
 x="-20%", y=0,                    -- makes the container start 20% of the screen away from the right side
 width = "20%", height="50%",      -- filling it up until the end

}) </lua>

Do make sure to account for the scrollbar, as Mudlet UI elements can overlap it. You can also move the scrollbar with setBorderRight().

Geyser.Label

Based on the Mudlet label, this allows you to use the labels functionality within Geyser. Labels allow you to use pictures in your interface, as well as nicely-formatted text.

Basic label

Here's an example to get you started with:

<lua> testlabel = Geyser.Label:new({

 name = "testlabel",
 x = "50%", y = 0,
 width = "50%", height = "100%",
 fgColor = "black",
 color = "SeaGreen",

message = [[

heey

]]

}) </lua>

This labels x coordinate is specified as 50% - and because it's not attached to any container, this implies that the window will start halfway at the main window. You can tell it's not attached to a container because there's nothing in between the last } and ), the place where the container goes.

The y coordinate is 0 - which means that the label will start at the top of the screen. With the width being 50%, the label will occupy 50% of the screen - and since it starts at the halfway point, it means it'll occupy the entire right side. A height of 100% means that it'll stretch from the top to the full bottom.

Here's what that'll look like:

Simple-label.png


Playing around with the starting location and dimensions, we can also place it in the center of the screen with:

<lua> testlabel = Geyser.Label:new({

 name = "testlabel",
 x = "25%", y = "25%",
 width = "50%", height = "50%",
 fgColor = "black",

message = [[

heey

]]

}) testlabel:setColor(0,255,0,150) </lua>

Simple label centered.png

To change the message on a label, you can use the mylabel:echo() function, where mylabel is the name of the label you gave it:

<lua> testlabel:echo("hello!") </lua>

Label inside a container

Once you've got your containers and mastered the basic labels, you can drop labels into your nicely-organized containers. Doing so is similar to nesting containers:

<lua> testlabel = Geyser.Label:new({

 name = "testlabel",
 x = "25%", y = "25%",
 width = "50%", height = "50%",
 fgColor = "black",

message = [[

heey

]]

}, left_container_bottom) -- this is where we tell it what container to go into testlabel:setColor(0,255,0,150) </lua>

That label is exactly the same as the one above that goes across the screen, except it's in our bottom-left container - so it looks appropriately different:

Label in a container.png

Image on a label

One of the more amazing things labels allow you to do is put pictures anywhere on your Mudlet screen, that blend in very well. To do so, once the label is created, use the setBackgroundImage() function with the exact path to the image (Skullface.png):

<lua> picture_label = Geyser.Label:new({

 name = "picture_label",
 x = 0, y = "-14px",
 width = "16px", height = "14px",

}) picture_label:setBackgroundImage(/home/vadi/Desktop/skullface.png) -- update location to actual image location on your computer </lua>

This'll plop the picture to the bottom-left of your screen. To make the picture show, download the skullface picture above - save it to your desktop, and adjust the location of the image within [[]]'s to what it is on your computer. For example, if you saved this on your Windows 7 desktop, it would be:

<lua> picture_label:setBackgroundImage([[C:/Users/<your user name>/Desktop/skullface.png]]) </lua>

(yes, that's / and not \ - \ has been known not to work)

If you saved this on your Mac desktop, it would be:

<lua> picture_label:setBackgroundImage([[/Users/<your user name>/Desktop/skullface.png]]) </lua>

If you saved this on your Ubuntu desktop, it would be:

<lua> picture_label:setBackgroundImage([[/home/<your user name>/Desktop/skullface.png]]) </lua>

Using this basic building block, you can work up to making yourself a UI!

Stretching an image on a label

If you'd like your image not to keep it's original size, but instead use up the available space of the label - you can use the border-image stylesheet property to do so.

<lua> label = Geyser.Label:new({

 name = "label",
 x = "50%", y = "50%",
 width = "50%", height = "50%",

})

-- change the location to your picture -- on windows, use / to separate folders still, not \ label:setStyleSheet[[

 border-image: url(/home/vadi/Desktop/iso-avatar-draft_0.png);

]] </lua>

Aligning an image within a label

You can use background-image in combination with background-position to align an image within a label (if, say, the image is much smaller than the label).

<lua> -- this will set and align an image top-right of the label if stunning then

 mylabel:setStyleSheet([[
   background-image: url("/home/vadi/Games/Mudlet/Offensive/Artwork/dialog-ok.png");
   background-repeat: no-repeat; background-position: top right; background-origin: margin;
 ]])

else

 mylabel:setStyleSheet([[
   background-image: url("/home/vadi/Games/Mudlet/Offensive/Artwork/dialog-no.png");
   background-repeat: no-repeat; background-position: top right; background-origin: margin;
 ]])

end </lua>

Showing / hiding a label

You can show and hide labels, as you can any container, miniconsole or a gauge in Geyser with Geyser.Container:show() and Geyser.Container:hide(). Remember that since labels are a type of a container, all container functions work on them.

Hiding a label will allow you to click through on what is below the label, as well as free up the visual space for something else.

<lua> testlabel = Geyser.Label:new({

 name = "testlabel",
 x = "50%", y = 0,
 width = "50%", height = "100%",
 fgColor = "black",
 color = "SeaGreen",

message = [[

heey

]]

})

-- hide the label with: testlabel:hide()

-- show the label with: testlabel:show() </lua>

Clickable images

Tacking onto the fact that you can plop images anywhere on your Mudlet screen now, you can also make them react to your clicks. You can do so with the setClickCallback() function - by giving it a function to call when your label is clicked, you'll make it react.

<lua> picture_label = Geyser.Label:new({

 name = "picture_label",
 x = "-215px", y = "0px",
 width = "200px", height = "200px",

}) picture_label:setBackgroundImage(/home/vadi/Desktop/qubodup-opengameart-cc0-200px-missile_icon.png) -- update location to actual image location on your computer picture_label:setClickCallback("on_bomb_press")

function on_bomb_press()

 send("say BOOM!")

end </lua>

That's it! Pressing on the image will make the on_bomb_press() function go off, which will do its code of send("say BOOM!"). Download the picture for use here.

Clickable image.png

Note Note: At the moment, callback functions cannot be inside a table - they have to be available at the global level. This means they can't have a dot in their name.

Styling labels

Besides putting text or images on labels, you can also style them using Qt's stylesheets feature. Doing so allows you to create various graphics that make the label look more appealing:

Label styling examples.png

To set a stylesheet on a label, use the Geyser.Label:setStyleSheet() function on your label, describing the stylesheet you'd like to give it. A stylesheet consists of properties you set - for example the background color, borders, padding, and so forth. You describe properties in the following format: property name:values;. See here for a of all supported properties. For example, to make your labels background be yellow, you'd use the background-color property:

<lua> mylabel = Geyser.Label:new({

 x = "50%", y = "50%",
 width = 200, height = 100

})

mylabel:setStyleSheet([[

 background-color: yellow;

]]) </lua>

Basic stylesheet.png

Which is nice, but not particularly impressive.

Scrolling down the list of properties, you'll come along a border one. Plopping it into our stylesheet nets the following:

<lua> mylabel:setStyleSheet([[

 background-color: yellow;
 border: 5px solid white;

]]) </lua>

Basic stylesheet border.png

Which gives a border!

Fiddling with it some more and applying new properties we find on that page, we get a rounded border on our label:

<lua> mylabel:setStyleSheet([[

 background-color: grey;
 border-width: 15px;
 border-style: solid;
 border-color: green;
 border-radius: 10px;

]]) </lua>

Basic stylesheet border radius.png

Which'll conclude our exploration for now. Try out all of the other possible options available there - there's loads, from funky borders, to tiling images and fancy color combinations using gradients.

Aligning text/images inside a label

By default, text is centered vertically and left aligned in a label. To align it to a specific side, use the stylesheets we learnt about earlier with the qproperty-alignment:

<lua> mylabel = Geyser.Label:new({

 name = "testlabel",
 x = "50%", y = 0,
 width = "50%", height = "100%",
 fgColor = "black",
 color = "SeaGreen",

message = [[

heey

]]

})

-- specify one property this way: mylabel:setStyleSheet(qproperty-alignment: 'AlignTop';)

-- or multiple ones separated with a |, for example this will align text to top-left: -- specify one property this way: mylabel:setStyleSheet([[

 qproperty-alignment: 'AlignLeft | AlignTop';

]])

mylabel:echo("hi!") </lua>

Text aligned.png

Enabling wordwrap in a label

If you need to enable word wrapping in a label (which by default is off), add the following line to the labels stylesheet:

 qproperty-wordWrap: true;

As an example:

<lua> mylabel:setStyleSheet([[

 qproperty-wordWrap: true;

]]) </lua>

If you'd like to set multiple properties, set them all at once - not via multiple :setStyleSheet() calls:

<lua> mylabel:setStyleSheet([[

 background: red;

]]) </lua>

Adding a hover effect to a label

The labels support adding stylesheets for specific cases, such as when a mouse is hovering over them. To make this work, you provide CSS for when the label is in its usual state, and for when it is hovered over:

<lua> -- this example will add a border to the label when it is hovered over mylabell:setStyleSheet([[

 QLabel{ border-radius: 4px; }
 QLabel::hover{
   background-color: rgba(0,0,0,0%);
   border: 4px double green;
   border-radius: 4px;
 }

]]) </lua>

Checkboxes

Combining the fact that you can click on a label with an image to do something with the fact that you can change pictures on a label at will, you can make an image that changes itself when you click on it.

<lua> picture_label = Geyser.Label:new({

 name = "picture_label",
 x = "50%", y = "50%",
 width = "21px", height = "19px"

}) -- a little trick we do to make the background of the label be transparent picture_label:setStyleSheet([[

 background-color: rgba(0,0,0,0%);

]])

picture_label:setBackgroundImage(/home/vadi/Desktop/checkbox_ticked.png) picture_label:setClickCallback("on_checkbox_press")

function on_checkbox_press()

 if checkbox_ticked then
   checkbox_ticked = false
   picture_label:setBackgroundImage(/home/vadi/Desktop/checkbox_unticked.png)
   echo("Checkbox unticked.\n")
 else
   checkbox_ticked = true
   picture_label:setBackgroundImage(/home/vadi/Desktop/checkbox_ticked.png)
   echo("Checkbox TICKED!\n")
 end

end </lua>

The on_checkbox_press() function this time keeps the track of the checkbox with the checkbox_ticked variable and sets the image appropriately. You can download the ticked (Checkbox ticked.png) and unticked images (Checkbox unticked.png) or the whole package altogether.

Checkbox demo.png

Animated labels

Using timers and several pictures, you can make your labels change quickly enough and look animated. Here's one such example:

<lua> picture_label = Geyser.Label:new({

 name = "picture_label",
 x = 10, y = "-24px",
 width = "16px", height = "14px",

})

santa_counter = nil

function animate_santa()

 santa_counter = (santa_counter or 0) + 1
 if santa_counter > 8 then santa_counter = 1 end
 picture_label:setBackgroundImage(/home/vadi/Desktop/santa/santa..santa_counter...png) -- update location to actual image location on your computer
 santa_timer = tempTimer(.16, animate_santa)

end

animate_santa() </lua>

The completed package is available here, install it and do start/end animation to watch.

Inserting extra spaces and newlines

Echoing text into Mudlet and Geyser labels is different from miniconsoles and the main window, due to their nature. One of the differences is that extra spaces in a label, by default, get compressed down to one. To add extra spaces in a label, replace extra spaces with &nbsp; or by wrapping your text with them inside <pre>my text here</pre>.

<lua> -- this won't work, it'll show as one space: mylabel:echo("You -> point")

-- but this would, because it replaces all spaces with &nbsp before echoing mylabel:echo(string.gsub("You -> point", " ", " ")) </lua>

<lua> -- here is another way to go about this - and it additionally makes the font be monospaced:

mylabel:echo("

You       ->      point

")

</lua>

To add a new line in a label (aka linebreak), use
(instead of \n as you are used to in an echo). <lua> mylabel:echo("These
words
are
split") </lua>

Transparent labels

One of the possible ways of achieving transparency on a label is to add background-color: rgba(0,0,0,0%); to its stylesheet. Here's an example:

<lua> my_transparent_label:setStyleSheet([[

 background-color: rgba(0,0,0,0%);

]]) </lua>

Geyser.MiniConsole

This allows you to spawn a Mudlet miniconsole - unlike labels, these aren't as styleable, but they do format text better. They make a good fit for text-based menus, chat and map capture, and other things.

Spawning one is very similar to other Geyser elements: <lua> HelloWorld = Geyser.MiniConsole:new({

 name="HelloWorld",
 x="70%", y="50%",
 width="30%", height="50%",

}) </lua>

This'll make you one at the bottom-right of the screen. The miniconsole will have a grey background by default, but you can set it to any color you'd like with miniconsole:setColor():

<lua> HelloWorld:setColor("black") -- give it a nice black background </lua>

A special dimension property that MiniConsoles have is a character - instead of specifying a miniconsole to be % of a container or a certain number of pixels, you can specify it as a certain number of characters. You do this by using "c" at the end of a number. This way, you can, for example, specify miniconsole to be 10 letters long and 2 lines high:

<lua> flatbox = Geyser.MiniConsole:new({

 name="flatbox",
 x="70%", y="50%",
 width="10c", height="2c",

}) flatbox:setColor("red") flatbox:echo("ABCDEFGHIJ") -- that is 10 letters </lua>

Adding text

You can use echo() the same way with a miniconsole to add text as to the usual window:

<lua> HelloWorld:echo("hello!") </lua>

As well as cecho, decho, or hecho:

<lua> HelloWorld:cecho("<green>hey, <blue>colored <red>text!\n") </lua>

Copying lines with color

To copy a line over to the miniconsole, as it is from the game with all colors preserved, you just select, copy, and append it. For an example, try making a trigger with this as the Lua function pattern type:

<lua> return true </lua>

That'll make the trigger go off on every line. Then give it the following script: <lua> selectCurrentLine() copy() appendBuffer("HelloWorld") </lua>

... and you'll see all MUD output duplicated exactly as it is to the miniconsole. Amazing! It's very efficient as well, so you can have many miniconsoles, even in spam, not lag you down.

Doing edits in copied lines

Sometimes you'll want to edit the line before stuffing it into the miniconsole. For example, if you're making a chat capture, you'd want to condense a really long org name into something that's more space-friendly.

To do so, you'd use the selectString() the text you'd like to modify, replace() it with a different one:

<lua> selectString("Your", 1) -- select the word you'd like to replace - in this case, 'Your' setBgColor(getBgColor()) -- preserve the background color in the replacement setFgColor(getFgColor()) -- preserve the foreground color in the replacement replace("Mine") -- replace the selection with the wird 'Mine'

selectCurrentLine() copy() appendBuffer("HelloWorld") </lua>

Gagging from the main window

If you'd like to gag the line from the main window so it only shows up in your miniconsole, delete it after moving it over:

<lua> selectCurrentLine() copy() appendBuffer("HelloWorld") deleteLine() </lua>

Clickable menus

Using the echoLink, insertLink and setLink functions, you can turn text into one that reacts on a click. Combined with your power of placing text anywhere on the screen with a miniconsole, you can make menus with options. Here is one such example, where selecting an item causes an echo to happen:

<lua> flatbox = Geyser.MiniConsole:new({

 name="flatbox",
 x="20%", y="80%",
 width="40c", height="4c",

}) flatbox:setColor("red") clearWindow("flatbox")

flatbox:cecho("<white:red>Choose one of the following options:\n")

setFgColor("flatbox", 255,255,255) setBgColor("flatbox", 255,0,0)

for _, fruit in ipairs{"banana", "apple", "orange"} do

 echoLink("flatbox", "* "..fruit:title().."\n", echo("You picked ..fruit..\n"), "The "..fruit.." option", true)

end

resetFormat() </lua>

Which'll look something like the following:

Fruit menu.png

Geyser.Gauge

A Gauge allows you to represent numbers on a scale - and most typically, you've seen it be used as your standard hp/mana/whatever bar. A basic bar is made similarly to other Geyser elements. To set the value on the gauge that it should represent, use the setValue() function:

<lua> hpbar = Geyser.Gauge:new({

 name="hpbar",
 x="50%", y="85%",
 width="45%", height="5%",

}) hpbar:setValue(math.random(1,100),100) </lua>

That'll spawn you a pretty basic gauge with a horizontal orientation and a grey colour - and as a test, with a random value.

Basic gauge.png

Updating a gauge

You'd want your gauge to stay in sync with your actual values. To make that happen, you want to call setValue() whenever the value that the gauge is tracking changes.

So for example, if you make a health bar - wherever you get your new health at (be it prompt, gmcp, atcp or whatever), update the gauge as well:

<lua> -- theoretical example current_health, max_health = tonumber(matches[2]), tonumber(matches[3])

-- update the bar hp_bar:setValue(current_health, max_health) </lua>

You can also write down how much health have you got on the bar with:

<lua> lua local hp = math.random(1,100) hpbar:setValue(current_health, max_health, ""..max_health.."hp") </lua>

Hpbar basic.png

Styling a gauge

The Geyser gauge is composed of two labels - one is called mygauge.front and the other is mygauge.back. Combining this with Geyser:Label.setStyleSheet, you can improve the visuals of your gauges by using Qt-supported CSS. The syntax for specifying CSS is a bit different - it requires a semicolon after every property, and is done in the format of property name:values;. A list of all possible properties you can use is available here. Practical example:

<lua> hpbar = Geyser.Gauge:new({

 name="hpbar",
 x="50%", y="85%",
 width="45%", height="20px",

}) hpbar.front:setStyleSheet([[background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #98f041, stop: 0.1 #8cf029, stop: 0.49 #66cc00, stop: 0.5 #52a300, stop: 1 #66cc00);

   border-top: 1px black solid;
   border-left: 1px black solid;
   border-bottom: 1px black solid;
   border-radius: 7;
   padding: 3px;

]]) hpbar.back:setStyleSheet([[background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #78bd33, stop: 0.1 #6ebd20, stop: 0.49 #4c9900, stop: 0.5 #387000, stop: 1 #4c9900);

   border-width: 1px;
   border-color: black;
   border-style: solid;
   border-radius: 7;
   padding: 3px;

]])

hpbar:setValue(math.random(1,100),100) </lua>

Fancy Geyser gauge.png

The same style can be adjusted by colors to red as well:

<lua> hpbar = Geyser.Gauge:new({

 name="hpbar",
 x="50%", y="85%",
 width="45%", height="20px",

}) hpbar.front:setStyleSheet([[background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f04141, stop: 0.1 #ef2929, stop: 0.49 #cc0000, stop: 0.5 #a40000, stop: 1 #cc0000);

   border-top: 1px black solid;
   border-left: 1px black solid;
   border-bottom: 1px black solid;
   border-radius: 7;
   padding: 3px;]])

hpbar.back:setStyleSheet([[background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #bd3333, stop: 0.1 #bd2020, stop: 0.49 #990000, stop: 0.5 #700000, stop: 1 #990000);

   border-width: 1px;
   border-color: black;
   border-style: solid;
   border-radius: 7;
   padding: 3px;]])

hpbar:setValue(math.random(1,100),100) </lua>

Fancy Geyser gauge red.png

HBox/VBox

These are special types of containers. Every window in these is horizontally or vertically aligned in the order they were added.

Added to Mudlet in 2.0-rc4

Tutorial

Note: This tutorial assumes you know how scripts in Mudlet work. If not then you should look at the manual first. Also it only shows how Geyser basically works and explains Geysers special windows. It wont go into detail about the windows that where already in Mudlet.

Hello World

Let's start with something simple. A Label.

<lua>

Geyser.Label:new({

name="HelloWorld", x=50, y=50, width=200, height=50, }) </lua>

Geyser HW 1.png

This code creates a blank Label with a size of 200x50 at a position of 50 points horizontal and vertical from its parent window - which is the main window since we didn't specify any.

You can manipulate the Label through the normal functions but Geyser.Label:new() returns an object which can be used to manipulate the label directly. So you should store it:

<lua>

local HelloWorld = Geyser.Label:new({

name="HelloWorld", x=50, y=50, width=200, height=50, }) </lua>

Then you can, for example print a text on it:

<lua>

HelloWorld:echo("Hello World")

</lua>

Geyser HW 2.png

You can put a format parameter so that the text is, for example, centered. <lua> HelloWorld:echo("Hello World", nil, "c") </lua>

Geyser HW 3.png

The second parameter is the color. We set it to nil which means the labels foreground color will be used.

The color parameter either accepts a string ("red"), a hex value("#FF0000" or "0xFF0000" or "|cFF0000"), or a decimal value "<255,0,0>"

Example: <lua> HelloWorld:echo("Hello World", "red", "c") </lua>

Geyser HW 4.png

Note Note: This will automatically set the foreground color, so any echo, without the color parameter set, after that will use the same color.

You can also set the foreground color with the setFgColor method:

<lua> HelloWorld:setFgColor("red") HelloWorld:echo("Hello World", nil, "c") </lua>

Geyser HW 4.png

Containers

Containers are windows that can contain other windows. Actually, since all other Geyser windows subclass container, every window can do that. But containers do not have any visible content by themselves.

Let's show that by an example: <lua>

local container = Geyser.Container:new({

name="container", x=50, y=50, width=250, height=50, }) </lua>

This will create a container, but if you look at the screen you will see nothing at the positon. There is a way to make containers visible though: <lua> container:flash() </lua>

This will flash the container for a short period of time.

Geyser Container 1.png

flash() accepts a number as paremeter which defines the time, in seconds, the flash is shown.

Now, that the container is created, you can add other windows to it. There are 2 ways:

Directly when creating the window:

<lua>

local container_label = Geyser.Label:new({

name="container_label", x=0, y=0, width="100%", height="100%", }, container) container_label:echo("This is a label in a container", nil, "c") </lua>

Later, after the window was created <lua>

local container_label = Geyser.Label:new({

name="container_label", x=0, y=0, width="100%", height="100%", }) container_label:echo("This is a label in a container", nil, "c") container:add(container_label) </lua>

Both will lead to the same outcome.

Geyser Container 2.png

Note that we gave a width and height of "100%" to the constructor of the container. This means that the label will take 100% of the containers width and height. If values are given in percent they will even resize with its parent:

<lua> container:resize(325, nil) </lua>

Geyser Container 3.png

The first parameter is the width, the second the height. If the value is nil the current value is used.

As said in the "Hello World" tutorial the position is relative to its parent window. That's why we could set both x and y to 0 and it is at the position we wanted - the position of the container.

When we now move the container the label moves with it: <lua> container:move(400, nil) </lua>

Geyser Container 4.png

The first parameter is the x-, the second the y-position. If the value is nil the current value is used.

VBox and HBox

The VBox and HBox classes are special Containers. They will automatically align its containing windows vertically or horizontally, respectively, in the order they where added to them.

<lua>

local HBox = Geyser.HBox:new({

name="HBox", x=0, y=0, width=400, height=30, })

</lua>

Like containers you won't see them by themselves.

Adding children works like with containers <lua>

local label1 = Geyser.Label:new({

name="Label1", }, HBox) label1:echo("Label 1", "black", "c") label1:setColor(255, 0, 0)

</lua>

HVBox 1.png

We didn't set any position or size, but the label gets the same size as the HBox.

If we add another window: <lua>

local label2 = Geyser.Label:new({

name="Label2", }, HBox) label2:echo("Label 2", "black", "c") label2:setColor(0, 255, 0)

</lua>

HVBox 2.png

the size will be divided equally between them!

What if you want a child that takes more or less space than the others? That's possible too: <lua>

local label3 = Geyser.Label:new({

name="Label3", h_stretch_factor=2.0, }, HBox) label3:echo("Label 3", nil, "c") label3:setColor(0, 0, 255)

</lua>

HVBox 3.png

As you can see, Label 3 takes the same space as Label 1 and 2 Together. That's because we supplied a horizontal stretch factor with "h_stretch_factor=2.0"

This works also with a vertical stretch factor, just replace "h_stretch_factor" with "v_stretch_factor"

Now you may have windows that should not be stretched at all. To accomplish this you have to set the horizontal and/or vertical policy:

<lua>

local label4 = Geyser.Label:new({

name="Label4", width="13%", h_policy=Geyser.Fixed, }, HBox) label4:echo("Label 4", "black", "c") label4:setColor(0, 255, 255)

</lua>

HVBox 4.png

Possible values for the policies are Geyser.Fixed and Geyser.Dynamic. The default is Geyser.Dynamic. Note that, like in the example above, the label will retain relative values (like percent) if used.

The VBox works like the HBox, only that the child windows are aligned vertically.

Nestable Labels

This is a new feature added by Chris. It is an extension of the Label class, but has a few nuances. First, within the current scope, nested labels cannot have a container, they must be their own container (ie you just don't specify a container). Second, you add the parameter nestable=true to your label creation. Lastly, it is not required, but you are advised to specify the width/height because the defaults are huge. To add additional labels under a nestable label, the addChild method exists. addChild takes the normal parameters available to a label, and inherently allows nesting. A nested label can have the option 'flyOut=true' which will make the label flyout and close with the mouse hovering over it. Note: as of October 1, 2011 this feature is only available within my repository, but it will likely be ported into the main Mudlet branch. Here is a small example:

Available options to layoutDir are the direction the window should go (R for right, L for left, T for top, B for bottom), followed by how the nested labels should be oriented (V for vertical or H for horizontal). So options are: RV, RH, LV, LH, etc...

<lua>

b = Geyser.Label:new({name="testa", x=400,y=50,height=100,width=100,nestable=true, message="CLICK ME!"})
c = {}
for i=1,20 do
 c[i] = b:addChild({name="test"..tostring(i),height=30,width=60, layoutDir="BH", flyOut=true, message="test"..tostring(i)})
end
d = {}
for i=21,40 do
 d[i]=c[5]:addChild({name="test"..tostring(i),height=30,width=60, layoutDir="RV", flyOut=true, message="test"..tostring(i)})
 d[i]:setClickCallback("testFunc", d[i].name)
end
function testFunc(name)
 display(name)
end

</lua>