How do I define my own properties for an object?

This lesson shows how to store custom properties in an object, and how to define getProp/setProp handlers to customize behaviour when getting/setting custom properties

Introduction

All objects in LiveCode have properties, built-in properties such as the name, width & height of an object, and custom properties which can be used to store any kind of information associated with that object.

The built-in properties often have an immediate effect on the appearance or behaviour of an object, whereas custom properties require some scripting on behalf of the LiveCode programmer to have an effect.

Setting and Getting Custom Properties

The syntax for accessing custom properties is the same as used to access built-in properties so it is important to choose names for custom properties that are different from the built-in object properties to avoid confusion.

One common approach to custom property naming is to prefix the names of custom properties with a lowerspace 'c' character.  As an example, if we wish to store a name and location within an object as a custom property, we could do the following:

set the cName of field "livecode" to "LiveCode Ltd."
set the cLocation of field "livecode" to "Edinburgh"

The "name" and "location" properties are built-in and common to all objects, so cannot be used as the names of our custom properties.

 

getProp and setProp Handlers

If we want our custom properties to be more than just static collections of data, we need a way to script how an object behaves when these properties are accessed.  This is done by defining getProp and setProp handlers for each custom property.

getProp

getProp

Using a getProp handler allows us to define a custom property as a function which returns a value computed at the time the property is requested.

To define a getProp handler for a property, the following syntax is used:

getProp <propertyName>
	/*
	the script which calculates
	the value to return goes here
	...
	*/
	return <propertyValue>
end <propertyName>

The following code shows an example of a getProp handler for a "longestline" property, which gives the longest line in a field or other text-containing object:

getProp longestLine
	local tLongestLine, tLongestLength, tLineLength
	put 0 into tLongestLength
	repeat for each line tLine in the text of me
		put the number of chars in tLine into tLineLength
		if tLineLength > tLongestLength then
			put tLineLength into tLongestLength
			put tLine into tLongestLine
		end if
	end repeat
	return tLongestLine
end longestLine

 

setProp

setProp

By adding setProp handlers to an object we can reduce complex operations to simple one-line scripts.  As an example, lets consider rotating a polygon through a given angle.  The built-in angle property has no effect on freehand polygons, but we can use the utility function revRotatePoly.  revRotatePoly modifies the points of a polygon in such a way that repeated uses of the function can deform the points of our polygon, so we also need to save the points of the polygon and restore these original points before rotation.  To simplify this process we can encapsulate this behaviour within a setProp handler for a new property "rotation" that acts as an angle property for freehand polygons:

setProp rotation pValue
	local tPoints, tLoc
	lock screen
	put the loc of me into tLoc
	if the cOldPoints of me is empty then
		// save the points before rotation
		put the points of me into tPoints
		set the cOldPoints of me to tPoints
	else
		// restore the saved points
		put the cOldPoints of me into tPoints
		set the points of me to tPoints
	end if
   
	if pValue is 0 or pValue is empty then
		set the cOldPoints of me to empty
	else
		revRotatePoly (the long id of me), pValue
	end if
	set the loc of me to tLoc
	unlock screen
end rotation

We can now use this property to rotate our polygon simply by setting the rotation property.

Note that defining a getProp or setProp handler for a custom property bypasses LiveCode's normal mechanism for storing custom properties, however we can still store them as normal within the property handler itself.  When a property handler for a particular custom property attempts to access that same custom property, rather than invoking the property handler in a infinite recursive loop, the custom property is accessed directly, rather than through the handler.

This example shows how to access and modify a custom property which is otherwise "masked" by the getProp handler:

getProp nextValue
	local tNextValue
	// this access of nextValue will not result
	// in the getProp handler being called again
	put the nextValue of me into tNextValue
	if tNextValue is empty then put 1 into tNextValue
   
	set the nextValue of me to tNextValue + 1
	return tNextValue
end nextValue

With this handler, every time we get the nextValue of an object, the stored property is incremented so that the next time we get the nextValue it will have increased by 1.

0 Comments

Add your comment

E-Mail me when someone replies to this comment