Skip to content

MIB App Design plugin

# MIB AppDesigner Plugin

Back to MIB | User Interface | Plugins | Tutorials


Overview

MIB plugin with GUI

The MIB App Design Plugin is a tutorial that demonstrates how to create plugins for Microscopy Image Browser (MIB) appdesigner-based graphical interface.
It demonstrates how to build a simple plugin that shows how to use various widgets.

Plugin filenames definition

A plugin built with the AppDesigner GUI typically includes the following files:

  • [PLUGIN-NAME]Controller.m, controller of the plugin with the main logic and functions
  • [PLUGIN-NAME]GUI.mlapp, figure file generated using MATLAB AppDesigner tool for GUI framework development.

Info

where [PLUGIN-NAME] is the name of the plugin.

Warning

This plugin name ([PLUGIN-NAME]) should match with the name of the directory where the plugin is located.

Example

For example mibPluginController.m:

  • [PLUGIN-NAME] -> mibPlugin, located under Plugins/Tutorials/mibPlugin directory
  • Full path: MIB/Plugins/Tutorials/mibPlugin/mibPluginController.m The same applies to mibPluginGUI.mlapp
Plugins with GUI made using guide

guide is the original MATLAB framework for development of GUI applications.
Example of the guide-based plugin is located under Plugins/Tutorials/mibPlugin and Plugins/Tutorials/GuiTutorial

Plugins without GUI

A plugin without a GUI consists of a single file named [PLUGIN-NAME]Controller.m, where [PLUGIN-NAME] is the name of the plugin. See more here.

Sections of mibAppDesignPluginController.m

properties

Use this section to define properties for the plugin class. These properties will be available to all functions within the plugin class.

Code for properties
properties
    mibModel
    % handles to mibModel
    View
    % handle to the view / mibAppDesignPluginGUI
    listener
    % a cell array with handles to listeners
    BatchOpt
    % a structure compatible with batch operation
    % name of each field should be displayed in a tooltip of GUI
    % it is recommended that the Tags of widgets match the name of the
    % fields in this structure
    % .Parameter - [editbox], char/string 
    % .Checkbox - [checkbox], logical value true or false
    % .Dropdown{1} - [dropdown],  cell string for the dropdown
    % .Dropdown{2} - [optional], an array with possible options
    % .Radio - [radiobuttons], cell string 'Radio1' or 'Radio2'...
    % .ParameterNumeric{1} - [numeric editbox], cell with a number 
    % .ParameterNumeric{2} - [optional], vector with limits [min, max]
    % .ParameterNumeric{3} - [optional], string 'on' - to round the value, 'off' to do not round the value
end

events

This plugin has a single event that is triggered when the plugin is closed.

Code for events
events
    %> Description of events
    closeEvent
    % event firing when plugin is closed
end

methods (static)

This section contains a function that listens for updateGuiWidgets event from mibModel. When it comes, the plugin refreshes itself using obj.updateGuiWidgets() function.

Code for static methods
methods (Static)
    function ViewListner_Callback(obj, src, evnt)
        switch evnt.EventName
            case {'updateGuiWidgets'}
                obj.updateWidgets();
        end
    end
end

constructor

Constructor is the first function
function obj = mibAppDesignPluginController(mibModel, varargin)
initialized when the plugin starts.

mibModel that holds data classes of MIB is passed as a parameter and assigned into obj.mibModel variable available to all functions of the plugin:
obj.mibModel = mibModel; % assign model

Initialization of default obj.BatchOpt parameters

In order to be compatible with the batch processing operations and work in general, the default values for the plugin widgets should be predefined in this section using obj.BatchOpt structure.
Each field in the structure corresponds to a widget tag in mibAppDesignPluginGUI.mlapp.
Depending on widget type, their initialization may be different, check this section for examples of initialization patterns for various widget types:

Initialization of obj.BatchOpt structure
%% fill the BatchOpt structure with default values
% fields of the structure should correspond to the starting
% text in the each widget tooltip.
% For example, this demo template has an edit box, where the
% tooltip starts with "Parameter:...". Text Parameter
% indicates field of the BatchOpt structure that defines value
% for this widget
obj.BatchOpt.Parameter = 'my parameter';    % edit box
obj.BatchOpt.Checkbox = true;               % checkbox
obj.BatchOpt.Dropdown = {'Option 3'};       % dropdown selected value
obj.BatchOpt.Dropdown{2} = {'Option 1', 'Option 2', 'Option 3'}; % dropdown options
obj.BatchOpt.Radio = {'Radio2'};  % selected radio button value
obj.BatchOpt.ParameterNumeric{1} = 512.125;     % numeric edit box or spinner
obj.BatchOpt.ParameterNumeric{2} = [0 1024];    % possible limits value
obj.BatchOpt.ParameterNumeric{3} = 'off';    % round the numeric value
obj.BatchOpt.showWaitbar = true;    % show or not the progress waitbar
obj.BatchOpt.id = obj.mibModel.Id;  % optional        

The initialization of obj.BatchOpt is followed with initialization of the section and action names to be compatible with MIB\Classes\@mibBatchController\mibAppDesignPluginController.m and Batch processing

Plugin information for Batch processing

Optionally:

%% part below is only valid for use of the plugin from MIB batch controller
% comment it if intended use not from the batch mode
obj.BatchOpt.mibBatchSectionName = 'Menu -> Plugins';    % section name for the Batch
obj.BatchOpt.mibBatchActionName = 'mibAppDesignPlugin';           % name of the plugin

Define tooltip text that appears when hovering over each widget. These tooltips help users understand the function of each GUI element.

Tooltip descriptions
% tooltips that will accompany the BatchOpt
obj.BatchOpt.mibBatchTooltip.Parameter = sprintf('Provide text or number as string');
obj.BatchOpt.mibBatchTooltip.Checkbox = sprintf('Specify checkboxes as logicals');
obj.BatchOpt.mibBatchTooltip.Popup = sprintf('Popups populated using cells');
obj.BatchOpt.mibBatchTooltip.Radio = sprintf('Selection of radio buttons, as cell with the handle of the target radio button');
obj.BatchOpt.mibBatchTooltip.showWaitbar = sprintf('Show or not waitbar');
Batch processing compatibility block

The next section defines how the plugin interacts with the Batch Processing dialog or to run the plugin from the Batch processing dialog.

  • obj.returnBatchOpt() function is used to return the plugin parameters to the Batch processing dialog
  • obj.BatchOpt = updateBatchOptCombineFields_Shared(obj.BatchOpt, BatchOptIn); updates obj.BatchOpt using the provided BatchOptIn from the Batch processing dialog.
  • obj.Calculate(); when started from the Batch processing dialog run the function and close the plugin dialog.
Batch processing block
%% add here a code for the batch mode, for example
% when the BatchOpt stucture is provided the controller will
% use it as the parameters, and performs the function in the
% headless mode without GUI
if nargin == 3
    BatchOptIn = varargin{2};
    if isstruct(BatchOptIn) == 0 
        if isnan(BatchOptIn)     % when varargin{2} == NaN return possible settings
            obj.returnBatchOpt();   % obtain Batch parameters
        else
            errordlg(sprintf('A structure as the 3rd parameter is required!')); 
        end
        notify(obj, 'closeEvent'); 
        return
    end
    % add/update BatchOpt with the provided fields in BatchOptIn
    % combine fields from input and default structures
    obj.BatchOpt = updateBatchOptCombineFields_Shared(obj.BatchOpt, BatchOptIn);

    obj.Calculate(); % run the main plugin function
    notify(obj, 'closeEvent'); % close the dialog
    return;
end
Optional modification of Batch processing controller

In order to use the plugin with Batch processing dialog, the corresponding section needs to be added into MIB\Classes\@mibBatchController\mibAppDesignPluginController.m
Navigate to

function obj = mibBatchController(mibModel, varargin)
...
obj.Sections(secIndex).Name = 'Menu -> Plugins';
Add the following code:
obj.Sections(secIndex).Actions(actionId).Name = 'mib App Design Plugin [any suitable name]';
obj.Sections(secIndex).Actions(actionId).Command = 'obj.mibController.startController(''mibAppDesignPluginController'', [], Batch);'; actionId = actionId + 1;

Plugin initialization block
  • guiName = 'mibAppDesignPluginGUI'; define plugin name
  • obj.View = mibChildView(obj, guiName); % initialize the view initialize the view provided by mibAppDesignPluginGUI.mlapp
  • obj.View.gui = moveWindowOutside(obj.View.gui, 'left'); move the plugin window to a side of the main MIB window
  • update the font size
Update font size
global Font;
if ~isempty(Font)
     if obj.View.handles.infoText.FontSize ~= Font.FontSize ...
         || ~strcmp(obj.View.handles.infoText.FontName, Font.FontName)
         mibUpdateFontSize(obj.View.gui, Font);
     end
end
  • obj.updateWidgets(); function is triggered at the plugin startup and whenever updateGuiWidgets event comes
  • obj.View = updateGUIFromBatchOpt_Shared(obj.View, obj.BatchOpt); update GUI widgets using obj.BatchOpt structure
  • obj.listener{1} = addlistener(obj.mibModel, 'updateGuiWidgets', @(src,evnt) obj.ViewListner_Callback(obj, src, evnt)); add listener to catch events generated by main MIB window.

closeWindow

You can define custom behavior that runs when the user closes the plugin window.
By default, the plugin notifies the main MIB controller that it gets closed: notify(obj, 'closeEvent');

Code of closeWindow function
function closeWindow(obj)
    % closing mibAppDesignPluginController window
    if isvalid(obj.View.gui)
        delete(obj.View.gui);   % delete childController window
    end

    % delete listeners, otherwise they stay after deleting of the
    % controller
    for i=1:numel(obj.listener)
        delete(obj.listener{i});
    end

    notify(obj, 'closeEvent');      % notify mibController that this child window is closed
end

updateWidgets

Function that updates the plugin GUI widgets from obj.BatchOpt triggered at the plugin startup and whenever updateGuiWidgets event comes

Code of updateWidgets function
function updateWidgets(obj)
    % function updateWidgets(obj)
    % update widgets of this window

    % updateWidgets normally triggered during change of MIB
    % buffers, make sure that any widgets related changes are
    % correctly propagated into the BatchOpt structure
    if isfield(obj.BatchOpt, 'id'); obj.BatchOpt.id = obj.mibModel.Id; end

    % when elements GIU needs to be updated, update obj.BatchOpt
    % structure and after that update elements of GUI by the
    % following function
    obj.View = updateGUIFromBatchOpt_Shared(obj.View, obj.BatchOpt);    %

    fprintf('childController:updateWidgets: %g\n', toc);
end

updateBatchOptFromGUI

This is a standard callback function for widgets of the GUI window. Upon change of a widget, it is triggered and updates the corresponding field of obj.BatchOpt

Code of updateBatchOptFromGUI function
function updateBatchOptFromGUI(obj, event)
    % function updateBatchOptFromGUI(obj, event)
    %
    % update obj.BatchOpt from widgets of GUI
    % use an external function (Tools\updateBatchOptFromGUI_Shared.m) that is common for all tools
    % compatible with the Batch mode
    %
    % Parameters:
    % event: event from the callback

    obj.BatchOpt = updateBatchOptFromGUI_Shared(obj.BatchOpt, event.Source);
end

returnBatchOpt

Return obj.BatchOpt structure to the Batch processing dialog

Code of returnBatchOpt function
function returnBatchOpt(obj, BatchOptOut)
    % return structure with Batch Options and possible configurations
    % via the notify 'syncBatch' event
    % Parameters:
    % BatchOptOut: a local structure with Batch Options generated
    % during Continue callback. It may contain more fields than
    % obj.BatchOpt structure
    % 
    if nargin < 2; BatchOptOut = obj.BatchOpt; end

    if isfield(BatchOptOut, 'id'); BatchOptOut = rmfield(BatchOptOut, 'id'); end  % remove id field
    % trigger syncBatch event to send BatchOptOut to mibBatchController 
    eventdata = ToggleEventData(BatchOptOut);
    notify(obj.mibModel, 'syncBatch', eventdata);
end

Calculate function

This is the main function of the plugin demonstrating usage of obj.BatchOpt to acquire current values of widgets of the plugin GUI.

Adapting the function to a new plugin

Perform the following operations to use this plugin as a template for a new plugin.

Copy and rename template files

  • Create a folder for your plugins under MIB/Plugins/ for example MyPlugins so that the full path is
    MIB/Plugins/MyPlugins
  • Create a subfolder under MIB/Plugins/MyPlugins and name it with the name of your new plugin (e.g.MIB/Plugins/MyPlugins/myThirdPlugin)
  • Copy mibAppDesignPluginController.m and mibAppDesignPluginGUI.mlapp to MIB/Plugins/MyPlugins/myThirdPlugin
  • Rename mibAppDesignPluginController.m to myThirdPluginController.m

Rename plugin name in the *Controller.m

  • Open myThirdPluginController.m in MATLAB
  • Do Find and Replace to search for mibAppDesignPlugin and replace with myThirdPlugin, Ctrl+F key shortcut.
  • Edit Calculate function to implement your desired functionality
  • Save the plugin

Modify and resave *GUI.mlapp

  • Type appdesigner mibAppDesignPluginGUI.mlapp to open it in MATLAB appdesigner.

Warning

You may need to change the current MATLAB folder to the plugin directory otherwise it may open the previous version of the plugin in Tutorials\mibPlugin\myThirdPlugin

  • Modify the plugin as needed
  • Resave the mlapp as myThirdPluginGUI.mlapp

Back to MIB | User Interface | Plugins | Tutorials