classdef ExtensionOptionsDialog < uiservices.BaseDialog
    %ExtensionOptionsDialog   Define the ExtensionOptionsDialog class.
    
    %   Copyright 2012 The MathWorks, Inc.
    
    properties (SetAccess = protected)
        
        Extension;
        Registration;
        Configuration;
    end
    
    properties (SetAccess = protected, Hidden, Dependent)
        Register;
        Config;
    end
    
    properties (Access = protected)
        PropertyChangedListener
    end
    
    methods
        function this = ExtensionOptionsDialog(hSystem, type, name)
            %EXTENSIONOPTIONSDIALOG Construct an EXTENSIONOPTIONSDIALOG object
            
            mlock;
            hRegister = findRegistration(hSystem, type, name);
            
            hExtension = getExtension(hSystem, type, name);
            prefix     = getOptionsDialogTitle(hExtension, hSystem);
            hConfig    = hExtension.Configuration;
            
            hApplication = hSystem.Application;
            
            % Build the dialog title from the name of the extension and the application
            if ismethod(hApplication, 'getDialogTitle')
                prefix = [prefix ': '];
            end
            this@uiservices.BaseDialog(prefix, hApplication);
            this.PropertyChangedListener = event.listener(hConfig.PropertySet, 'PropertyChanged', ...
                uiservices.makeCallback(@show, this, false));

            this.Extension     = hExtension;
            this.Registration  = hRegister;
            this.Configuration = hConfig;
            
            updateTitleBar(this);
        end
        
        function r = get.Register(this)
            r = this.Registration;
        end
        function c = get.Config(this)
            c = this.Configuration;
        end
    end
    
    methods (Hidden)
        function dlg = getDialogSchema(this, dummy)
            %GETDIALOGSCHEMA Get the dialog information.
            
            dlg = getDialogSchema@uiservices.BaseDialog(this, dummy);
            
            % Get the dialog information from the extension.  We recommend that
            % extension author's write their getPropsSchema with Mode=false for their
            % widgets.  However, we are not going to force this spec, because there may
            % be widget dependencies that require Mode=true and DialogRefresh=true.
            
            hExtension = this.Extension;
            if isempty(hExtension)
                dlg.Items = {feval(this.Registration, 'getPropsSchema', this.Configuration, this.Dialog)};
            else
                dlg.Items = {getPropsSchema(hExtension, this.Dialog)};
            end
            
            % Remove the help menu item.
            dlg.StandaloneButtonSet = {'OK', 'Cancel', 'Apply'};
            dlg.PostApplyMethod     = 'postApply';
            dlg.DialogTag           = [this.Registration.FullName 'Options'];
            dlg.DialogCSHTag        = 'ExtensionOptionsDialog.Tools_Plot_NavigationOptions';
            dlg.WebDialog           = {'MatlabOnline'};
        end
        
        function [b, msg] = postApply(this)
            %POSTAPPLY
            
            hExtension = this.Extension;
            if isempty(hExtension)
                [b, msg] = feval(this.Registration, 'postOptionsDialogApply', this.Dialog);
            else
                [b, msg] = postOptionsDialogApply(hExtension, this.Dialog);
            end
            
        end
        
        function updateTitleBar(this, ~)
            %UPDATETITLEBAR   Update the titlebar when the application changes its name
            
            % Build the dialog title from the name of the extension and the application
            if ismethod(this.Application, 'getDialogTitle')
                suffix = getDialogTitle(this.Application);
            else
                suffix = '';
            end
            
            % Save the extension handle and the dialog properties.
            this.TitleSuffix = suffix;
            
            show(this, false);
        end
        
        function closedlg(this)
            %CLOSEDLG Close callback for the dialog.
            
            try
                evaluateExtensionMethod(this);
            catch ME
                
                % If the extension method failed, we still need to clean up
                % the dialog before erroring out.
                cleanUpDialog(this);
                
                rethrow(ME);
            end
            
            cleanUpDialog(this);
        end
        
        function varargout = validate(this)
            %VALIDATE Returns true if this object is valid
            
            % Dispatch to the validate method of the extension.  Make sure we pass the
            % dialog handle because extensions will not be setting their widgets to
            % Mode = true and will have to get the widget values from the dialog.
            hExtension = this.Extension;
            if isempty(hExtension)
                [b, exception] = feval(this.Registration, 'validate', this.Dialog);
            else
                [b, exception] = hExtension.validate(this.Dialog);
            end
            
            if nargout
                varargout = {b, exception};
            elseif ~b
                rethrow(exception);
            end
        end
    end
end

% -------------------------------------------------------------------------
function evaluateExtensionMethod(this)

hExtension = this.Extension;
hDialog    = this.Dialog;

% Only call onOptionsDialogClose if we are using instance methods.  There
% is no static method version of onOptionsDialogClose
if ~isempty(hExtension)
    onOptionsDialogClose(hExtension, hDialog);
end
end

% -------------------------------------------------------------------------
function cleanUpDialog(this)

% capture current position of dialog
this.DialogPosition = this.Dialog.position;

% Clear handle since dialog is closing
this.Dialog = [];

end

% [EOF]
