Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Livecode widget course

1,025 views

Published on

Extending Livecode with widgets and libraries

Published in: Software
  • If you want to discover how you can increase your cup size within 6 weeks then you need to see this new website... ★★★ https://dwz1.cc/c0uELUMU
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Hi there! I just wanted to share a list of sites that helped me a lot during my studies: .................................................................................................................................... www.EssayWrite.best - Write an essay .................................................................................................................................... www.LitReview.xyz - Summary of books .................................................................................................................................... www.Coursework.best - Online coursework .................................................................................................................................... www.Dissertations.me - proquest dissertations .................................................................................................................................... www.ReMovie.club - Movies reviews .................................................................................................................................... www.WebSlides.vip - Best powerpoint presentations .................................................................................................................................... www.WritePaper.info - Write a research paper .................................................................................................................................... www.EddyHelp.com - Homework help online .................................................................................................................................... www.MyResumeHelp.net - Professional resume writing service .................................................................................................................................. www.HelpWriting.net - Help with writing any papers ......................................................................................................................................... Save so as not to lose
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Get Paid To Write Articles? YES! View 1000s of companies hiring online writers now! ■■■ https://tinyurl.com/vvgf8vz
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Livecode widget course

  1. 1. #LiveCodeGlobal Widget Course Extending LiveCode with Widgets and Libraries LiveCode Dev Team
  2. 2. #LiveCodeGlobal Hello World Library
  3. 3. #LiveCodeGlobal LiveCode Builder Extensions In this lesson we will create a minimal LiveCode Builder library which extends the set of commands and functions available in LiveCode. We will ● Install and configure an appropriate text editor for developing in LiveCode Builder. ● Create a Hello World library which extends LiveCode with a single function, which returns the string “Hello World!”. ● Compile the library. ● Install the library into the LiveCode IDE. ● Include the library in a standalone.
  4. 4. #LiveCodeGlobal Libraries and Widgets There are two types of extensions that can be created with LiveCode Builder: ● Libraries: A library can be used to extend the set of commands and functions available in LiveCode. The public handlers in a library are added at the bottom of the Message Path. LCB libraries make LCB features available to LiveCode apps directly. They can also be used as support code for widgets. ● Widgets: A widget is a custom control that is treated as an engine level element. Widgets appear in the Tools Palette and can be added as controls to any LiveCode stack. A widget and a library are identical, except that a widget draws to a canvas. As a result, the authoring process is much the same for both extension types.
  5. 5. #LiveCodeGlobal When to use LiveCode Builder Write widgets when: ● You need unique capabilities that can't be provided by "traditional" controls. ● You require encapsulation - widgets are 'black boxes' whose behavior can only be changed from LiveCode apps via predefined API. ● You want access to drawing / low-level / native APIs. ● You want improved performance, you control what recalculations are made when a control is redrawn.
  6. 6. #LiveCodeGlobal When to use LiveCode Builder Write libraries when: ● You want to write functions that are available to both LiveCode Builder(LBC) and LiveCode Script(LCS). ● You want to wrap platform-specific functionality and make it usable from LiveCode Script. ● You want to use LiveCode Builder's stricter rules to implement algorithms that can't be expressed reliably in LiveCode Script.
  7. 7. #LiveCodeGlobal The Message Path LiveCode Engine LiveCode Builder Libraries Stack Card Group Grouped Control Control Input Events (mouseUp, keyDown, etc.) Other Events (openCard, closeStack, etc.) Handlers implemented in installed libraries are placed at the end of the Message Path. For more on the Message Path see the “Message Path” Chapter of the LiveCode User Guide.
  8. 8. #LiveCodeGlobal Installed widgets are shown in the widgets section of the Tools Palette. Widgets are added to stacks by dragging and dropping from the Tools Palette. Tools Palette showing installed widgets Rotated Text Widget Pie Chart Widget
  9. 9. #LiveCodeGlobal LiveCode Builder API The API for LiveCode Builder is available in the Dictionary stack. You may find it useful to have this open while you are writing your extension. 1. Open the Dictionary from the Menubar. 2. Ensure you are on the API pane. 3. Select LiveCode Builder from the drop down menu.
  10. 10. #LiveCodeGlobal LiveCode Builder extensions are written in a text editor rather than the LiveCode IDE. We recommend using the Atom text editor. A LiveCode package is available which provides some colorization as well as indentation. If you are on Mac and prefer to use TextWrangler, there is a colorizing script here. It should be placed in /Application Support/TextWrangler/Language Modules/. Installing a Text Editor
  11. 11. #LiveCodeGlobal Installing the Atom LiveCode Language Pack To install the LiveCode Language Pack in Atom ● Select File -> Preferences to open the Atom Settings ● Go to the Install tab of the Settings pane ● Search for the “language-livecode” package in the Search field ● Click Install
  12. 12. #LiveCodeGlobal Creating a LiveCode Builder Library Start by creating a new directory to develop your extension in. When you package an extension a number of files are created. The Extension Builder currently relies on there being only one .lcb file in a given directory. Because of this it is simplest to create a new directory for each extension you create. The extension files that are created include an API file, manifest and compiled module file.
  13. 13. #LiveCodeGlobal Creating a LiveCode Builder Library Create a new plain text file in the directory and save it to disk with the extension ".lcb". It’s important to use the “.lcb” extension so your chosen text editor applies LiveCode Builder formatting to your code, if available. I am naming my file "helloWorldLibrary.lcb" but you can name your file anything suitable.
  14. 14. #LiveCodeGlobal LCB Library Definition The first thing we need to do is declare the type of extension we are writing. We are writing a library and so we need to declare the extension as such. The library declaration is followed by an identifier. An extension identifier should be in the form community.livecode.<user name>.<library name> In my case my username is "elanorb" and I have chosen to use "helloworld" as the name part of the identifier. library community.livecode.elanorb.helloworld end library
  15. 15. #LiveCodeGlobal LCB module naming The module name uses reverse DNS notation. For example, a module created by the Example Organisation would use module names beginning with ‘org.example.’. You must only use module names corresponding to domain names that you control or are allowed to use. If you don't have a domain name of your own, you may use module names beginning with ‘community.livecode.’. For example, if your username is "sophie", then you can create a module named ‘community.livecode.sophie.mymodule’. Always write module names in lower case. For more detailed information check the LiveCode Builder Style Guide. The guide is available under the ‘Guide’ tab in the Dictionary or as a PDF under the ‘Resources’ tab for this lesson.
  16. 16. #LiveCodeGlobal LCB public handler definitions Handler definitions are used to define functions which can be called from LCB code, invoked as a result of events triggering in a widget module, or called from LCS if public and inside a library module. There is no distinction between handlers which return a value and ones which do not, apart from the return type. Definitions can be either public or private (the default is private). Private handlers can only used within the module. Public handlers are available when the module is used by another module, for example public handlers can be called from LCS. Handler definitions have the form <HandlerType> handler <HandlerName>(<ParameterList>) [ returns <ReturnType> ] end handler
  17. 17. #LiveCodeGlobal Naming Handlers It is best practice to give handlers TitleCase names. In general, please use verbs to name your handlers. For example, handler RotateShape(inout xShape, in pAngleInDegrees) ... end handler For more on this see the LiveCode Builder Language Reference Guide in the Dictionary or Additional Course Resources.
  18. 18. #LiveCodeGlobal The Hello World Library has one handler which returns the string "Hello World!". Add the definition for the sayHello handler to the library. Let's break down the definitions ● HandlerType - public: we want to be able to call this handler from LCS so it needs to be public ● HandlerName - SayHello: the name of the handler, used to call the handler from LCS ● ParameterList - empty, no parameters are passed in. The SayHello handler <HandlerType> handler <HandlerName> (<ParameterList>) [ returns <ReturnType> ] library community.livecode.elanorb.helloworld public handler SayHello() end handler end library
  19. 19. #LiveCodeGlobal To return a string value we can return the string directly. Add a return statement to the sayHello handler. Returning a string library community.livecode.elanorb.helloworld public handler SayHello() return "Hello World!" end handler end library
  20. 20. #LiveCodeGlobal Testing the library Now we have a complete library we want to compile and test it. To do this we use the LiveCode Extension Builder. 1. Open LiveCode. 2. Open the Extension Builder from the Tools Menu.
  21. 21. #LiveCodeGlobal The Extension Builder 1. Open button - allows you to select and load the extension you wish to build. 2. Data that the builder was able to parse from the directory such as icons, resources, API's the user guides. 3. Log: Shows status, error and log messages. 4. Test Button: compiles the extension and loads it into LiveCode 5. Script Button: Opens the lcb script in an external default editor. 6. Install Button: Installs the extension into the IDE 7. Uninstall Button: Uninstalls the extension from the IDE 8. Package Button: Creates a .lce package which can be shared
  22. 22. #LiveCodeGlobal Compiling the Hello World Library Initially we will use the Test button to compile the library and test it without installing. 1. Click the Open button and select the “HelloWorldLibrary.lcb” file. 2. The Icons, Resources, Default Script, API and User Guide sections are automatically populated. 3. Click the Test button to compile and load the library in LiveCode.
  23. 23. #LiveCodeGlobal Compiling the Hello World Library The log field will give you show the compilation progress and display any warnings. The Extension Builder will create a test stack.
  24. 24. #LiveCodeGlobal LiveCode Builder Extension Files When the Extension Builder is used to compile a LiveCode Builder file a number of files are created. ● api.lcdoc - LiveCode doc file for the extension. This file is generated by extracting all of the documentation information from the LCB source code, and is used to display the API documentation for the library in the Dictionary window in the IDE ● mylibraryname.lci - LiveCode Interface file. This file provides information about the "public" interface for the library. It's used by the compiler when compiling LCB source code that uses the library. ● Manifest.xml - This file describes the library and its contents in a structured format. It is used by the IDE and by other tools to discover what the library contains. ● Module.lcm - The compiled module file. This is the compiled library bytecode, which is the output of compiling the library source code. It is the low-level code that's run by the LCB virtual machine when the library is in use. Each module you create will have files with the same names, for example api.lcdoc, which is why we create each extension in a separate directory.
  25. 25. #LiveCodeGlobal Now the library is loaded we can test it in a LiveCode stack. ● Add a button to the test stack. ● Set the code of the button to ● Click the button. You should see an answer dialog displaying the “Hello World!” message returned by the library. Testing the library in a LiveCode stack on mouseUp answer sayHello() end mouseUp
  26. 26. #LiveCodeGlobal In order to package any extension in LiveCode Builder we need to add some required metadata. The metadata provides information about the extension. The required metadata is ● title: a human-readable name for the module ● author : the name of the author of the module ● version a string in the form X.Y.Z (with X, Y and Z integers) describing the module version You can also include an optional description ● description: a simple description of the module's purpose If the required metadata is not added a number of warnings will be printed into the log field when building and packaging the extension. LiveCode Builder extension metadata
  27. 27. #LiveCodeGlobal Version numbers We suggest using Semantic Versioning when assigning the version number of the extension. The uses a version format of X.Y.Z (Major.Minor.Patch). Given this format you would increment 1. The Major version when you make incompatible API changes. 2. The Minor version when you add functionality in a backwards-compatible manner. 3. The Patch version when you make backwards-compatible bug fixes. Under this scheme version numbers, and the way they change, provide clear and valuable information about the underlying code and the changes between versions. For a more detailed explanation of Semantic Versioning see http://semver.org/.
  28. 28. #LiveCodeGlobal Library metadata library community.livecode.elanorb.helloworld metadata title is "Hello World Library" metadata author is "Elanor Buchanan" metadata version is "1.0.0" … handler definition end library Add the metadata after the library definition in the LCB file ● title: a human-readable name for the module, I have used “Hello World Library” but you can choose any suitable name ● author: add your name as the author of your library ● version: this is the first version of the library so the version is “1.0.0”
  29. 29. #LiveCodeGlobal The finished library library community.livecode.elanorb.helloworld metadata title is "Hello World Library" metadata author is "Elanor Buchanan" metadata version is "1.0.0" public handler sayHello() return "Hello World!" end handler end library The library is now complete, including metadata, ready to be installed into LiveCode
  30. 30. #LiveCodeGlobal Installing the library into the LiveCode IDE The Extension Builder is also used to install libraries. Installed libraries are loaded each time LiveCode is started up. Extensions are installed into your My LiveCode folder. 1. Open the Extension Builder from the Tools menu. 2. Click the Open button and load the “HelloWorldLibrary.lcb” file. 3. Click the Install button to install the library. 4. You will be asked to select an icon and a high resolution icon, click ‘Cancel’ on these dialogs as no icon is needed for a library.
  31. 31. #LiveCodeGlobal The installed library Go to your My LiveCode folder. In the Extensions folder you will see a folder with the same name as your library identifier. This folder contains the files that are make up the packaged extension. Any extensions installed to My LiveCode are automatically loaded when LiveCode is started up.
  32. 32. #LiveCodeGlobal To test your library is correctly installed execute execute put the loadedExtensions in the Message Box. Your library will appear in the list of extensions. To test the library handler execute put sayHello() in the Message Box Testing the installed library
  33. 33. #LiveCodeGlobal Packaging a library In order to share your library you create a package. This package can be shared with other LiveCode users. 1. Open the Extension Builder from the Tools menu. 2. Click the Open button and load the “HelloWorldLibrary.lcb” file. 3. Click the Package button. This will create a packaged library file with the extension .lce in the same folder as your .lcb file. The name of the file is the library identifier followed by the version number.
  34. 34. #LiveCodeGlobal Loading a Packaged Extension To load a packaged extension you use the Extension Manager. 1. Open the Extension Manager from the Tools menu. 2. Click Open(+). 3. Select the .lce file you want to install. The loaded extension appears in the list. You can also use the Extension Manager to uninstall extensions.
  35. 35. #LiveCodeGlobal Including the library in a standalone If you have created a LiveCode app that uses a library and want to build it into a standalone you must ensure the library is included in the standalone file. Choose File -> Standalone Application Settings. On the General Pane you can choose to let LiveCode search for inclusions (libraries, widgets and externals) or select any inclusions manually.
  36. 36. #LiveCodeGlobal Selecting inclusions If you choose to select the extensions to include the Inclusions pane will be enabled. Go to the Inclusions pane and select the extensions you want to include in the standalone.
  37. 37. #LiveCodeGlobal Testing the standalone Once your Standalone Settings are complete choose File -> Save as Standalone Application. Start up the standalone and check that the library is included and returning the message.
  38. 38. #LiveCodeGlobal Congratulations You have completed this lesson, you can now ● Create a LiveCode Builder library ● Package and install a library into LiveCode ● Include the library in a standalone
  39. 39. #LiveCodeGlobal Widget Course Extending LiveCode with Widgets and Libraries LiveCode Dev Team
  40. 40. #LiveCodeGlobal Extending the Hello World Library
  41. 41. #LiveCodeGlobal Extending the Hello World library In this lesson we will extend the minimal LiveCode Builder library we created in Lesson 1. We will ● Learn about LiveCode Builder types. ● Work with LiveCode Builder lists. ● Learn about type conversion between LCB and LCS. ● Pass a parameter to the SayHello handler. ● Document the library using documentation comments. ● Browse the library documentation in the Dictionary stack.
  42. 42. #LiveCodeGlobal LiveCode Builder Typing LiveCode Builder is a strongly, dynamically typed language, although typing is completely optional in most places. If a type is not specified it is taken to be the most general type optional any (meaning any value, including nothing).
  43. 43. #LiveCodeGlobal If a language is defined as typed it means that the types of all variables are known or inferred at compile time. Strongly typed A strongly typed language does not allow you to use one type as another. For example you cannot add a string and a number together. Type conversions have to be performed explicitly when required. Weakly typed A weakly typed language allows types to be mixed in the same expression, by making implicit type conversions. What is a strongly typed language?
  44. 44. #LiveCodeGlobal What is a dynamically typed language? Dynamically typed Dynamically typed programming languages do type checking at run-time as opposed to compile-time. Statically typed Statically typed programming languages do type checking (the process of verifying and enforcing the constraints of types) at compile-time as opposed to run-time. LiveCode Builder is a dynamically typed language. Any typing errors are found at runtime, not at compile time.
  45. 45. #LiveCodeGlobal LiveCode Builder Types The range of core types is relatively small, comprising the following: ● Boolean: one of true or false ● Integer: any integral numeric value ● Real: any numeric value ● Number: any integer or real value ● String: a sequence of UTF-16 code units ● Data: a sequence of bytes ● List: a sequence of any values ● Array: a mapping from strings to values ● any: a value of any type Additionally, all types can be annotated with optional. An optional annotation means the value may be the original type or nothing. There is one additional type, nothing, meaning no value.
  46. 46. #LiveCodeGlobal To demonstrate typing in LiveCode Builder we will create a very simple addition library. Example 1: Adding 2 numbers together In this example we create 2 number variables and add them together, resulting in another number. ● The return type of the additionTest handler is defined as Number. ● The 2 variables tLeft and tRight are defined as Number. ● Adding two numbers together results in a number value which can be successfully returned. Addition library library community.livecode.elanorb.addition metadata version is "1.0.0" metadata author is "Elanor Buchanan" metadata title is "Addition Library" public handler AdditionTest() returns Number variable tLeft as Number variable tRight as Number put 4 into tLeft put 5 into tRight return tLeft + tRight end handler end library
  47. 47. #LiveCodeGlobal Test the library using the Extension Builder. 1. Open the Extension Builder from the Tools menu. 2. Load the addition.lcb file. 3. Click the Test button Execute put additionTest() in the Message Box . The correct value “9” is displayed in the Message Box. Testing the Addition library
  48. 48. #LiveCodeGlobal Example 2: Adding a string and a number In this example we try to add a String and a Number and return a number. ● The return type of the AdditionTest handler is defined as Number. ● Variable tLeft is defined as a String. ● Variable tRight is defined as a Number. ● Attempting to add the 2 values together will return an error. Addition library 2 library community.livecode.elanorb.addition metadata version is "1.0.0" metadata author is "Elanor Buchanan" metadata title is "Addition Library" public handler AdditionTest() returns Number variable tLeft as String variable tRight as Number put 4 into tLeft put 5 into tRight return tLeft + tRight end handler end library
  49. 49. #LiveCodeGlobal Testing the Addition library Test the library using the Extension Builder ● Open the Extension Builder from the Tools menu. ● Load the addition.lcb file. ● Click the Test button No errors are returned at compile time but if you execute put AdditionTest() In the Message Box you will see an error. This is because LBC is strongly typed (you can’t add an string to a number) and dynamically typed (the error occurs at runtime).
  50. 50. #LiveCodeGlobal Addition library 3 Example 3: Adding a string and a number using type conversion In this example we create a String and a Number variable, convert the String to a Number and return a Number. ● The return type of the AdditionTest handler is defined as Number ● Variable tLeft is defined as a String ● Variable tRight is defined as a Number ● The value in tLeft is converted to a number by parsing the value as a number ● The value of the two numbers added together is returned library community.livecode.elanorb.addition metadata version is "1.0.0" metadata author is "Elanor Buchanan" metadata title is "Addition Library" public handler AdditionTest() returns Number variable tLeft as String variable tRight as Number put 4 into tLeft put 5 into tRight return tLeft parsed as number + tRight end handler end library
  51. 51. #LiveCodeGlobal Test the library using the Extension Builder. ● Open the Extension Builder from the Tools menu. ● Load the addition.lcb file. ● Click the Test button. Execute put AdditionTest() In the Message Box . The correct value “9” is displayed in the Message Box. The value in the string variable was converted to a number before the calculation was performed, allowing a number to be calculated and returned. Testing the Addition library
  52. 52. #LiveCodeGlobal LiveCode Builder Lists and Arrays Two important types in LCB, which deserve some more attention are lists and arrays. ● list - a list is a sequence of values, each element of the sequence is assigned a numerical index, starting with 1 and proceeding sequentially ● array - an array is a mapping from a string to any value (i.e. an associative array, just like in LiveCode Script)
  53. 53. #LiveCodeGlobal Creating Lists in LCB library community.livecode.elanorb.example metadata title is "Example Library" metadata author is "Elanor Buchanan" metadata version is "1.0.0" public handler CreateList() returns nothing variable tLetterList as List variable tNumberList as List variable tMixedList as List put ["a","b","c"] into tLetterList put [1,2,3] into tNumberList put ["one","two","three",4,5,6] into tMixedList end handler end library Creating a list in LiveCode Builder is very simple, you put a comma-separated list of values between square brackets as shown. Each element in a list can hold a different type of value.
  54. 54. #LiveCodeGlobal Creating Lists in LCB public handler CreateListFromString() returns String variable tVar as String variable tSplit as List put "first,second,third,fourth,fifth" into tVar split tVar by "," into tSplit end handler You can also split a string into a list using the split keyword. You specify the delimiter you want to use and the string is split into a list of strings using the delimiter.
  55. 55. #LiveCodeGlobal List elements You can access the individual elements of a list using the element keyword. You can ● Get the value of an element ● Set the value of an element ● Delete an element To add an element to a list you push a value onto the list, you can push a value onto the front or end of a list. Note: LCB lists are 1 based. Note: An error is returned if the index is out of range. public handler ListElement() returns any variable tMixedList as List put ["one","two","three",4,5,6] into tMixedList delete element 2 of tMixedList -- tMixedList = ["one","three",4,5,6] put "five" into element 4 of tMixedList -- tMixedList = ["one","three",4,"five",6] push "zero" onto front of tMixedList --tMixedList = ["zero","one","three",4,"five",6] end handler
  56. 56. #LiveCodeGlobal Creating Arrays in LCB Arrays in LCB are created in the same way as in LiveCode Script, so you are likely familiar with the syntax. You specify an element of an array variable by using the variable name along with the element's key. You enclose the key in square brackets. In LCB array keys are always strings. public handler CreateArray() returns nothing variable tCapitals as Array put "Kabul" into tCapitals["Afghanistan"] put "Tirana" into tCapitals["Albania"] put "Algiers" into tCapitals["Algeria"] put "Andorra la Vella" into tCapitals["Andorra"] put "Luanda" into tCapitals["Angola"] end handler
  57. 57. #LiveCodeGlobal Creating Arrays in LCB You can also create LiveCode Builder arrays using {} notation with the syntax: {Key 1:Value 1,Key 2:Value 2,...,Key n:Value n} public handler CreateBracketedArray() returns nothing variable tCapitals as Array put {"Afghanistan":"Kabul", "Albania":"Tirana", "Algeria":"Algiers", "Andorra":"Andorra la Vella", "Angola":"Luanda"} into tCapitals end handler
  58. 58. #LiveCodeGlobal Array elements You can access the individual elements on array using square bracket notation. You can ● Get the value of an element ● Set the value of an element ● Delete an element public handler CreateArray() returns nothing … previous array code -- Add an element to the array put "St. John" into tCapitals["Antigua and Barbuda"] -- Update an existing element of the array put "St. John's" into tCapitals["Antigua and Barbuda"] -- Delete the specified element of the array delete tCapitals["Antigua and Barbuda"] end handler
  59. 59. #LiveCodeGlobal Nested elements Both lists and arrays can be nested. This means an element in a list can contain another list, or an element in an array can contain another array. Elements of a nested list can be accessed by using multiple element values. For example: return element 2 of element 2 of tListOfLetters -- returns “B” Elements of a nested array can be accessed by using multiple sets of square brackets containing the keys. For example: return tCapitals["Spain"]["name"] -- returns “Madrid” public handler CreateNested() returns nothing -- A nested list (list of lists) variable tListOfLetters as List put ["a", ["b","B"]] into tListOfLetters -- A nested array variable tCapitals as Array variable tSpain as Array put "Madrid" into tSpain["name"] put "3,165,000" into tSpain["population"] put tSpain into tCapitals["Spain"] end handler
  60. 60. #LiveCodeGlobal You can also create nested arrays directly using the syntax {Key 1:Value 1,Key 2:Value 2,...,Key n:Value n} Where each value can also be an array expression {Key 1:{Key a:Value a,Key b:{Key α:Value α,Key β:Value β}},Key 2:Value 2,...,Key n:Value n} Example Returns public handler CreateNested() returns nothing variable tCapitals as Array put {"Spain": {"Name":"Madrid", "Population":"3,165,000"}, "UK":{"Name":"London", "Population":"8,539,000"}} into tCapitals end handler Nested elements 2
  61. 61. #LiveCodeGlobal Type Conversion between LCB and LCS When a value is returned to LiveCode from a LiveCode Builder library what type will it be? Because LCB is strongly typed and LiveCode Script is weakly typed for most LCB types we don’t need to worry about it. ● nothing ● Boolean ● Integer ● Real ● Number ● String ● Data All these types can be used directly in expressions or put into a LiveCode Script variable.
  62. 62. #LiveCodeGlobal Type Conversion between LCB and LCS The two exceptions are LiveCode Builder lists and arrays. ● list: when a LiveCode Builder handler returns a list it is converted to a numerically keyed LiveCode array, with continuous numerical keys. ● array: when a LiveCode Builder handler returns an array it is converted to a LiveCode array LiveCode Builder LiveCode Script variable tLetterList put ["a","b","c"] into tLetterList return tLetterList LiveCode Builder LiveCode Script variable tSpain put "Madrid" into tSpain["name"] put "3,165,000" into tSpain["population"] return tSpain
  63. 63. #LiveCodeGlobal Adding explicit types to the library In the first version of the Hello World Library we didn’t use any explicit types. In this lesson we will update the library with: ● An explicit return type ● A typed variable that will hold the message to be returned
  64. 64. #LiveCodeGlobal Adding a return type The first change we will make is to define the return type of the handler. In the initial version of the library the return type was not specified so was taken to be the general type optional any, meaning any value, including nothing, could be returned. We want to ensure the SayHello handler always returns a string so change the handler definition to specify String as the return type. public handler sayHello() returns String … handler code end handler
  65. 65. #LiveCodeGlobal Adding a typed variable To ensure we return a String from the SayHello handler we will also update the handler code to store the message in a String variable and return the value of the variable. Update the SayHello handler with: 1. String variable declaration. 2. Command to update the value of the variable with the “Hello World!” message. 3. Return statement returning the value of the String variable. public handler sayHello() returns String variable tMessage as String put "Hello World!" into tMessage return tMessage end handler
  66. 66. #LiveCodeGlobal Test that your library compiles and behaves correctly. 1. Open the Extension Builder. 2. Load the updated LiveCode Builder file. 3. Click the Uninstall button to uninstall the previous version. 4. Click the Test button. 5. Execute put sayHello() in the Message Box. The string returned by the library is displayed in the Message Box. Testing the Extended Library
  67. 67. #LiveCodeGlobal Passing parameters to a library handler In many cases you will want to use parameters in your library handlers. Handler definitions have the form <HandlerType> handler <HandlerName>(<ParameterList>) [ returns <ReturnType> ] end handlerName The parameter list is a comma separated list of parameters, each of which has the form ( 'in' | 'out' | 'inout' ) <ParameterName> [ 'as' <ParameterType>] The type of parameter is optional, if no type is specified it is taken to be optional any meaning it can be of any type.
  68. 68. #LiveCodeGlobal Passing parameters to a library handler The parameter list describes the parameters which can be passed to the handler. Handlers must be called with the correct number of parameters. An in parameter means that the value from the caller is copied to the parameter variable in the callee handler. An out parameter means that no value is copied from the caller, and the value on exit of the callee handler is copied back to the caller on return. An inout parameter means that the value from the caller is copied to the parameter variable in the callee handler on entry, and copied back out again on exit. The type of parameter is optional, if no type is specified it is taken to be optional any meaning it can be of any type.
  69. 69. #LiveCodeGlobal Adding a parameter to the sayHello handler We want to update the SayHello handler to take a pName parameter, passed in when SayHello is called from LiveCode Script. The pName parameter will be a String value, which we will use to construct and return a custom “Hello” string.
  70. 70. #LiveCodeGlobal Adding a parameter We will ● Update the handler definition with an in String parameter, pName. ● Construct the string to be returned using the pName parameter. ● Return the constructed string. Constructing a string in LCB uses the same syntax as LCS ● & - concatenates 2 strings ● && - concatenates 2 strings with a space in between public handler SayHello(in pName as String) returns String variable tMessage as String put "Hello" && pName & "!" into tMessage return tMessage end handler
  71. 71. #LiveCodeGlobal Test that your library compiles and behaves correctly. 1. Open the Extension Builder. 2. Load the updated LCB file. 3. Click the Test button. 4. Execute put SayHello(“Elanor”) in the Message Box. The returned String, containing the passed String, is displayed in the Message Box. Testing the parameter passing
  72. 72. #LiveCodeGlobal Using lists in the library It will often be useful to return more that a single piece of data from a library handler. Next we will update the SayHello handler to take a string containing a comma separated list of names, and return a LCB list with an element containing a “Hello” message for each name passed in.
  73. 73. #LiveCodeGlobal Updating the return type The first step is to update the SayHello handler definition. We will be returning a List rather than a String so update the return type. We also want to be able to pass more than one name in so update the parameter name to pNames. public handler sayHello(in pNames as String) returns List … widget code end handler
  74. 74. #LiveCodeGlobal Defining variables We will be using 3 variables in the handler ● tNameList - a list variable created from the pNames parameter ● tMessage - the list variable that will be returned, with an element holding a message for each name passed in in pNames ● tElement - a string variable used to iterate over the elements of tNameList Add variable definitions for these 3 variables. public handler sayHello(in pNames as String) returns List variable tNameList as List variable tMessage as List variable tElement as String end handler
  75. 75. #LiveCodeGlobal Creating a List from a String We want to convert the String parameter into a List. We can do this using the split statement, which splits the string into a list of strings, using the specified delimiter. We know the pNames parameter is a command separated list of names so we split pNames by comma to create a List variable. public handler sayHello(in pNames as String) returns List variable tNameList as List variable tMessage as List variable tElement as String split pNames by "," into tNameList end handler
  76. 76. #LiveCodeGlobal Building a List Next we want to create a list of messages, with an element for each name. ● Loop over each element in tNameList ● Construct a “Hello” message using the current element ● Append it to the end of the list using the push statement. ● Return the list of messages Note: When a value is pushed onto a list the pushed value becomes the tail of the list, by default. Use the 'front of' variant to push onto the front of a list instead. public handler sayHello(in pNames as String) returns List variable tNameList as List variable tMessage as List variable tElement as String split pNames by "," into tNameList repeat for each element tElement in tNameList push ("Hello" && tElement & "!") onto tMessage end repeat return tMessage end handler
  77. 77. #LiveCodeGlobal Compile the library using the Extension Builder. ● Open the Extension Builder from the Tools menu. ● Load the helloWorldLibary.lcb file ● Click Test. ● This will load the library and create a test stack. ● Add a button to the test stack. ● Set the code of the button to on mouseUp put sayHello("Adam,Brenda,Craig") into tArray end mouseUp ● Add a breakpoint to line 3 line so you can view the array in the Variable Watcher Testing the library Note: Remember that LCB lists are converted to numerically keyed arrays in LiveCode Script.
  78. 78. #LiveCodeGlobal Documenting the Library Extensions can provide an API (Dictionary) and User Guide as part of the installed package. They are installed and viewable through the LiveCode Dictionary stack. Any extension can include an API. To do so, either add a file called api.lcdoc to your widget folder alongside the other widget files or markup your source code inline. The api.lcdoc file must be in the lcdoc format. For a full description of the lcdoc format see the Contributing to LiveCode Documentation guide.
  79. 79. #LiveCodeGlobal Marking up your code In this example we will document the library using inline code comments. Marking up your scripts is simple and follows a similar model to other documentation formats. Consider the following handler: public handler myHandler(in pString as String, in pNumber as Number) end handler To add an entry to the API for this handler, place a formatted comment above the handler definition: /** summary: Use this handler to do an action pString: This parameter does x pNumber: This parameter does y description: # Markdown Title Here is a full description in markdown for how this function works. Once again, any GitHub flavoured markdown is accepted. **/ public handler MyHandler(in pString as String, in pNumber as Number) end handler
  80. 80. #LiveCodeGlobal Documenting SayHello We want to markup the source code of the Hello World library by adding inline documentation to the SayHello handler. ● The documentation is enclosed within /** and **/ ● Add a summary ● Add a description of the pNames parameter ● Add a description of the return value ● Add a full description of how the handler works. library community.livecode.elanorb.helloWorld metadata version is "1.0.0" metadata author is "Elanor Buchanan" metadata title is "Hello World Library" /** Summary: Constructs and returns a list of Hello messages pNames: String containing a comma separated list of names Returns: List of Hello strings Description: Takes a comma separated String of names, converts the String to a List, constructs a Hello message for each name and returns the List of Hello messages. **/ public handler SayHello(in pNames as String) returns List … handler code end handler end library
  81. 81. #LiveCodeGlobal Browse the Documentation in the Dictionary Now we have added documentation to the library we can view it in the Dictionary Stack. Extension documentation only shows once the extension is fully installed. ● Open the Extension Builder. ● Load the Hello World Library. ● Click Install.
  82. 82. #LiveCodeGlobal Browse the Documentation in the Dictionary Now open the Dictionary Stack and go to the API tab. Open the Drop Down list, you should see “Hello World Library”, or the title you gave your library, in the list. Select the library and you will see the documentation you added to the source file displayed.
  83. 83. #LiveCodeGlobal Congratulations You have completed this lesson, you can now ● Use explicit typing ● Perform type conversion ● Use LCB lists and arrays ● Pass parameters to library handlers ● Add documentation to libraries
  84. 84. #LiveCodeGlobal Widget Course Extending LiveCode With Widgets and Libraries LiveCode Dev Team
  85. 85. #LiveCodeGlobal The Rotated Text Widget
  86. 86. #LiveCodeGlobal The Rotated Text Widget The second type of extension that that be created is a widget. A widget is a custom control that is treated as an engine level element. Widgets appear in the Tools Palette and can be added as controls to any LiveCode stack. The Rotated Text Widget displays text and allows the user to set the rotation property of the widget. We will ● Define the widget. ● Define properties for the widget. ● Draw the widget using LCB canvas operations. ● Compile and test the widget. ● Install the widget into LiveCode. ● Add the widget to a stack. ● Include the widget in a standalone.
  87. 87. #LiveCodeGlobal What is a Canvas? A canvas is a container that holds various drawing elements (lines, shapes, text, frames containing other elements, etc.). It takes its name from the canvas used in visual arts. The main difference between a library and an extension is that a widget draws itself to the canvas, providing a UI element for the extension. Advantages Widgets have a number of advantages over traditional custom controls, created using LiveCode groups ● Once built the widget it is an atomic control. ● Widgets are more efficient. ● Widgets are not affected by engine messages. ● Widgets can be easily updated by updating the extension without having to replace the controls on the stacks.
  88. 88. #LiveCodeGlobal Creating a LiveCode Builder Widget Just like libraries widgets are written in a text editor. Start by creating a plain text file in a new directory and save it to disk with the extension ".lcb". I am naming my file "rotatedText.lcb" but you can name your file anything suitable. Note: The extension builder currently relies on there being only one .lcb file in a given directory, this is why we create a separate folder for each new extension.
  89. 89. #LiveCodeGlobal The first thing we need to do is declare the type of extension we are writing. We are writing a widget so we need to declare the extension as such. The widget declaration is followed by an identifier. An extension identifier should be in the form community.livecode.<user name>.<widget name> In my case my username is "elanorb" and I have chosen to use "rotatedtext" as the name part of the identifier. For more on module naming see the Naming section of the LiveCode Builder Style Guide, accessible from the Dictionary stack or the Additional Resources section of this course. LCB widget definition widget community.livecode.elanorb.rotatedtext end widget
  90. 90. #LiveCodeGlobal As with an LCB library, widgets also require metadata. The required metadata for widgets is the same as for libraries ● title ● author ● version You can also include an optional description. Add the widget metadata to the definition. Widget metadata widget community.livecode.elanorb.rotatedtext metadata title is "Rotated Text" metadata author is "Elanor Buchanan" metadata version is "1.0.0" end widget
  91. 91. #LiveCodeGlobal The LiveCode builder syntax is broken down into modules. Each module contains the syntax for a particular part of LiveCode Builder. You include the modules that provide the syntax for the features your extension requires. There are 3 classes of module: Type Description Default These modules are part of LiveCode builder and are included by default. Their syntax is always available to you as a LiveCode developer. Optional These modules are created and distributed by LiveCode Ltd and must be imported by the extension developer in order to make use of their syntax. Custom These modules are created and distributed through the online portal and must be imported by the extension developer in order to make use of their syntax. For a full list of modules see the Importing Libraries section of the Extending LiveCode Guide and the API entries for the individual modules. The guide can be found under the Guides tab of the Dictionary or in the Additional Resources section of the course. LCB modules
  92. 92. #LiveCodeGlobal As a general rule we recommend importing all three optional modules and the Widget Utilities library whenever developing widgets. Include the 3 modules and 1 library using the use keyword, followed by the module or library extension. Including modules widget community.livecode.elanorb.rotatedtext use com.livecode.canvas use com.livecode.widget use com.livecode.engine use com.livecode.library.widgetutils metadata title is "Rotated Text" metadata author is "Elanor Buchanan" metadata version is "1.0.0" end widget
  93. 93. #LiveCodeGlobal Module level variables A variable definition defines a module-scope variable. In a widget module, such variables are per-widget (i.e. instance variables). In a library module, there is only a single instance (i.e. a private global variable). Module-scope variables in LCB are similar to script local variables in LiveCode Script. The syntax for declaring variables is variable <variableName> [as <type>] The type specification for the variable is optional, if it is not specified the type of the variable is optional any meaning that it can hold any value, including being nothing. Variables whose type has a default value are initialized to that value at the point of definition. For a list of default values see the Variables section of the LiveCode Builder Language Reference Guide. The guide can be found under the Guides tab of the Dictionary or in the Additional Resources section of the course. Variables whose type do not have a default value will remain unassigned and it is a checked runtime error to fetch from such variables until they are assigned a value.
  94. 94. #LiveCodeGlobal Variable declarations In this widget we will use one module level variable to store the value of the rotation property of the widget. The value of the rotation property must be a number so we define the type as such. The variable will be a module level instance variable, so we prepend the variable name with a lower case ‘m’ to make it easily identifiable as such. Add the variable definition to the widget code. widget community.livecode.elanorb.rotatedtext use com.livecode.canvas use com.livecode.widget use com.livecode.engine use com.livecode.library.widgetutils metadata title is "Rotated Text" metadata author is "Elanor Buchanan" metadata version is "1.0.0" variable mRotation as Number end widget
  95. 95. #LiveCodeGlobal Defining widget properties Property definitions can only appear in widget modules. They define a property which can be accessed from LiveCode Script in the usual way (e.g. the myProperty of widget 1). The syntax for declaring properties is property <propertyName> get <getterIdentifier> [ set <setterIdentifier> ] The getterIdentifier and setterIdentifier can use either a variable or handler identifier. If a variable identifier is used, then the property value is fetched (and stored) from that variable. If a handler identifier is used then a handler is called instead. A getter handler must take no arguments and return a value. A setter handler must take a single argument and return no value. The set clause is optional. If it is not present then the property is read-only. Note: The Extension Builder will report an error if a setter or getter handler that is used in a property definition is not defined in the module file.
  96. 96. #LiveCodeGlobal The rotation property widget community.livecode.elanorb.rotatedtext use com.livecode.canvas use com.livecode.widget use com.livecode.engine use com.livecode.library.widgetutils metadata title is "Rotated Text" metadata author is "Elanor Buchanan" metadata version is "1.0.0" private variable mRotation as Number property "rotation" get mRotation set setRotation end widget The widget will only have one property, rotation. The value of the rotation property will be stored in the mRotation variable. The getter The getter for the rotation property will return the value of mRotation. The setter The setter for the rotation property will call a handler, setRotation. Implementing the "setter" ourselves provides us with a little more flexibility and allows us to take multiple actions when the property is set. Add the property definition to the widget code.
  97. 97. #LiveCodeGlobal widget community.livecode.elanorb.rotatedtext … previous code public handler setRotation(in pRotation as Number) returns nothing put pRotation into mRotation redraw all end handler end widget The setRotation handler allows us to take multiple actions when the property is updated ● The in parameter is a number. ● The handler does not return a value. 1. Update mRotation with the new value. 2. Redraw the widget to reflect the property change. We do this by calling "redraw all". Add the setRotation handler to the widget code. The setRotation handler
  98. 98. #LiveCodeGlobal The Property Inspector Any properties that are defined in the widget are automatically shown in the Basic pane of the Property Inspector. We will be looking at integrating properties into the Property Inspector in more detail in the next lesson.
  99. 99. #LiveCodeGlobal Widget Handlers There are five core handlers that any widget developer should implement: Handler Description OnPaint Sent to your widget whenever LiveCode requires it to redraw. The performance of your widget is tied primarily to this handler and should be kept as efficient as possible. OnCreate Sent to your widget when it is first created by LiveCode. This can be used to initialise default data and where applicable, reduce the burden for calculating constants etc in the OnPaint handler. OnGeometryChanged Sent when the control is changed in size. OnSave Sent when your widget is about to be destroyed and enables the widget to save data set on the widget. OnLoad Sent when your widget is created and enables the widget to retrieve data saved on the widget.
  100. 100. #LiveCodeGlobal The OnPaint handler This widget is very simple so only the OnPaint handler is required to draw the widget. The OnPaint handler will be a public handler which takes no parameters and does not return a value. Add the OnPaint definition to the widget code. public handler OnPaint() end handler
  101. 101. #LiveCodeGlobal The OnPaint handler width heightLiveCode There are a number of steps to take in the OnPaint handler. The first step is to draw the unrotated text in the widget. 1. Work out the size of the widget by getting its width and height 2. Work out the rectangle of the area we have to draw into 3. Draw the text at the center of the available space
  102. 102. #LiveCodeGlobal public handler OnPaint() variable tText as String variable tHeight as Number variable tWidth as Number put my width into tWidth put my height into tHeight put "LiveCode" into tText variable tRectangle as Rectangle put rectangle [0,0,tWidth,tHeight] into tRectangle fill text tText at center of tRectangle on this canvas end handler Drawing the text For the basic widget we will use “LiveCode” as the text. 1. Declare variables for the text to be displayed and the height and width of the canvas. 2. Update the variables with the relevant values. 3. Declare a rectangle variable. 4. Put the rectangle describing the area of the canvas into the rectangle variable. 5. Draw the text in the center of the canvas.
  103. 103. #LiveCodeGlobal my width: Returns the width of the widget. my height:Returns the height of the widget. rectangle: Specifies an area, consists of a list of 4 integers left, top, right, bottom Example: put rectangle [0,0,tWidth,tHeight] into tRectangle fill text at: Renders text on a canvas Syntax: fill text mText at mAlignment of mRect on mCanvas Example: fill text "Widget Label" at top left of rectangle [50, 100, 250, 200] on this canvas For more on each of these keywords see the API entries in the LiveCode Dictionary. Search for “com.livecode.canvas” in the LiveCode Builder API to see all the associated API entries. Drawing the text
  104. 104. #LiveCodeGlobal Rotating text To draw rotated text we 1. Rotate the canvas 2. Get the rectangle of the rotated canvas as a path 3. Rotate the path back 4. Get the rectangle of the un-rotated path 5. Draw the text within the un-rotated rectangle. This draws the text horizontally, but relative to the position of the canvas. Because the canvas is rotated the text also appears rotated.
  105. 105. #LiveCodeGlobal Key Concept: Rectangle Path Syntax: rectangle path of mRect Summary: Creates a new path. Parameters: mRect: An expression which evaluates to a rectangle. Example: // Create a rectangle path variable tPath as Path put rectangle path of rectangle [10,10,210,60] into tPath
  106. 106. #LiveCodeGlobal Key Concept: Bounding Box Syntax: the bounding box of mPath Summary: The bounding box of a path which is the smallest rectangle that completely encloses mPath. Parameters: mPath: An expression which evaluates to a path. Example: // Create a circle path variable tPath as Path put circle path centered at point [100,100] with radius 50 into tPath // Get the bounds of the path variable tBounds as Rectangle put the bounding box of tPath into tBounds
  107. 107. #LiveCodeGlobal public handler OnPaint() variable tText as String variable tHeight as Real variable tWidth as Real put my width into tWidth put my height into tHeight put "LiveCode" into tText rotate this canvas by mRotation variable tRectangle as Rectangle variable tPath as Path put rectangle path of rectangle [0,0,tWidth,tHeight] into tPath rotate tPath by (mRotation * -1) put the bounding box of tPath into tRectangle fill text tText at center of tRectangle on this canvas end handler Drawing rotated text 1. Rotate the canvas by the value stored in the mRotation variable. 2. Declare a path variable tPath. 3. Put the rectangle path of the canvas into tPath. 4. Rotate the path by -mRotation, setting it to a horizontal rectangle. 5. Update the line that sets tRectangle to get the bounding box of the un-rotated path and put it into the tRectangle variable. This gives the rectangle that completely encloses the un-rotated the path in tPath. 6. Draw the text at the center of the rectangle given by tRectangle. The text in drawn in a horizontal rectangle, but relative to the canvas, so appears drawn on an angle.
  108. 108. #LiveCodeGlobal Testing the widget Now we have completed the OnPaint handler we are ready to test the widget. This is the full code of the widget, so far. widget community.livecode.elanorb.rotatedtext use com.livecode.canvas use com.livecode.widget use com.livecode.engine use com.livecode.library.widgetutils metadata title is "Rotated Text" metadata author is "Elanor Buchanan" metadata version is "1.0.0" private variable mRotation as Number property "rotation" get mRotation set setRotation public handler setRotation(in pRotation as Number) returns nothing put pRotation into mRotation redraw all end handler … continued on next slide
  109. 109. #LiveCodeGlobal Testing the widget Now we have completed the OnPaint handler we are ready to test the widget. This is the full code of the widget, so far. public handler OnPaint() variable tText as String variable tHeight as Real variable tWidth as Real put my width into tWidth put my height into tHeight put "LiveCode" into tText rotate this canvas by mRotation variable tRectangle as Rectangle variable tPath as Path put rectangle path of rectangle [0,0,tWidth,tHeight] into tPath rotate tPath by (mRotation * -1) put rectangle [0,0,tWidth,tHeight] into tRectangle put the bounding box of tPath into tRectangle fill text tText at center of tRectangle on this canvas end handler end widget
  110. 110. #LiveCodeGlobal Testing the widget Just like a library we compile, test, package and install widgets using the Extension Builder. 1. Open the Extension Builder from the Tools menu 2. Click the Open button 3. Load the ‘rotatedtext.lcb’ file
  111. 111. #LiveCodeGlobal Testing the widget To test the widget click the Test button. This will create a stack in the IDE with a Rotated Test widget on it. 1. Go into Edit mode. 2. Select the widget. 3. Open the Property Inspector. 4. Set the Rotation property.
  112. 112. #LiveCodeGlobal Widget icons When a widget is installed it shows in the Tools Palette. To provide an icon for the widget you add image files to the folder containing the widget definition .lcb file. Open the folder containing the LCB file ● Create a “support” folder ● Add 2 image files ○ Icon.png (20 x 20) ○ icon@extrahigh.png (40x40) The icon files can be found under the Resources tab of this lesson.
  113. 113. #LiveCodeGlobal Installing a widget To install a widget we use the Extension Builder. 1. Open the Extension Builder from the Tools Palette. 2. Select the Open button. 3. Load the ‘rotatedtext.lcb’ file. 4. Click Install. The widget will be installed and will appear in the Tools Palette.
  114. 114. #LiveCodeGlobal Creating a widget You can now add the widget to a stack by dragging it out from the Tools Palette. 1. Create a new stack. 2. Drag on a Rotated Text Widget. 3. Go into Edit mode. 4. Select the widget. 5. Open the Property Inspector for the widget. 6. Set the Rotation property on the widget.
  115. 115. #LiveCodeGlobal Including the Widget in a Standalone When building a standalone that includes a widget you need to ensure that the widget is included when the standalone is built. Open the Standalone Application Settings from the File menu. On the General Pane you can choose to let LiveCode search for inclusions (libraries and widgets) or select any inclusions manually.
  116. 116. #LiveCodeGlobal Selecting inclusions If you choose to select the extensions to include yourself the Inclusions pane will be enabled. Go to the Inclusions pane and check the extensions you want to include in the standalone. In this case we want to include the Rotated Text widget so check it in the list.
  117. 117. #LiveCodeGlobal Saving the standalone Choose File -> Save as Standalone Application to save the stack as a standalone. Start up the standalone and check that the widget is included and the rotation can be set.
  118. 118. #LiveCodeGlobal Congratulations You have completed this lesson, you can now ● Create a LiveCode Builder widget. ● Package and install a widget into LiveCode. ● Include the widget in a standalone.
  119. 119. #LiveCodeGlobal Widget Course Extending LiveCode with Widgets and Libraries LiveCode Dev Team
  120. 120. #LiveCodeGlobal The Advanced Rotated Text Widget
  121. 121. #LiveCodeGlobal The Advanced Rotated Text Widget In this lesson we will take the Rotated Text Widget to the next level. We will ● Fully integrate widget properties into the Property Inspector ● Add color and font properties by shadowing standard LiveCode properties ● Handle mouse events to make the widget clickable ● Add handlers to load and save widgets ● Add read only properties to a widget ● Document the widget
  122. 122. #LiveCodeGlobal Widget properties In Lesson 3 we defined the rotation property of the widget property "rotation" get mRotation set setRotation ● Properties are shown in the Basic pane of the Property Inspector ● The name of the property is shown as the label in the Property Inspector ● A standard editor is shown for the property
  123. 123. #LiveCodeGlobal You can more fully define widget properties in the LCB source file using metadata. All property metadata is optional. Property metadata definitions have the format metadata <property name>.<metadata name> is <value> You can define ● Property label ● Editor type ● Editor specific metadata ● Default value ● Property Inspector Section ● Property group ● User visible ● Read only For more on property metadata see Property Definitions Read Me. Widget properties
  124. 124. #LiveCodeGlobal Property metadata Add the metadata for the rotation property to the widget source file. ● label: the label to be shown in the Property Inspector ● editor: the type of editor to be used in the Property Inspector ● default: the default value of the property Editor specific metadata ● step: the step value for number properties ● min: the minimum value for a number property ● max: the maximum value for a number property We want this property to appear in the Basic section so do not specify a section. widget community.livecode.elanorb.rotatedtext … widget inclusions and metadata private variable mRotation as Number property "rotation" get mRotation set setRotation metadata rotation.label is "Rotation" metadata rotation.editor is "com.livecode.pi.number" metadata rotation.default is "0" metadata rotation.step is "1" metadata rotation.min is "0" metadata rotation.max is "359" … widget handlers end widget
  125. 125. #LiveCodeGlobal Test in the Property Inspector To see the property integrated into the Property Inspector, using the metadata, rebuild the widget. ● Open the Extension Builder from the Tools menu ● Load the widget source file ● Click the Test button ● Select the widget on the test stack ● Open the Property Inspector You should see the rotation property, with a number property editor that will not allow values outside the range 0-360.
  126. 126. #LiveCodeGlobal The Content property We will add a second property, content, which allows the user to change the text displayed in the widget. ● Define a variable to store the property value ● Define the property, getter and setter ● Add metadata for the property ○ editor ○ default ○ label widget community.livecode.elanorb.rotatedtext … widget inclusions and metatdata … rotation property definition private variable mContent as String property "content" get mContent set setContent metadata content.editor is "com.livecode.pi.string" metadata content.default is "Default text" metadata content.label is "Content" … widget handlers end widget
  127. 127. #LiveCodeGlobal Add the content property setter handler. ● Takes a string parameter ● Has no return value ● Update the mContent variable with the parameter value ● Redraw the widget with the new text The setContent handler widget community.livecode.elanorb.rotatedtext … widget inclusions and metatdata … property definitions … OnPaint handler … SetRotation handler public handler SetContent(in pText as String) returns nothing put pText into mContent redraw all end handler end widget
  128. 128. #LiveCodeGlobal Update OnPaint The OnPaint() handler needs updated to use the value of the content property. ● Delete the declaration for the tText variable ● Delete the line where “LiveCode” is put into the tText variable ● Update the “fill text” line to use the mContent variable public handler OnPaint() variable tText as String variable tHeight as Real variable tWidth as Real put my width into tWidth put my height into tHeight put "LiveCode" into tText rotate this canvas by mRotation variable tRectangle as Rectangle variable tPath as Path put rectangle path of rectangle [0,0,tWidth,tHeight] into tPath rotate tPath by (mRotation * -1) put the bounding box of tPath into tRectangle fill text tText at center of tRectangle on this canvas fill text mContent at center of tRectangle on this canvas end handler
  129. 129. #LiveCodeGlobal When a widget is created the default values for its properties should be used. The OnCreate handler is called when the widget is first created. To ensure the values of the rotation and content properties are set we add the OnCreate handler which will call the property setters with the default values. ● Set the default value of the content property to “Default text” ● Set the default value of the rotation property to 0 The OnCreate handler widget community.livecode.elanorb.rotatedtext … widget inclusions and metadata … property definitions … OnPaint handler public handler OnCreate() setContent("Default text") setRotation(0) end handler … Property setters end widget
  130. 130. #LiveCodeGlobal Test the widget Now build and test your widget using the Extension Builder. You should see the Content property in the Property Inspector and be able to change the text displayed in the widget.
  131. 131. #LiveCodeGlobal In addition to adding widget specific properties you can also link your widget to standard LiveCode control properties, such as font, background color etc. All controls in LiveCode, both widgets and classic controls, have a set of basic properties which are always present and do not need to be implemented when writing a widget. Any widget you create will always have these properties in its Property Inspector. These properties are You can also choose to allow your widget to implement any other LiveCode control properties which are not in the basic set. Basic name, kind, tooltip, visible, disabled Custom properties custom properties and custom property sets Colors ink, blendLevel Position lockLoc, width, height, location, left, top, right, bottom, layer Text textFont, textSize Advanced layerMode, behavior, traversalOn, number Shadowing LiveCode control properties
  132. 132. #LiveCodeGlobal Accessing standard properties Although all controls, including widgets, have all the basic properties some work automatically and you need to take some into account when you draw the widget. For example the width property works automatically but the text size requires some extra handling.
  133. 133. #LiveCodeGlobal Text properties The two basic text properties all controls have are ● Text font ● Text size We want to use the values of these properties when drawing the widget. We get the effective text properties of the widget using my font and apply these settings when drawing the widget. Update the OnPaint handler to apply these settings to the canvas before rotating the canvas. public handler OnPaint() … variable declarations … tWidth and tHeight values set the font of this canvas to my font rotate this canvas by mRotation … remainder of code end handler
  134. 134. #LiveCodeGlobal Test the text properties To test the text properties in the Property Inspector re-compile the widget using the Extension Builder. ● Select the widget on the test stack ● Open the Property Inspector ● Go to the Text section ● Set the Font and Text size The text in the widget should change to reflect the property values.
  135. 135. #LiveCodeGlobal Linking to other LiveCode properties You can also link to other standard LiveCode properties beyond the basic, built in set. For example we might want to set the Text fill of the Rotated Text Widget. Text fill, or foregroundColor to use the property name, is a standard LiveCode property but it not part of the basic set. To access it we have to specify that the widget has the property, but we do not have to define the property itself.
  136. 136. #LiveCodeGlobal Linking to other LiveCode properties Below is a list of the LiveCode properties you can link to as described. abbrevId, abbrevName, abbrevOwner, altId, backColor, backPattern, backPixel, blendLevel, borderColor, borderPattern, borderPixel, bottom, bottomColor, bottomLeft, bottomPattern, bottomPixel, bottomRight, brushColor, cantSelect, colors, customKeys, customProperties, customPropertySet, customPropertySets, disabled, enabled, focusColor, focusPattern, focusPixel, foreColor, forePattern, forePixel, height, hiliteColor, hilitePattern, hilitePixel, ink, invisible, kind, layer, layerMode, left, location, lockLocation, longId, longName, longOwner, name, number, owner, parentScript, patterns, penColor, properties, rectangle, right, script, selected, shadowColor, shadowPattern, shadowPixel, shortId, shortName, shortOwner, textFont, textSize, textStyle, themeControlType, toolTip, top, topColor, topLeft, topPattern, topPixel, topRight, traversalOn, unicodeToolTip, visible, width
  137. 137. #LiveCodeGlobal Metadata for LiveCode properties To define a LiveCode property in a widget you provide metadata, but do not need to define the property within the widget. We want to the Rotated Text Widget to have the foregroundColor property, and for it to be settable in the Property Inspector. Add the metadata for the property. ● Use a color editor in the Property Inspector ● Setting the default to empty means the value will be inherited ● Show in the Colors section of the Property Inspector ● Set the label to “Text Fill” widget community.livecode.elanorb.rotatedtext … widget inclusions and metadata … property definitions for rotation and content metadata foregroundColor.editor is "com.livecode.pi.color" metadata foregroundColor.default is "" metadata foregroundColor.section is "Colors" metadata foregroundColor.label is "Text fill" … widget handlers end widget
  138. 138. #LiveCodeGlobal Update OnPaint We now need to update the OnPaint handler to use the selected foregroundColor when drawing the text to the canvas. ● my foreground paint - returns the effective foreground color of the widget. This value is either inherited, set in code or set in the Property Inspector ● set the paint of this canvas - sets the color to be used when drawing to the canvas public handler OnPaint() … variable declarations set the font of this canvas to my font set the paint of this canvas to my foreground paint … code continues end handler
  139. 139. #LiveCodeGlobal Test the Text Fill property Compile and test the widget using the Extension Builder. ● Go into Edit mode ● Select the widget in the test stack ● Open the Property Inspector ● Go to the Colors pane ● Change the Text fill
  140. 140. #LiveCodeGlobal Handling mouse events You will often want to create widgets that can respond to user actions. LCB provides a range of messages, similar to LiveCode event messages, some examples are ● OnMouseDown ● OnMouseUp ● OnDoubleClick ● OnKeyPress You can choose which of these messages your widget will handle and how to handle them. Note that the event names are all one word, e.g. OnMouseUp, unlike LCS. You can can also post messages to the widget object in LiveCode, these can be standard messages such as mouseUp or customised messages, such as segmentClicked in a Pie Chart widget. As with widget handlers we use TitleCase for event names.
  141. 141. #LiveCodeGlobal Handling mouseUp When the widget is clicked we want it to get a mouseUp message, just like a button or graphic control. To do this we handle the LCB OnMouseUp message and post a mouseUp message to the widget object. Add the OnMouseUp handler to the widget code. Note: Properties and events are, by their nature, always public as they define things which are external to the widget. widget community.livecode.elanorb.rotatedtext … widget inclusions and metadata … property definitions … OnPaint and OnCreate handlers … Property Setters public handler OnMouseUp() post "mouseUp" end handler end widget
  142. 142. #LiveCodeGlobal Compile and test the widget using the Extension Builder. ● Go into Edit mode ● Select the widget on the test stack ● Open the Code editor for the widget on mouseUp answer "mouseUp received" end mouseUp ● Go into Run mode ● Click the widget ● The widget will respond to the mouse click Testing mouseUp
  143. 143. #LiveCodeGlobal You can post any message to the widget object, not just LiveCode messages. For example if you want the Rotated Text Widget to receive a rotatedTextClicked message instead of a mouseUp message when it is clicked you would post “rotatedTextClicked”. public handler OnMouseUp() post "rotatedTextClicked" end handler Custom messages
  144. 144. #LiveCodeGlobal Creating, saving and loading widgets In Lesson 3 we looked at the core handlers but so far we have only implemented the OnPaint and OnCreate handlers. In this lesson we will implement the OnSave and OnLoad handlers. Handler Description OnSave Sent when your widget is about to be destroyed and enables the widget to save data set on the widget. OnLoad Sent when your widget is created and enables the widget to retrieve data saved on the widget.
  145. 145. #LiveCodeGlobal We want to be able to save and load the widget’s properties. If the OnSave and OnLoad handlers are not included then every time you open a saved stack that includes a widget, the widget will lose its property data and the properties will be set to the default values. When your widget is saved you are sent an OnSave message. It returns an array which you can fill with whatever widget data you have. LiveCode saves this data along with instances of the widget in the stack file. This same array will be returned to you as a parameter to the the OnLoad message, which is sent when the widget is next opened and can be used to recreate the widget with its saved properties. Saving and loading the widget state
  146. 146. #LiveCodeGlobal The OnSave handler First we write the OnSave handler, which saves the widget’s properties when a stack containing a widget is saved. Add the OnSave handler to the widget code. The rProperties array is an out parameter meaning the value of the array is copied back to the caller when the handler completes. Add an element to the rProperties array for each property ● key: property name ● value: property value Note: LiveCode properties are automatically saved so don’t need to be explicitly stored in the array. widget community.livecode.elanorb.rotatedtext … widget inclusions and metadata … property definitions … OnPaint and OnCreate handlers … Property Setters … Event handlers public handler OnSave(out rProperties as Array) put mContent into rProperties["content"] put mRotation into rProperties["rotation"] end handler end widget
  147. 147. #LiveCodeGlobal The OnLoad handler Next we write the OnLoad handler, which loads the widget’s properties when a stack containing a widget is opened: Add the OnLoad handler to the widget code. The array of saved properties is passed in as a parameter, and can be used to set the values of the private instance variables to the stored property values. ● Set the value of the content property to the value of the content element in the properties array ● Set the value of the rotation property to the value of the rotation element in the properties array widget community.livecode.elanorb.rotatedtext … widget inclusions and metadata … property definitions … OnPaint and OnCreate handlers … Property Setters … Event handlers … OnSave handler public handler OnLoad(in pProperties as Array) put pProperties["content"] into mContent put pProperties["rotation"] into mRotation end handler end widget
  148. 148. #LiveCodeGlobal Testing saving and loading a widget In order to test saving and loading a widget we have to install the widget. ● Open the Extension Builder from the Tools Palette ● Load the lcb file ● Uninstall the previous widget, if necessary ● Click Install ● The widget will appear in the Tools Palette ● Create a new stack ● Drag on a Rotated Text Widget ● Set some properties ● Save the stack ● Close LiveCode ● Reopen the stack The widget should appear with its properties set to the saved state.
  149. 149. #LiveCodeGlobal Read only properties So far we have only looked at properties that can be set by the user. In this lesson we will implement some read-only properties that depend entirely on the widget state. These properties will be familiar to anyone experienced with LiveCode Script. ● formattedWidth - Reports the width needed by an object to display its full contents without scrolling. This property is read-only and cannot be set. ● formattedHeight - Reports the height needed by an object to display its full contents without scrolling. This property is read-only and cannot be set. We will implement these two properties for the Rotated Text widget by calculating the space the text displayed in the widget requires and returning these values.
  150. 150. #LiveCodeGlobal Declare the properties Firstly declare the properties in the widget source code. Add two instance variables to hold the property values and add definitions for the formattedWidth and formattedHeight properties. Because the properties are read only they do not require setter identifiers. The getter simply returns the value of the variable. widget community.livecode.elanorb.rotatedtext … widget inclusions and metadata … existing property definitions private variable mFormattedWidth as Real private variable mFormattedHeight as Real property "formattedWidth" get mFormattedWidth property "formattedHeight" get mFormattedHeight … OnPaint and OnCreate handlers … Property Setters … Event handlers .... OnSave and OnLoad handlers end widget
  151. 151. #LiveCodeGlobal We want to update the values of the formattedWidth and formattedHeight properties whenever the state of the widget changes. This ensures the correct value will always be returned by the property. Update the OnPaint handler to calculate and store the formattedWidth and formattedHeight of the widget whenever it is redrawn. ● Declare a rectangle variable ● Get the bounds of the text on the canvas. This returns the bounding box of the text when drawn at point 0,0 as a rectangle, taking into account the font, style and text size of the canvas ● Update the variables holding the property values with the width and height of the bounding box of the text Storing the values public handler OnPaint() … previous code variable tBounds as Rectangle put the bounds of text mContent on this canvas into tBounds put the width of tBounds into mFormattedWidth put the height of tBounds into mFormattedHeight end handler
  152. 152. #LiveCodeGlobal Testing read only properties Compile and test the widget using the Extension Builder. ● Go into Edit mode ● Select the widget in the test stack ● Open the Property Inspector The formattedWidth and formattedHeight properties will be shown on the Basic pane, they can’t be edited because the are read only. You can check the width and height properties in the Position pane and see they are different values.
  153. 153. #LiveCodeGlobal Hiding properties There may be cases where your widget has properties that you do not want to show in the Property Inspector. This may be because they are read only, internal or undocumented. You can set property metadata to prevent the properties being visible to the user. Add user_visible metadata to the formattedWidth and formattedHeight properties widget community.livecode.elanorb.rotatedtext … widget inclusions and metadata … existing property definitions private variable mFormattedWidth as Real private variable mFormattedHeight as Real property "formattedWidth" get mFormattedWidth metadata formattedWidth.user_visible is "false" property "formattedHeight" get mFormattedHeight metadata formattedHeight.user_visible is "false" … OnPaint and OnCreate handlers … Property Setters … Event handlers .... OnSave and OnLoad handlers end widget
  154. 154. #LiveCodeGlobal Testing non user-visible properties Compile and test the widget using the Extension Builder. ● Go into Edit mode ● Select the widget on the test stack ● Open the Property Inspector The formattedWidth and formattedHeight properties will not be shown in the Property Inspector. However you can get the property value from code. Execute the following code in the Message Box to test the property. put the formattedHeight of widget 1
  155. 155. #LiveCodeGlobal Documenting the widget Extensions can provide an API (Dictionary) entry and User Guide as part of the installed package. They are installed and viewable through the LiveCode Dictionary stack. In Lesson 2 we documented a library extension, which involved documenting the handlers provided by the library. To document the widget we will document the properties and messages associated with the widget. As with the Hello World library, we will use in-line documentation comments in the LCB file to document the widget.
  156. 156. #LiveCodeGlobal Documenting the widget A description of the widget can be included in a comment block above the widget declaration in the LCB file. This description will appear in the Dictionary stack under the API entry for the widget identifier. Add a comment block with a description of the widget at the start of the LCB file. /** A rotated text control. The control displays text rotated to a given number of degrees, 0 degrees meaning unrotated. **/ widget community.livecode.elanorb.rotatedText … widget code end widget
  157. 157. #LiveCodeGlobal Documenting messages Widget messages are not declared explicitly in the LCB file, so all messages should be documented within the comment block that includes the widget description at the start of the LCB file. Each message has ● Name ● Type ● Syntax ● Description Add the documentation for the mouseUp message to LCB file. You can add documentation for multiple messages in this comment block. /** A rotated text control. The control displays text rotated to a given number of degrees, 0 degrees meaning unrotated. Name: mouseUp Type: message Syntax: on mouseUp Description: The <mouseUp> message is sent when the widget is clicked. **/ widget community.livecode.elanorb.rotatedText … widget code end widget
  158. 158. #LiveCodeGlobal Documenting properties When properties in LCB, the documentation is included above the property definition within a /** **/ comment block. Include ● Syntax: the syntax for using the property. This usually included a set and get example ● Summary: a brief description of the property ● Description: a more extensive description of the property, its effects and how to use it Add in-line documentation for the declared Rotated Text widget properties: rotation, content, formattedWidth and formattedHeight. /** Syntax: set the rotation of <widget> to <pDegrees> Syntax: get the rotation of <widget> Summary: The number of degrees the text displayed in the widget is rotated by. Description: Use the <rotation> property to set the amount the text displayed in the widget is rotated by. The default is 0 degrees which is unrotated, horizontal text. The text is rotated in a clockwise direction. **/ property "rotation" get mRotation set setRotation
  159. 159. #LiveCodeGlobal Documenting Properties The foregroundColor property shadows a LiveCode property and is not declared explicitly in the widget source code. Therefore the documentation must be in the top-level comment beside the message documentation. Include ● Name: the property name ● Type: “property” ● Syntax: the syntax for using the property. This usually included a set and get example ● Summary: a brief description of the property ● Description: a more extensive description of the property, its effects and how to use it /** ...widget and message documentation Name: foregroundColor Type: property Syntax: set the foregroundColor of <widget> to <pColor> Syntax: get the foregroundColor of <widget> Summary: The text color of the widget Description: Use the <foregroundColor> property to control the text color of the widget. **/ widget community.livecode.elanorb.rotatedText … widget code end widget
  160. 160. #LiveCodeGlobal Browsing the documentation Use the Extension Builder to install the widget. You can find the widget icons in the Lesson 4 Resources. You will see the Rotated Text widget in the Tools Palette. Open the Dictionary stack and select Rotated Text from the drop down menu. The documentation for the widget, message and properties will be shown in the Dictionary stack.
  161. 161. #LiveCodeGlobal Congratulations You have completed this lesson, you can now ● Fully integrate widget properties into the Property Inspector ● Shadow standard LiveCode properties ● Handle mouse events to make widgets clickable ● Save and load widget properties ● Add read only properties to a widget ● Document the widget
  162. 162. #LiveCodeGlobal Widget Course Extending LiveCode with Widgets and Libraries LiveCode Dev Team
  163. 163. #LiveCodeGlobal The Pie Chart Widget
  164. 164. #LiveCodeGlobal The Pie Chart Widget In this lesson we will plan and implement a Pie Chart widget. We will ● Decide how the Pie Chart should look ● Decide what properties the Pie Chart should have ● Decide what messages the Pie Chart should send ● Implement the Pie Chart widget in steps ○ Define the Properties ○ Implement OnCreate ○ Implement OnPaint ○ Implement OnGeometryChanged ○ Implement OnSave ○ Implement OnLoad ○ Respond to mouse events ● Document the widget ● Package and install the widget
  165. 165. #LiveCodeGlobal Pie Chart Examples Everyone is familiar with pie charts, but before we start implementing the pie chart widget we’ll look at a couple of examples. Google Docs Libre Office
  166. 166. #LiveCodeGlobal The Pie Chart information There are 2 main pieces of information required to draw the pie chart ● List of values ● Labels associated with each value In the examples we looked at, the values and labels were: Label Value January 1 February 2 March 3 April 5 May 8 June 13
  167. 167. #LiveCodeGlobal The Pie Chart layout The usual layout for pie charts is to have ● Chart on the left ● List of labels on the right Because the user can resize the widget there are some considerations for us ● Ensure the labels are shown ● Make the pie chart the maximum size while showing all the labels ● If the widget is taller than it is wide display the labels below the chart ● Allow the user to choose whether to show the labels or not, to provide flexibility within apps Aaa Bbb Ccc Aaa Bbb Ccc
  168. 168. #LiveCodeGlobal Pie Chart properties and messages Through planning our widget we have identified 3 properties the widget needs ● List of values ● List of labels ● Boolean value specifying whether the labels should be shown or not We also want the widgets to respond to user actions. We could simply provide a mouseUp message but for a pie chart this is not particularly informative. Instead a useful message would tell the user that the chart had been clicked, and which sector was clicked on. So we will send a message with a parameter ● sectorClicked pSectorNumber The colors used for sectors will be assigned by the widget. A possible extension of the widget would be to make these colors settable by the user.
  169. 169. #LiveCodeGlobal Creating the LiveCode Builder file As with the Hello World Library and Rotated Text Widget we will start a new LiveCode Builder source file. ● Create a new directory. ● Create a new plain text file in the directory and save it to disk with the extension "lcb". I am naming my file "pieChart.lcb" but you can name your file anything suitable. Note: The extension builder currently relies on there being only one .lcb file in a given directory, this is why we create a separate folder for each new extension.
  170. 170. #LiveCodeGlobal Widget definition Begin by defining the pie chart widget in the LCB file. Remember ● The widget declaration is followed by an identifier. ● An extension identifier should be in the form community.livecode.<user name>.<widget name> For more on module naming see the Naming section of the LiveCode Builder Style Guide, accessible from the Dictionary stack or the Additional Resources section of the course. widget community.livecode.elanorb.piechart end widget
  171. 171. #LiveCodeGlobal Include the recommended modules and libraries in the LCB file. ● com.livecode.canvas ● com.livecode.widget ● com.livecode.engine ● Com.livecode.library.widgetutils For a full list of modules see the Importing Libraries section of the Extending LiveCode Guide and the API entries for the individual modules. Including modules widget community.livecode.elanorb.piechart use com.livecode.canvas use com.livecode.widget use com.livecode.engine use com.livecode.library.widgetutils end widget
  172. 172. #LiveCodeGlobal Widget metadata Add the required widget metadata to the definition. ● Title ● Author ● Version number You can also include an optional metadata. We want to ensure the Pie Chart widget is created at a reasonable size so add ● Preferred size widget community.livecode.elanorb.piechart use com.livecode.canvas use com.livecode.widget use com.livecode.engine use com.livecode.library.widgetutils metadata title is "Pie Chart" metadata author is "Elanor Buchanan" metadata version is "1.0.0" metadata preferredSize is "200,150" end widget
  173. 173. #LiveCodeGlobal Variable declarations In Step 1 we identified 3 properties of the Pie Chart widget: values, labels and whether labels should be shown. In addition we want an a list variable to store the list of colors that will be used for the sectors. As before we will use module level variables to store the values of these properties. Declare the 4 variables and their types. Also add a constant, kPadding, which will be used to layout the elements of the widget. Note: See Lesson 3 - Step 3: Module level variables if you need a refresher. widget community.livecode.elanorb.piechart … module imports … metadata private variable mValues as List private variable mLabels as List private variable mColors as List private variable mShowLabels as Boolean constant kPadding is 10 end widget
  174. 174. #LiveCodeGlobal The values property will have both a getter and a setter handler. Add the definition for the property, including: ● Property name ● Getter handler name ● Setter handler name ● Default value ● Property label The values property widget community.livecode.elanorb.piechart … module imports … metadata … instance variable declarations property "sectorValues" get getValues set setValues metadata sectorValues.default is "1,2,3,5,8,13" metadata sectorValues.label is "Values" end widget
  175. 175. #LiveCodeGlobal The segmentValues property has both a getter and a setter property. The Property Inspector allows the user to set the segmentValues to a comma separated list of values. The setValues handler converts the comma separated string to a LCB list. The getValues handler converts the LCB list to a string, allowing it to be displayed in the Property Inspector. Add the handlers to the source code. The values property widget community.livecode.elanorb.piechart ...previous code public handler setValues(in pValues as String) returns nothing split pValues by "," into mValues redraw all end handler private handler getValues() returns String variable tValues combine mValues with "," into tValues return tValues end handler end widget
  176. 176. #LiveCodeGlobal The labels property will also have both a getter and a setter handler. Add the definition for the property, including: ● Property name ● Getter handler name ● Setter handler name ● Default value ● Property label The labels property widget community.livecode.elanorb.piechart … module imports … metadata … instance variable declarations … previous property definitions property "sectorLabels" get getLabels set setLabels metadata sectorLabels.default is "Jan,Feb,Mar,Apr,May,Jun" metadata sectorLabels.label is "Labels" … code continues end widget
  177. 177. #LiveCodeGlobal Like the segmentValues property the segmentLabels property has both a getter and a setter property. The Property Inspector allows the user to set the segmentLabels to a comma separated list of values. The setLabels handler converts the comma separated string to a LCB list. The labels property widget community.livecode.elanorb.piechart … previous code public handler setLabels(in pLabels as String) returns nothing split pLabels by "," into mLabels redraw all end handler private handler getLabels() returns String variable tLabels combine mLabels with "," into tLabels return tLabels end handler end widget
  178. 178. #LiveCodeGlobal The Show labels property is a boolean value so only has a setter handler. The value of the mShowLabels variable is returned when the property value is requested. Add the definition for the property, including: ● Property name ● Variable name for the get method ● Setter handler name ● Default value ● Property label The showLabels property widget community.livecode.elanorb.piechart … module imports … metadata … instance variable declarations … previous property definitions property "showLabels" get mShowLabels set setShowLabels metadata showLabels.default is "true" metadata showLabels.label is "Show labels" … code continues end widget
  179. 179. #LiveCodeGlobal The setShowLabels handler sets the value of the mShowLabels variable to the value passed in. Add the handler to the source code. The showLabels property widget community.livecode.elanorb.piechart … previous code public handler setShowLabels(in pShow as Boolean) returns nothing put pShow into mShowLabels redraw all end handler end widget
  180. 180. #LiveCodeGlobal The OnCreate handler The OnCreate handler is sent to a widget when it is first created by LiveCode. This handler can be used to initialise default data and, where applicable, reduce the burden for calculating constants etc in the OnPaint handler. Add the OnCreate handler to the LCB file ● Define a variable, tSectors, to hold the number of sectors ● Call setValues to set the default values of the mValues variable. ● Call setLabels to set the default values of the mLabels variable ● Set the value of mShowLabels to true ● Update tSectors with the number of elements in the list of values ● Call colorList to intitialise the mColors variable Setting the property values in the OnCreate handler ensures the values of the properties are set when we test from the Extension Builder. widget community.livecode.elanorb.piechart ...previous code public handler OnCreate() variable tSectors setValues("1,2,3,5,8,13") setLabels("Jan,Feb,Mar,Apr,May,Jun") put true into mShowLabels put the number of elements in mValues into tSectors put colorList(tSectors) into mColors end handler end widget
  181. 181. #LiveCodeGlobal LiveCode Builder Colors LiveCode Builder colors are expressions which evaluates to a list of 3 or 4 numbers, the red, green, blue, and (optional) alpha components of the color. The component value denotes the intensity of that component, expressed as a real number between 0 and 1. The alpha component represents the opacity of the color. If the alpha component is not specified then it is assumed to be 1 (fully opaque). variable tColor -- Set tColor to opaque red put color [1.0, 0.0, 0.0] into tColor -- Set tColor to partially transparent cyan put color [0.0, 1.0, 1.0, 0.75] into tColor
  182. 182. #LiveCodeGlobal The colorList handler Red: 1,0,0,1 Green: 0,1,0,1 Blue: 0,0,1,1 Yellow: 1,1,0,1 Purple: 1,0,1,1 Cyan: 0,1,1,1 Red 2: 0.5,0,0,1 Green 2: 0,0.5,0,1 Blue 2: 0,0,0.5,1 Yellow 2: 0.5,0.5,0,1 Purple 2: 0.5,0,0.5,1 Cyan 2: 0,0.5,0.5,1 The colorList handler returns a list of unique colors for use when coloring the sectors of the chart. The number of colors to be returned is given by the pNumber parameter. The handler loops calculating RGB values for colors. ● Highest intensity primary colors ● Highest intensity secondary colors ● Reduce the color intensity by half Each iteration adds 6 colors to the list. 1. R,0,0,1 2. 0,G,0,1 3. 0,0,B,1 4. R,G,0,1 5. R,0,B,1 6. 0,G,B,1
  183. 183. #LiveCodeGlobal The colorList handler Add the colorList handler to the source file. ● Declare the variables that will be used. ● Assign a value to tColorLevel: the color intensity to be used. ● Calculate the number of repeats ○ Divide pNumber by 6, 6 colors are add to the color list on each iteration of the loop ○ Round the result ○ Add 1 to the result to ensure we always calculate enough colors public handler colorList(in pNumber) returns List variable tColors as List variable tColorLevel as Number variable tRepeats as Number put 1 into tColorLevel put pNumber / 6 into tRepeats round tRepeats add 1 to tRepeats … continues on next slide end handler

×