classdef AbstractPreferenceDlg < handle
    % @PreferenceDlg defines preference dialog for PID Tuner

    % Author(s): R. Chen
    % Copyright 2009-2012 The MathWorks, Inc.
    
    properties
        
        ParentFigure
        BackgroundColor
        Width
        Height
        Handles

        DesignFocusContents = {'balanced','reference-tracking','disturbance-rejection'}
        IFormulaContents = {'ForwardEuler','BackwardEuler','Trapezoidal'};
        DFormulaContents = {'ForwardEuler','BackwardEuler','Trapezoidal'};
        
    end

    properties(SetObservable)
        
        PlotSettings                       
    
    end
    
    methods

        % Constructor
        function this = AbstractPreferenceDlg(color)
            this.BackgroundColor = color;
        end
        
        % refresh GUI
        function refresh(this, varargin)
            TunedColor = varargin{1};
            BaseColor = varargin{2};
            this.setPlotPreferences(TunedColor, BaseColor);
        end
        
        % set visibility
        function setVisible(this, Visible, fig)
            scrsz = get(fig,'position');
            center = [scrsz(1)+scrsz(3)/2 scrsz(2)+scrsz(4)/2];
            set(this.Handles.Figure,'Position',[center(1)-this.Width/2 center(2)-this.Height/2 this.Width this.Height]);
            this.layout;
            set(this.Handles.Figure,'Visible',Visible);
            this.ParentFigure = fig;
        end
        
    end
    
    methods (Hidden)
        
        function qeClickOKButton(this)
            this.apply;
            this.close;
        end
        
        function qeClickApplyButton(this)
            this.apply;
        end
        
        function qeClickCancelButton(this)
            this.close;
        end
        
    end
    
    methods (Access = protected, Abstract)
        build(this)
    end
    
    methods (Access = protected)

        function buildFigure(this)
            %% create figure
            fig = figure('Color',this.BackgroundColor,...
                 'WindowStyle','normal',...
                 'IntegerHandle','off', ...
                 'Menubar','None',...
                 'Toolbar','None',...
                 'DockControl','off',...
                 'Name',pidtool.utPIDgetStrings('cst','prefdlg_title'), ...
                 'NumberTitle','off', ...
                 'Visible','off', ...
                 'Resize','off', ...
                 'Tag','PreferenceDlg',...
                 'HandleVisibility','off');
            % set default dialog size
            set(fig,'units','character')
            % figure callbacks
            set(fig,'CloseRequestFcn',@(x,y) close(this));
            % store handle
            this.Handles.Figure = fig;
        end
        
        function buildColorPanel(this)        
            % preference
            Prefs = cstprefs.tbxprefs;
            % common properties of GBC
            GBc = java.awt.GridBagConstraints;
            GBc.insets = java.awt.Insets(10,5,10,5);
            GBc.fill = java.awt.GridBagConstraints.HORIZONTAL;
            % panel
            Panel = javaObjectEDT('com.mathworks.mwswing.MJPanel');
            titleborder = javaMethodEDT('createTitledBorder','javax.swing.BorderFactory',pidtool.utPIDgetStrings('cst','prefdlg_title'));
            javaObjectEDT(titleborder);
            Panel.setBorder(titleborder);
            Panel.setLayout(java.awt.GridBagLayout);
            Panel.setFont(Prefs.JavaFontB);            
            % row 1: 
            TunedColorLabel = javaObjectEDT('com.mathworks.mwswing.MJLabel');
            TunedColorLabel.setName('PREFERENCEDLG_TUNEDCOLORLABEL');
            TunedColorLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
            GBc.gridx = 0;
            GBc.weightx = 0;
            GBc.gridy = 0;
            GBc.anchor = java.awt.GridBagConstraints.EAST;
            Panel.add(TunedColorLabel,GBc);
            TunedColorColorPicker = javaObjectEDT('com.mathworks.mlwidgets.graphics.ColorPicker',...
                com.mathworks.mlwidgets.graphics.ColorPicker.NO_OPTIONS,...
                com.mathworks.mlwidgets.graphics.ColorPicker.LINE_ICON,...
                'Color');
            TunedColorColorPicker.setName('PREFERENCEDLG_TUNEDCOLORCOMBOBOX');
            GBc.gridx = 1;
            GBc.weightx = 1;
            GBc.gridy = 0;
            GBc.anchor = java.awt.GridBagConstraints.WEST;
            GBc.fill = java.awt.GridBagConstraints.NONE;
            Panel.add(TunedColorColorPicker,GBc);
            % row 2: 
            BaseColorLabel = javaObjectEDT('com.mathworks.mwswing.MJLabel');
            BaseColorLabel.setName('PREFERENCEDLG_BLOCKCOLORLABEL');
            BaseColorLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
            GBc.gridx = 0;
            GBc.weightx = 0;
            GBc.gridy = 1;
            GBc.anchor = java.awt.GridBagConstraints.EAST;
            Panel.add(BaseColorLabel,GBc);
            BaseColorColorPicker = javaObjectEDT('com.mathworks.mlwidgets.graphics.ColorPicker',...
                com.mathworks.mlwidgets.graphics.ColorPicker.NO_OPTIONS,...
                com.mathworks.mlwidgets.graphics.ColorPicker.LINE_ICON,...
                'Color');
            BaseColorColorPicker.setName('PREFERENCEDLG_BLOCKCOLORCOMBOBOX');
            GBc.gridx = 1;
            GBc.weightx = 1;
            GBc.gridy = 1;
            GBc.anchor = java.awt.GridBagConstraints.WEST;
            GBc.fill = java.awt.GridBagConstraints.NONE;
            Panel.add(BaseColorColorPicker,GBc);
            %
            this.Handles.ColorPanel = Panel;
            this.Handles.TunedColorLabel = TunedColorLabel;
            this.Handles.TunedColorColorPicker = TunedColorColorPicker;
            this.Handles.BaseColorLabel = BaseColorLabel;
            this.Handles.BaseColorColorPicker = BaseColorColorPicker;
        end
        
        function buildButtonPanel(this)        
            %% Button Panel
            ButtonPanel = uipanel('parent',this.Handles.Figure,'bordertype','none','units','character','BackgroundColor', this.BackgroundColor);
            % CSH
            CSHButton = javaObjectEDT('com.mathworks.mwswing.MJButton',...
                javaObjectEDT('javax.swing.ImageIcon',fullfile(matlabroot,'toolbox','matlab','icons','csh_icon.png')));
            CSHButton.setName('PREFERENCEDLG_CSHBUTTON');
            CSHButton.setFlyOverAppearance(true);
            CSHButton.setFocusTraversable(false);
            [~, CSHButtonCONTAINER] = matlab.ui.internal.JavaMigrationTools.suppressedJavaComponent(CSHButton,[.1,.1,.9,.9],ButtonPanel);
            set(CSHButtonCONTAINER,'units','character')
            % OK
            OKButton = javaObjectEDT('com.mathworks.mwswing.MJButton',pidtool.utPIDgetStrings('cst','button_ok'));
            OKButton.setName('PREFERENCEDLG_OKBUTTON');
            [~, OKButtonCONTAINER] = matlab.ui.internal.JavaMigrationTools.suppressedJavaComponent(OKButton,[.1,.1,.9,.9],ButtonPanel);
            set(OKButtonCONTAINER,'Position',[0 0 OKButton.getPreferredSize.getWidth OKButton.getPreferredSize.getHeight]);
            set(OKButtonCONTAINER,'units','character');
            % Cancel
            CancelButton = javaObjectEDT('com.mathworks.mwswing.MJButton',pidtool.utPIDgetStrings('cst','button_cancel'));
            CancelButton.setName('PREFERENCEDLG_CANCELBUTTON');
            [~, CancelButtonCONTAINER] = matlab.ui.internal.JavaMigrationTools.suppressedJavaComponent(CancelButton,[.1,.1,.9,.9],ButtonPanel);
            set(CancelButtonCONTAINER,'Position',[0 0 CancelButton.getPreferredSize.getWidth CancelButton.getPreferredSize.getHeight]);
            set(CancelButtonCONTAINER,'units','character')
            % Apply
            ApplyButton = javaObjectEDT('com.mathworks.mwswing.MJButton',pidtool.utPIDgetStrings('cst','button_apply'));
            ApplyButton.setName('PREFERENCEDLG_APPLYBUTTON');
            [~, ApplyButtonCONTAINER] = matlab.ui.internal.JavaMigrationTools.suppressedJavaComponent(ApplyButton,[.1,.1,.9,.9],ButtonPanel);
            set(ApplyButtonCONTAINER,'Position',[0 0 ApplyButton.getPreferredSize.getWidth ApplyButton.getPreferredSize.getHeight]);
            set(ApplyButtonCONTAINER,'units','character')
            % Button Callbacks
            h = handle(CSHButton,'callbackproperties');
            hListener = handle.listener(h, 'ActionPerformed',{@CSHButtonCallback this});
            this.Handles.CSHButtonListener = hListener;
            h = handle(OKButton,'callbackproperties');
            hListener = handle.listener(h, 'ActionPerformed',{@OKButtonCallback this});
            this.Handles.OKButtonListener = hListener;
            h = handle(CancelButton,'callbackproperties');
            hListener = handle.listener(h, 'ActionPerformed',{@CancelButtonCallback this});
            this.Handles.CancelButtonListener = hListener;
            h = handle(ApplyButton,'callbackproperties');
            hListener = handle.listener(h, 'ActionPerformed',{@ApplyButtonCallback this});
            this.Handles.ApplyButtonListener = hListener;
            %
            this.Handles.ButtonPanel = ButtonPanel;
            this.Handles.CSHButtonCONTAINER = CSHButtonCONTAINER;
            this.Handles.OKButtonCONTAINER = OKButtonCONTAINER;
            this.Handles.CancelButtonCONTAINER = CancelButtonCONTAINER;
            this.Handles.ApplyButtonCONTAINER = ApplyButtonCONTAINER;
        end
        
        function setPlotPreferences(this, TunedColor, BaseColor)
            jcolor = java.awt.Color(TunedColor(1),TunedColor(2),TunedColor(3));
            this.Handles.TunedColorColorPicker.setValue(jcolor);
            jcolor = java.awt.Color(BaseColor(1),BaseColor(2),BaseColor(3));
            this.Handles.BaseColorColorPicker.setValue(jcolor);
        end
        
        function layout(this)
            p = get(this.Handles.Figure,'Position');
            fw = p(3);  fh = p(4);
            set(this.Handles.ButtonPanel,'Position',[0, 0, fw, 3]);
            set(this.Handles.CSHButtonCONTAINER,'Position',[1,0.5,5,2]);
            
            pb = [get(this.Handles.OKButtonCONTAINER,'Position');
                get(this.Handles.CancelButtonCONTAINER,'Position');
                get(this.Handles.ApplyButtonCONTAINER,'Position')];
            bw = max(pb(:,3));  bh = 2;
            sw = 1;             ew = 2;
            
            set(this.Handles.OKButtonCONTAINER,'Position',[fw-(3*bw+2*sw+ew),0.5,bw,bh]);
            set(this.Handles.CancelButtonCONTAINER,'Position',[fw-(2*bw+1*sw+ew),0.5,bw,bh]);
            set(this.Handles.ApplyButtonCONTAINER,'Position',[fw-(bw+ew),0.5,bw,bh]);
            
            set(this.Handles.PanelCONTAINER,'Position',[2, 3, fw-4, max(0.01,fh-3.5)]);
        end

        function apply(this)
            % obtain current settings
            TunedColor = this.Handles.TunedColorColorPicker.getValue;            
            BaseColor = this.Handles.BaseColorColorPicker.getValue;            
            % update PlotSettings property
            this.PlotSettings = struct( ...
                'TunedColor',[TunedColor.getRed,TunedColor.getGreen,TunedColor.getBlue]/255,...
                'BaseColor',[BaseColor.getRed,BaseColor.getGreen,BaseColor.getBlue]/255);
        end
        
        function close(this)
            try %#ok<*TRYNC>
                set(this.Handles.Figure,'Visible','off');
            end
        end
    end
    
end

%% Callback
function CSHButtonCallback(hObject,eventdata,this) %#ok<*INUSD>
    helpview(fullfile(docroot,'csh_icon_message.html'),'CSHelpWindow');
end

function OKButtonCallback(hObject,eventdata,this) %#ok<*INUSL>
    this.apply;
    this.close;
end

function CancelButtonCallback(hObject,eventdata,this) %#ok<*INUSL>
    this.close;
end

function ApplyButtonCallback(hObject,eventdata,this) %#ok<*INUSL>
    this.apply;
end

