classdef (Hidden) ModelBrowser < controllib.app.databrowser.internal.AbstractDataBrowserComponent
    % Workspace component for Models
    
    % Copyright 2014-2015 The MathWorks, Inc.
    
    properties
        AppData
        VEDialogs
        TempLabels
    end
    
    methods        
        function this = ModelBrowser(data)
            this = this@controllib.app.databrowser.internal.AbstractDataBrowserComponent('Models','Models');
            this.SingleSelection = false;
            this.AppData = data;
            updateUI(this);
            addlistener(this.AppData, 'Models', 'PreSet', @(es,ed) callbackPreSet(this));
            addlistener(this.AppData, 'Models', 'PostSet', @(es,ed) callbackPostSet(this));
            setName(this.Table,'ModelReducer_ModelBrowserTable')
        end        
        function delete(this)
            for ct=1:length(this.VEDialogs)
                if isvalid(this.VEDialogs(ct))
                    delete(this.VEDialogs(ct))
                end
            end
        end        
    end
    
    methods (Access = protected)        
        %% Abstract methods
        function popup = getPopup(this, row)
            % return the popup menu of selected row
            if isempty(row)
                popup = [];
            else
                popup = createPopups(this);
                % update delete status
%                 item = this.MenuItems.Delete;
                % REVISIT do we want to be able to delete last system?
%                 item.setEnabled(length(this.AppData.Models)~=1);            
            end
        end        
        function cbOpen(this)
            Model = getSelectedData(this);
            label = matlab.lang.makeValidName(Model.Label);
            sys = Model.LTI;
            LocalWorkspace = toolpack.databrowser.LocalWorkspaceModel;
            assignin(LocalWorkspace,label,sys);
            ve = toolpack.databrowser.VariableEditorManager.getInstance();
            % cleanup deleted ones
            this.VEDialogs = this.VEDialogs(arrayfun(@(x) isvalid(x),this.VEDialogs));            
            % find if existing open dialog, delete it
            Dialog = this.VEDialogs(arrayfun(@(x) strcmp(getVarName(x),label),this.VEDialogs));
            delete(Dialog);
            % cleanup deleted ones
            this.VEDialogs = this.VEDialogs(arrayfun(@(x) isvalid(x),this.VEDialogs));
            % open a new one
            veDialog = ve.openDialog(LocalWorkspace, label, this.Table);
            this.VEDialogs = [this.VEDialogs; veDialog];
        end        
        function cbRename(this, oldname, newname, row)
            renameModel(this.AppData,newname,row);
            ix = arrayfun(@(x) isvalid(x) && strcmp(x.getVarName,oldname),this.VEDialogs);
            if any(ix)
                delete(this.VEDialogs(ix));
                cbOpen(this);
            end
        end
        function cbExport(this)
            showExportDialog(this.AppData);
        end
        function cbDelete(this)
            ModelsToDelete = getSelectedData(this);            
            % delete already opened system information panel if model is deleted            
            for ct=1:length(ModelsToDelete)
                for ctDialogs = 1:length(this.VEDialogs)
                    CurrentDialog = this.VEDialogs(ctDialogs);
                    if isvalid(CurrentDialog) && isequal(getVarName(CurrentDialog),matlab.lang.makeValidName(ModelsToDelete(ct).Label))
                        delete(CurrentDialog);
                    end
                end
            end
            this.VEDialogs = this.VEDialogs(arrayfun(@(x) isvalid(x),this.VEDialogs));
            removeModel(this.AppData,ModelsToDelete);
        end        
        function data = getLabel(this, idx) 
            % must return cell vector of labels.  If no 2nd input
            % argument, return every label.  If no row is selected, return {}
            if nargin==1
                if isempty(this.AppData.Models)
                    data = {};
                else
                    data = {this.AppData.Models.Label};
                end
            else
                if isempty(this.AppData.Models) || isempty(idx) || any(idx > numel(this.AppData.Models))
                    data = {};
                else
                    data = {this.AppData.Models(idx).Label};
                end
            end
        end        
        function data = getData(this, idx) 
            % must return vector of data objects.  If no 2nd input
            % argument, return every data object.  If no row is selected, return
            % []
            if nargin==1
                if isempty(this.AppData.Models)
                    data = [];
                else
                    data = this.AppData.Models;
                end
            else
                if isempty(this.AppData.Models) || isempty(idx) || any(idx > numel(this.AppData.Models))
                    data = [];
                else
                    data = this.AppData.Models(idx);
                end
            end
        end
       
        %% additional menu item callbacks
        function PopupMenu = createPopups(this)
            %% popup
            this.PopupMenu = javaObjectEDT('com.mathworks.mwswing.MJPopupMenu');
            this.ItemPopupMenu = javaObjectEDT('com.mathworks.mwswing.MJPopupMenu');
           
            %% Model Reduction Techniques Label
            MethodsMenuItem = javaObjectEDT('com.mathworks.mwswing.MJMenu', ...
                getString(message('Control:mrtool:MRTechnique')));
            setName(MethodsMenuItem,'MethodsMenuItem');
            this.ItemPopupMenu.add(MethodsMenuItem);

            %% Balanced Truncation Menu
            BalancedTruncationItem = javaObjectEDT('com.mathworks.mwswing.MJMenuItem', ...
                getString(message('Control:mrtool:MRBalancedTruncation')));
            setName(BalancedTruncationItem,'BalancedTruncationMenuItem');
            MethodsMenuItem.add(BalancedTruncationItem);
            h = handle(BalancedTruncationItem, 'callbackproperties' );
            L = handle.listener(h, 'ActionPerformed', @(es,ed) cbBalancedTruncationMethod(this));
            registerUIListeners(this, L, 'cbBalancedTruncationMethod');            
            
            %% Mode Selection Popup Menu           
            ModeSelectionMenuItem = javaObjectEDT('com.mathworks.mwswing.MJMenuItem', ...
                getString(message('Control:mrtool:MRModeSelection')));
            setName(ModeSelectionMenuItem,'ModeSelectionMenuItem');
            MethodsMenuItem.add(ModeSelectionMenuItem);
            h = handle(ModeSelectionMenuItem, 'callbackproperties' );
            L = handle.listener(h, 'ActionPerformed', @(es,ed) cbModeSelectionMethod(this));
            registerUIListeners(this, L, 'cbModeSelectionMethod');            
            
            %% Pole Zero Simplification Popup Menu            
            PoleZeroSimplificationMenuItem = javaObjectEDT('com.mathworks.mwswing.MJMenuItem', ...
                getString(message('Control:mrtool:MRPoleZeroSimplification')));
            setName(PoleZeroSimplificationMenuItem,'PoleZeroSimplificationMenuItem');
            MethodsMenuItem.add(PoleZeroSimplificationMenuItem);  
            h = handle(PoleZeroSimplificationMenuItem, 'callbackproperties' );
            L = handle.listener(h, 'ActionPerformed', @(es,ed) cbPoleZeroSimplificationMethod(this));
            registerUIListeners(this, L, 'cbPoleZeroSimplificationMethod');                                
            
            %% View Menu
            ViewMenuItem = javaObjectEDT('com.mathworks.mwswing.MJMenuItem', ...
                getString(message('Control:mrtool:OpenSelection')));
            setEnabled(ViewMenuItem,numel(getSelectedData(this)) == 1);
            setName(ViewMenuItem,'EditMenuItem');
            this.ItemPopupMenu.add(ViewMenuItem);
            h = handle(ViewMenuItem, 'callbackproperties' );
            L = handle.listener(h, 'ActionPerformed', @(es,ed) cbOpen(this));
            registerUIListeners(this, L, 'cbOpenListener');
            this.MenuItems.View = ViewMenuItem; 
            
            %% Export Menu
            ExportMenuItem = javaObjectEDT('com.mathworks.mwswing.MJMenuItem', ...
                getString(message('Control:mrtool:Export')));
            setName(ExportMenuItem,'ExportMenuItem');
            this.ItemPopupMenu.add(ExportMenuItem);
            h = handle(ExportMenuItem, 'callbackproperties' );
            L = handle.listener(h, 'ActionPerformed', @(es,ed) cbExport(this));
            registerUIListeners(this, L, 'cbExportListener');
            this.MenuItems.View = ExportMenuItem;            
            
            %% Delete menu
            DeleteMenuItem = javaObjectEDT('com.mathworks.mwswing.MJMenuItem', ...
                getString(message('Control:mrtool:Delete')));
            setName(DeleteMenuItem,'DeleteMenuItem');
            this.ItemPopupMenu.add(DeleteMenuItem);
            h = handle(DeleteMenuItem, 'callbackproperties' );
            L = handle.listener(h, 'ActionPerformed', @(es,ed) cbDelete(this));
            registerUIListeners(this, L, 'cbDeleteListener');
            this.MenuItems.Delete = DeleteMenuItem;
            
            PopupMenu = this.ItemPopupMenu;
        end        
        function callbackPreSet(this)
            this.TempLabels = this.getLabel();
        end        
        function cbBalancedTruncationMethod(this)
            Model = getSelectedData(this);
            openBalancedTruncationTool(this.AppData,Model);            
        end
        function cbModeSelectionMethod(this)
            Model = getSelectedData(this);
            openModeSelectionTool(this.AppData,Model);            
        end
        function cbPoleZeroSimplificationMethod(this)
            Model = getSelectedData(this);
            openPoleZeroSimplificationTool(this.AppData,Model);            
        end                
        function callbackPostSet(this)
            % update table first
            updateUI(this);
            % hilite new plants
            newLabels = setdiff(this.getLabel(),this.TempLabels);
            if ~isempty(newLabels)
                hilite(this, newLabels);
            end
            this.TempLabels = [];
        end        
    end
    
end




