Main Content

Live Editor Task Development Overview

Live Editor tasks are simple point-and-click interfaces that can be embedded into a live script to perform a specific set of operations. You can use tasks to explore parameters and automatically generate code in a live script. Tasks are useful because they can help reduce development time, errors, and time spent plotting.

MATLAB® provides a set of Live Editor tasks for use in live scripts. You also can create your own Live Editor task by defining a subclass of the matlab.task.LiveTask base class. Then, to make the task available in the Live Editor, configure the task using the Task Metadata dialog box.

Define Live Editor Task Subclass

To create custom Live Editor task, first, define a subclass of the matlab.task.LiveTask base class by following these steps:

  1. Create the Live Editor task subclass.

  2. Define public and private properties.

  3. Implement the get.Summary, get.State, and set.State methods.

  4. Implement the setup, generateCode, and reset methods.

  5. Implement the postExecutionUpdate method (optional).

  6. Emit a StateChanged event (optional).

  7. Set the AutoRun property (optional).

Create Live Editor Task Subclass

To create a subclass of the matlab.task.LiveTask base class, on the Live Editor or Editor tab, select New > Live Task Class. A new untitled file opens containing a template of a Live Editor Task subclass. Replace the class name in the template code with the name of your Live Editor task class. Then, save the file as a .m file with the same name as the class.

classdef untitled < matlab.task.LiveTask
    % Add summary here

    % NOTE: To register/update your task, run matlab.task.configureMetadata
    % in command window. To de-register run matlab.task.removeMetadata
    % This class extends the base class LiveTask and provides the
    % implementation for all the abstract methods defined in the parent
    % class.

    properties(Access = private,Transient)
        % Declare UI elements here

    end

    properties(Dependent)
        % State property stores current state of UI objects in the task, specified as a struct.
        State

        % Task summary, specified as a string scalar or character vector.
        Summary
    end

    methods(Access = protected)
        function setup(task)
            % Method to set up the initial state of the task.
            % This method is called when the task is constructed.
            % Add your implementation here
        end
    end

    methods
        function [code,outputs] = generateCode(task)
            % Method to generate code and outputs for the task.
            % Construct code exclusively using information from this class.
            % Add your implementation here
            code = "";
            outputs = {};
        end

        function summary = get.Summary(task)
            % Define this method to get the Summary of the task.
            % This is used to dynamically generate the description of what the task does.
            summary = "";
        end

        function state = get.State(task)
            % Used along with jsonencode for serialization of task
            state = struct;
        end

        function set.State(task,state)
            % Used along with jsondecode for task restoration
        end

        function reset(task)
            % This method is called when a user restores the default values
            % of the task by clicking the options button
        end
    end
end

For example, to create a Live Editor task that normalizes vector data, replace class name in the first line of the template code with NormalizeVectorData. Then, save the file as NormalizeVectorData.m.

classdef NormalizeVectorData < matlab.task.LiveTask

To view the complete code for NormalizeVectorData, see NormalizeVectorData Class Definition.

Define Public and Private Properties

Define the properties for your class. In the private properties block, define properties to store the implementation details of your class that you want to hide. These properties store the underlying graphics and UI objects that make up your task, in addition to any calculated values that you want to store. Eventually, your class will use the data in the public properties to configure the underlying objects in the private properties. Set the Transient attribute for the private block to avoid storing redundant information if an instance of the task is saved.

In the public properties block, define the properties that the base class needs access to, including the two required public properties State and Summary. The State property stores the current state of the task, and the Summary property stores a dynamic summary of what the task does. Set the Dependent attribute for the public block to avoid access issues with the get and set methods for the properties.

For example, define the public and private properties for the NormalizeVectorData class.

properties(Access = private,Transient)
    InputDataDropDown               matlab.ui.control.DropDown
    MethodDropDown                  matlab.ui.control.DropDown
    ZscoreGrid                      matlab.ui.container.GridLayout
    ZscoreDropDown                  matlab.ui.control.DropDown
end
    
properties(Dependent)
    State
    Summary
end   

Implement get.Summary Method

Define the get.Summary method for your class to dynamically generate the description of what the task does. The get.Summary method executes when the value of the Summary property is requested. The returned summary displays at the top of the task and remains visible when the task is collapsed.

Define the method in a method block with no arguments so that it is called when getting the value of the Summary property. The get.Summary method returns the generated description as a character array.

For example, implement the get.Summary method for the NormalizeVectorData class. Use the selected normalizing method in the MethodDropDown list and the selected input data in the InputDataDropDown list to generate a dynamic summary based on the current selection. If no input data is selected, set the summary to match the default description defined in the liveTasks.json file. To display variable or function names in monospaced font, surround them with backticks (``).

function summary = get.Summary(task)
    if isequal(task.InputDataDropDown.Value,"select variable")
        summary = "Normalize vector data";
    else
        switch task.MethodDropDown.Value
            case "zscore"
                methodString = " using z-score";
            case "norm"
                methodString = " using 2-norm";
            case "scale"
                methodString = " using scaling by standard deviation";
        end
        summary = "Normalized vector `" + task.InputDataDropDown.Value + ...
            "`" + methodString;
    end
end

Implement get.State and set.State Methods

Define the get.State and set.State methods for your class to get and set the current state of the UI objects in the task. The Live Editor uses these methods to restore a task to a specified state during copy, paste, undo, and redo operations, as well as when the live script containing the task is closed and reopened. The current state of the task is stored in a struct. When the live script is closed, the Live Editor uses the jsonencode function to convert the struct returned by get.State to JSON format and saves the encoded state with the live script. When the live script is reopened, the Live Editor converts the encoded state back to a struct, which is then used to set the current state of the task using set.State. Refer to the jsonencode function for more information about the data types it supports.

Define the methods in the same method block as the get.Summary method so that they are called when setting or getting the value of the State property. The get.State method returns a struct containing the current value of each UI object in the task. The set.State method takes a struct previously returned by the get.State method and uses the struct to set the value of each UI object in the task.

For example, implement the get.State and set.State methods for the NormalizeVectorData class. In the get.State method, create and return a struct with the value of each DropDown object in the task.

function state = get.State(task)
    state = struct;
    state.InputDataDropDownValue = task.InputDataDropDown.Value;
    state.MethodDropDownValue = task.MethodDropDown.Value;
    state.ZscoreDropDownValue = task.ZscoreDropDown.Value;
end

In the set.State method, use the values stored in the struct that is passed in to set the value of each DropDown object in the task.

function set.State(task,state)
    value = state.InputDataDropDownValue;
    if ~ismember(value, task.InputDataDropDown.ItemsData)
        task.InputDataDropDown.Items = [task.InputDataDropDown.Items value];
    end
    task.InputDataDropDown.Value = value;
    task.MethodDropDown.Value = state.MethodDropDownValue;
    task.ZscoreDropDown.Value = state.ZscoreDropDownValue;
    updateComponents(task);
end

Implement setup Method

Define the setup method for your class. The setup method sets the initial state of the task and executes once when MATLAB constructs the task. Define the setup method in a protected block so that only your class can execute it.

Use the setup method to:

  • Create, layout, and configure the graphics and UI objects that make up the task.

  • Program the behavior of objects within the task.

  • Set the default values for the objects.

Note

All graphics and UI objects for the task must be added to the task's grid layout manager, LayoutManager. If an object is added to the task directly, MATLAB throws an error.

For example, implement the setup method for the NormalizeVectorData class. In the setup method, call the createComponents, setComponentsToDefault, and updateComponents helper functions to create and arrange the components in the task, set all the components to their default values, and update the components.

function setup(task)
    createComponents(task);
    setComponentsToDefault(task);
    updateComponents(task);
end

Create a private methods block and define the createComponents, setComponentsToDefault, updateComponents, and populateWSDropdownItems helper functions.

In the createComponents function, call the uilabel, uigridlayout, and uidropdown functions to create and arrange Label, GridLayout, and DropDown objects, specifying the task's LayoutManager as the parent. Store those objects in the corresponding private properties. Specify the updateComponents method as the ValueChangedFcn callback that is called when the value of a drop-down list is changed. Specify the populateWSDropdownItems method as the DropDownOpeningFcn callback that is called when a drop-down list is opened.

methods(Access = private)
    function createComponents(task)
        g = uigridlayout(task.LayoutManager,[1,1]);
        g.RowHeight = ["fit" "fit" "fit" "fit"];
        g.ColumnWidth = "fit";

        % Row 1: Select data section label
        uilabel(g,Text="Select data",FontWeight="bold");

        % Row 2: Select data section components
        inputgrid = uigridlayout(g,RowHeight="fit", ...
            ColumnWidth=["fit","fit"],Padding=0);
        uilabel(inputgrid,Text="Input data");
        task.InputDataDropDown = uidropdown(inputgrid, ...
            ValueChangedFcn=@task.updateComponents, ...
            DropDownOpeningFcn=@task.populateWSDropdownItems);
        task.populateWSDropdownItems(task.InputDataDropDown);

        % Row 3: Specify method section label
        uilabel(g,Text="Specify method",FontWeight="bold");

        % Row 4: Method section components
        methodgrid = uigridlayout(g,RowHeight="fit", ...
            ColumnWidth=["fit","fit","fit"],Padding=0);
        uilabel(methodgrid,Text="Normalization method");
        task.MethodDropDown = uidropdown(methodgrid, ...
            ValueChangedFcn=@task.updateComponents);
        task.MethodDropDown.Items = ["Z-score" "2-Norm" ...
            "Scale by standard deviation"];
        task.MethodDropDown.ItemsData = ["zscore" "norm" "scale"];

        % Subgrid 1 in method section
        task.ZscoreGrid = uigridlayout(methodgrid,RowHeight="fit", ...
            ColumnWidth=["fit","fit"],Padding=0);
        uilabel(task.ZscoreGrid,Text="Deviation type");
        task.ZscoreDropDown = uidropdown(task.ZscoreGrid, ...
            ValueChangedFcn=@task.updateComponents, ...
            Items=["Standard" "Median absolute"], ...
            ItemsData=["std" "robust"], ...
            Tooltip="Center data to 0 and scale to deviation 1");
    end

    function setComponentsToDefault(task)
        task.MethodDropDown.Value = "zscore";
        task.ZscoreDropDown.Value = "std";
    end

    function updateComponents(task,source,~)
        hasData = ~isequal(task.InputDataDropDown.Value,"select variable");

        task.MethodDropDown.Enable = hasData;
        task.ZscoreDropDown.Enable = hasData;

        % Show only relevant subgrids
        task.ZscoreGrid.Visible = isequal(task.MethodDropDown.Value,"zscore");

        % Trigger the Live Editor to update the generated script
        notify(task,"StateChanged");
    end

    function populateWSDropdownItems(~,src,~)
        workspaceVariables = evalin("base","who");
        src.Items = ["select variable"; workspaceVariables];
    end
end

Implement generateCode Method

Define the generateCode method for your class to generate the MATLAB commands and output for the task. This method executes when the task state changes, for example, when a user modifies a task parameter. The generated code displays in the code section of the task. When the live script section containing the task runs, the Live Editor uses the generated code to run the task. Define the generateCode method in the same method block as the get.Summary, get.State, and set.State methods.

The generateCode method returns two output arguments, code and outputs. code is a character array or string array containing the generated code for the task. outputs is a cell array containing the output variables produced by the code. If the task does not generate output, return outputs as an empty cell array.

  • Start the generated code with a comment that describes what the code is doing. For example, % Normalize data.

  • Surround variable names with backticks (``) to identify variables to the Live Editor and prevent them from being renamed. If backticks are not added and the task has the same input and output variable name, then the input variable could get auto-incremented, which could result in errors.

  • Minimize the amount of generated code by only including commands that set parameters to nondefault values. For example, this code checks whether the selected normalization method is the default method.

  • Optionally, separate out the plotting code and add it to the end of the generated code.

For example, implement the generateCode method for the NormalizeVectorData class:

function [code,outputs] = generateCode(task)
    if isequal(task.InputDataDropDown.Value,"select variable")
        % Return empty values if there is not enough
        % information to generate code
        code = "";
        outputs = {};
        return
    end
                
    outputs = {'normalizedData'};
                
    inputdata = "`" + task.InputDataDropDown.Value + "`";
    if isequal(task.MethodDropDown.Value,"zscore") && ...
            isequal(task.ZscoreDropDown.Value,"std")
        code = "normalizedData = normalize(" + inputdata + ");";
    elseif isequal(task.MethodDropDown.Value,"zscore")
        code = "normalizedData = normalize(" + inputdata + ...
            ",""zscore"",""" + task.ZscoreDropDown.Value + """);";
    else
        code = "normalizedData = normalize(" + inputdata + ...
            ",""" + task.MethodDropDown.Value + """);";
    end
    code = ["% Normalize data"; code];                           
end

Implement reset Method

Define the reset method for your class to bring the task back to its default state. Define the method in the same method block as the get.Summary, get.State, set.State, and generateCode methods.

For example, implement the reset method for the NormalizeVectorData class. Call the setComponentsToDefault function to set all objects to their default values. Then, call the updateComponents function to update all the components.

function reset(task)
    setComponentsToDefault(task);
    updateComponents(task);
end

Implement postExecutionUpdate Method (Optional)

Optionally, you can define a postExecutionUpdate method for your class to perform specific updates for your task. This method executes after the generated code for your task runs. For example, you can implement the postExecutionUpdate method to add newly created variables to a drop-down list used to select input data after the generated code for your task runs.

Define the postExecutionUpdate method in the same method block as the get.Summary, get.State, set.State, generateCode, and reset methods. The postExecutionUpdate method takes two inputs, an instance of the task, and a struct containing the task outputs (returned by the generateCode method) and their current workspace values.

function postExecutionUpdate(task,data)
    ...
end

Emit StateChanged Event (Optional)

The Live Editor listens for changes in a task and calls the generateCode method to update the task's generated code when it detects a change. The Live Editor detects changes by monitoring the components in the task that fire these events:

  • ValueChanged

  • ButtonPushed

  • ImageClicked

  • SelectionChanged

To update the generated code for a task when changes occur outside of the events listed (for example, in a component that does not fire these events), you can call the notify method to fire the StateChanged event and trigger a call to the generateCode method for the task.

notify(task,"StateChanged");

Note

The Live Editor does not monitor events for components that are created dynamically at run time.

Set AutoRun Property (Optional)

Optionally, you can set the AutoRun property for your class to specify whether your task runs automatically when a user modifies the task parameters.

By default, the AutoRun property is set to true and the task runs automatically after a change. To disable running your task automatically, set the AutoRun property to false.

task.AutoRun = false;

You only need to set the AutoRun property once, preferably when setting the initial state of the task. For example, set the AutoRun property for the NormalizeVectorData class in the setup method.

function setup(task) 
    task.AutoRun = false;
    createComponents(task);
    setComponentsToDefault(task);
    updateComponents(task);
end

Configure Live Editor Task Metadata

After creating the Live Editor task subclass, configure your task for use in the Live Editor by using the matlab.task.configureMetadata function. The function opens the Task Metadata dialog box. This dialog box allows you to specify metadata for the task. The Live Editor then uses this metadata to display the task in the Live Editor task gallery as well as in automatic code suggestions and completions.

Call the function by passing it the path to the class definition file for your task. If you do not specify a path, a file selection dialog box opens and prompts you to select a file.

For example, use the matlab.task.configureMetadata function to configure the Normalize Vector Data task.

matlab.task.configureMetadata("NormalizeVectorData")

The Task Metadata dialog box prepopulates all of the required task metadata details from your task class definition file.

Task Metadata dialog box with the required task metadata prepopulated

You can edit the prepopulated metadata options using the Task Metadata dialog box. This table describes each individual task metadata option.

OptionSummary
Name

Specify the name of the task to display in the autocompletion list and in the Live Editor task gallery.

This detail is required.

Description

Specify the description of the task to display in the autocompletion list and in the Live Editor task gallery.

This detail is optional.

Icon

Specify the path for the task icon to display in the Live Editor task gallery. If you specify a task icon, MATLAB copies it to the resources folder.

This detail is optional.

Keywords

Specify the keywords that can be used to show the task in the autocompletion list.

This detail is optional.

Documentation Link

Specify the documentation link as a URL to the documentation that opens when the task help icon is clicked.

To specify a function that returns a documentation link dynamically, include the text taskmethod: followed by the name of the function that returns the doc link. For example, taskmethod:fetchHelpLink. The function must be defined as a public method in the task class definition file.

If a documentation link is not specified, clicking the task help icon opens the generated help for the task in the system web browser.

This detail is optional.

Normalize Vector Data task with the help icon at the top-right circled in red

When you are done editing, click OK. MATLAB creates a folder named resources inside the folder containing your task class definition file. Inside the resources folder, MATLAB generates a file named liveTasks.json. This file contains the metadata you provided in the Task Metadata dialog box, in addition to other metadata MATLAB needs to make your task available in the Live Editor. Share this folder when you share your Live Editor task.

Note

Do not modify the liveTasks.json file by hand. To change any Live Editor task metadata, use the matlab.task.configureMetadata function.

To make your task available in the Live Editor, add the folder containing your task class definition file to the MATLAB path. To add the folder, use the addpath function or the Add Folder button in the Set Path dialog box.

Note

You do not need to add the resources folder that is inside the folder containing your task class definition file to the path. Folders named resources are not allowed on the MATLAB path.

Use Custom Live Editor Task

To test whether your task creates correctly, create an instance of your class. For example, create an instance of the NormalizeVectorData class.

c = NormalizeVectorData;

MATLAB creates the Normalize Vector Data task.

Instance of the Normalize Vector Data task with drop-down lists for selecting the input data, the normalization method, and the deviation type

To get all of the UI objects in the task, use the findall function.

h = findall(c.Parent)
h = 
  14×1 graphics array:

  Figure        (NormalizeVectorData)
  GridLayout
  GridLayout
  Label         (Select data)
  GridLayout
  Label         (Specify method)
  GridLayout
  Label         (Input data)
  DropDown      (select variable)
  Label         (Normalization method)
  DropDown      (Z-score)
  GridLayout
  Label         (Deviation type)
  DropDown      (Standard)

To add your task to a live script, in the live script, type one of the keywords defined in liveTasks.json and select your task from the list of suggested names.

For example, to add the Normalize Vector Data task to a live script, first, create a live script. Then, on a code line, type norm. MATLAB shows a list of suggested matches.

Live script with a code line containing the text "norm" and a list of suggestions including the Normalize Vector Data task

Select Normalize Vector Data from the list. MATLAB adds the Normalize Vector Data task to the live script.

Normalize Vector Data task in a live script

To add your task from the toolstrip, go to the Live Editor tab and in the Code section, click Task . Select Normalize Vector Data to add the Normalize Vector Data task to your live script. You must save the MATLAB path and restart MATLAB to include your task in the Live Editor task gallery.

Live Editor task gallery with the Normalize Vector Data task in the "My Tasks" section

NormalizeVectorData Class Definition

This code provides the complete contents of the NormalizeVectorData class.

classdef NormalizeVectorData < matlab.task.LiveTask
    properties(Access = private,Transient)
        InputDataDropDown               matlab.ui.control.DropDown
        MethodDropDown                  matlab.ui.control.DropDown
        ZscoreGrid                      matlab.ui.container.GridLayout
        ZscoreDropDown                  matlab.ui.control.DropDown
    end
    
    properties(Dependent)
        State
        Summary
    end 
    methods(Access = protected)      
        function setup(task)
            createComponents(task);
            setComponentsToDefault(task);
            updateComponents(task);
        end
    end
    methods(Access = private)
        function createComponents(task)
            g = uigridlayout(task.LayoutManager,[1,1]);
            g.RowHeight = ["fit" "fit" "fit" "fit"];
            g.ColumnWidth = "fit";

            % Row 1: Select data section label
            uilabel(g,Text="Select data",FontWeight="bold");

            % Row 2: Select data section components
            inputgrid = uigridlayout(g,RowHeight="fit", ...
                ColumnWidth=["fit","fit"],Padding=0);
            uilabel(inputgrid,Text="Input data");
            task.InputDataDropDown = uidropdown(inputgrid, ...
                ValueChangedFcn=@task.updateComponents, ...
                DropDownOpeningFcn=@task.populateWSDropdownItems);
            task.populateWSDropdownItems(task.InputDataDropDown);

            % Row 3: Specify method section label
            uilabel(g,Text="Specify method",FontWeight="bold");

            % Row 4: Method section components
            methodgrid = uigridlayout(g,RowHeight="fit", ...
                ColumnWidth=["fit","fit","fit"],Padding=0);
            uilabel(methodgrid,Text="Normalization method");
            task.MethodDropDown = uidropdown(methodgrid, ...
                ValueChangedFcn=@task.updateComponents);
            task.MethodDropDown.Items = ["Z-score" "2-Norm" ...
                "Scale by standard deviation"];
            task.MethodDropDown.ItemsData = ["zscore" "norm" "scale"];

            % Subgrid 1 in method section
            task.ZscoreGrid = uigridlayout(methodgrid,RowHeight="fit", ...
                ColumnWidth=["fit","fit"],Padding=0);
            uilabel(task.ZscoreGrid,Text="Deviation type");
            task.ZscoreDropDown = uidropdown(task.ZscoreGrid, ...
                ValueChangedFcn=@task.updateComponents, ...
                Items=["Standard" "Median absolute"], ...
                ItemsData=["std" "robust"], ...
                Tooltip="Center data to 0 and scale to deviation 1");
        end

        function setComponentsToDefault(task)
            task.MethodDropDown.Value = "zscore";
            task.ZscoreDropDown.Value = "std";
        end

        function updateComponents(task,~,~)
            hasData = ~isequal(task.InputDataDropDown.Value,"select variable");    
            task.MethodDropDown.Enable = hasData;
            task.ZscoreDropDown.Enable = hasData;

            % Show only relevant subgrids
            task.ZscoreGrid.Visible = isequal(task.MethodDropDown.Value,"zscore");

            % Trigger the Live Editor to update the generated script
            notify(task,"StateChanged");
        end

        function populateWSDropdownItems(~,src,~)
            workspaceVariables = evalin("base","who");
            src.Items = ["select variable"; workspaceVariables];
        end
    end    

    methods
        function [code,outputs] = generateCode(task)
            if isequal(task.InputDataDropDown.Value,"select variable")
                % Return empty values if there is not enough
                % information to generate code
                code = "";
                outputs = {};
                return
            end
                
            outputs = {'normalizedData'};
                        
            inputdata = "`" + task.InputDataDropDown.Value + "`";        
            if isequal(task.MethodDropDown.Value,"zscore") && ...
                    isequal(task.ZscoreDropDown.Value,"std")
                code = "normalizedData = normalize(" + inputdata + ");";
            elseif isequal(task.MethodDropDown.Value,"zscore")
                code = "normalizedData = normalize(" + inputdata + ...
                    ",""zscore"",""" + task.ZscoreDropDown.Value + """);";
            else
                code = "normalizedData = normalize(" + inputdata + ...
                    ",""" + task.MethodDropDown.Value + """);";
            end
            code = ["% Normalize data"; code];                           
        end

        function summary = get.Summary(task)
            if isequal(task.InputDataDropDown.Value,"select variable")
                summary = "Normalize vector data";
            else
                switch task.MethodDropDown.Value
                    case "zscore"
                        methodString = " using z-score";
                    case "norm"
                        methodString = " using 2-norm";
                    case "scale"
                        methodString = " using scaling by standard deviation";
                end
                summary = "Normalized vector `" + task.InputDataDropDown.Value + ...
                    "`" + methodString;
            end
        end
        
        function state = get.State(task)
            state = struct;
            state.InputDataDropDownValue = task.InputDataDropDown.Value;
            state.MethodDropDownValue = task.MethodDropDown.Value;
            state.ZscoreDropDownValue = task.ZscoreDropDown.Value;
        end
        
        function set.State(task,state)
            value = state.InputDataDropDownValue;
            if ~ismember(value, task.InputDataDropDown.ItemsData)
                task.InputDataDropDown.Items = [task.InputDataDropDown.Items value];
            end
            task.InputDataDropDown.Value = value;
            task.MethodDropDown.Value = state.MethodDropDownValue;
            task.ZscoreDropDown.Value = state.ZscoreDropDownValue;
            updateComponents(task);
        end
	
        function reset(task)
            setComponentsToDefault(task);
            updateComponents(task);
        end
    end
end

See Also

| | |

Related Topics