One of the most useful features of LiveCode is the ability to group controls and view them as a single object. In this lesson, we demonstrate how to use a group as an custom control in LiveCode, while constructing a scrollbar.
You can download the sample stack from this url: https://tinyurl.com/ydx8s8bj
What is a LiveCode custom control?
The idea of a custom control in LiveCode is similar to the idea of an "object" in programming languages such as Java. A custom control is a group whose functionality is entirely encapsulated within itself, and which doesn't affect its environment in any way.
Using custom controls in your programs has many advantages, two of the most significant are increased modularity of the program, and the greater ability to re-use code between programs. A well designed custom control can be copied and pasted into any application and will be ready for use almost immediately. Over time you can build up a library of controls which will greatly speed up programming. The modularity helps when debugging your application, because a custom control is insulated from errors in other parts of the program, and likewise, the rest of the program is insulated from errors in the control.
Groups and Group Scripts
A simple and effective way to write a custom control is to make use of the group script, and have a single handler that updates the control based on its state. The state of the control is the only thing that the "outside world" knows about it, and custom properties in LiveCode are an ideal way to express this. Below we show how this idea can be used to create a scrollbar control that can be used in exactly the same way as the default LiveCode scrollbar, with the advantage of being fully customizable. Using this control it is possible to have "skinned" scrollbars throughout your program in no time at all!
Creating a custom control
The first thing to do is to create your custom control by dragging the fields, buttons etc that you require into your program, naming them, and grouping them.
For the scrollbar, create three buttons "End 1", "End 2" and "Slider" and an image area called "Background". Group these four controls and call the group "Scrollbar", don't worry about arranging or resizing the controls. Now open the script of your new custom control and lets begin.
The state of the custom control
The state of the custom control is the first thing to set up. The state will consist of a number of local variables, and a number of getProps and setProps to allow the rest of the program to manipulate them. We need to consider what properties the control should have. With the scrollbar this is easy, because we can just drag a LiveCode scrollbar control from the tools palette into the stack and examine its properties in the inspector.
The essential properties of the scrollbar are
- Orientation: whether the scrollbar is vertical or horizontal
- Start value: the number that the scrollbar runs from
- End value: the number that the scrollbar runs to
- Thumb size: the size of the scrollbar's slider
- Thumb position: the position of the scrollbar's slider
There are also some other properties that will help make the scrollbar more customizable:
- Line increment: how much to scroll when the user clicks on the scroll buttons
- Page increment: how much to scroll when the user clicks on the back of the scrollbar
So we use the variables sOrientation, sStartValue, sEndValue, sThumbSize, sThumbPosition, sLineInc and sPageInc. These are declared at the top of the group script, outside any handler.
Using setProp and getProp handlers
Next we write setProp handlers for each variable. It is a good idea to comment these handlers explaining what the format of each variable should be. It is sensible also to check the input is correct to help find errors and keep the state of the scrollbar valid. Below is the setProp and getProp for the scrollbar's orientation.
setProp cOrientation pValue if pValue is not among the items of "horizontal,vertical" then error "invalid orientation, expected horizontal or vertical, got " & pValue end if put pValue into sOrientation updateScrollbar end cOrientation getProp cOrientation return sOrientation end cOrientation
The update function
Once all the properties of the control are set up in this manner, we can write the "update" function, which simply needs to take all the variables and set the scrollbar up correctly. This function should consist of the following steps:
- Verify all the parameters are valid
- Layout the scrollbar's controls
Also it is very useful here to add an update lock to the control. This enables multiple changes to be made to the control's state without needing to update many times, because the update handler may become quite large in more complex custom controls. The update lock requires another variable "sUpdateLock" and a setProp as follows:
setProp cUpdateLock pValue if pValue is not among the items of "true,false" then answer error "invalid value, expected Boolean, got " & pValue end if if pValue then add 1 to sUpdateLock else if sUpdateLock > 0 then subtract 1 from sUpdateLock end if if sUpdateLock is 0 then updateScrollbar end if end cUpdateLock
If we add an if statement to the top of the update handler that exits the handler immediately if sUpdateLock is not zero, then this effectively means we can set all the properties and then only call update once when we are done.
on updateScrollbar local tResult if sUpdateLock > 0 then exit updateScrollbar end if put updateCheckParams() into tResult if tResult is not empty then answer error tResult end if updateLayout end updateScrollbar
Setting up the scrollbar
Once the update handler has been written, all that remains is to handle the scrollbar's user interaction. This requires writing mouseDown, mouseUp and mouseMove handlers, plus a few more to fine tune the interaction. These handlers should set the properties of the scrollbar, thus causing it to update, rather than manipulate the controls directly.
It is relatively straightforward to write the remaining code, and if done correctly, the scrollbar can now be configured using a handler similar to this, in the script of the card that you wish to use the scrollbar on.
on scrollbarSetup pBar set the cUpdateLock of pBar to true set the cOrientation of pBar to the label of button "Orientation" set the cStartValue of pBar to the text of field "startValue" set the cEndValue of pBar to the text of field "endValue" set the cThumbSize of pBar to the text of field "thumbSize" set the cThumbPosition of pBar to the text of field "thumbPosition" set the cLineInc of pBar to the text of field "lineInc" set the cPageInc of pBar to the text of field "pageInc" set the cUpdateLock of pBar to false end scrollbarSetup
Note: pBar is a reference to a scrollbar group, for example the long id of group "Scrollbar"
Using the scrollbar
When the scrollbar is used, its cThumbPosition will be set to the same value as if it was a standard scrollbar in LiveCode, so that if you are already using a standard scrollbar in your program, it will be very easy to change your code to use a custom scrollbar group.
The key to this design is the fact that the custom control has a minimal interaction with the rest of the program. Its state can be changed, but no other messages need to be passed, and no shared variables are used. You can easily use the place command to duplicate the control across your whole stack, and can with equal ease use the scrollbar in many different stacks.
There are many ways to extend this custom control, if you download the stack attached to this lesson you can experiment. A very easy and useful extension is to give the scrollbar group default values for all its properties, which are stored as constants in the script. These default values can then be used if any of the scrollbar's properties are not set, allowing a scrollbar to be created without any initialisation.