classdef LogicAnalyzerGroup < dsp.AbstractLogicAnalyzerDisplay
%

%   Copyright 2016-2020 The MathWorks, Inc.

    properties
        Color = 'Default';
        
        Radix = 'Default';
        
        FontSize = 0;
        
        Format = 'Default';
        Children = {};
    end
    
    methods
        function this = LogicAnalyzerGroup(varargin)
            for indx = 1:2:nargin
                this.(varargin{indx}) = varargin{indx+1};
            end
        end
        
        function obj = set.Children(obj, children)
            if iscell(children)
                for indx = 1:numel(children)
                    if ~isa(children{indx}, 'dsp.AbstractLogicAnalyzerDisplay')
                        error(getString(message('Spcuilib:logicanalyzer:invalidGroupChildren')));
                    end
                end
            else
                error(getString(message('Spcuilib:logicanalyzer:invalidGroupChildren')));
            end
            obj.Children = children;
        end
        
        function obj = set.Color(obj, value)
            % Color can be one of the set specifiedy
            if ischar(value) || isstring(value)
                colorSet = getLogicAnalyzerDisplayColorSet;
                colorSet = {'Default', colorSet{:}}; %#ok<CCAT>
                value    = validatestring(value, colorSet, '', 'Color');
            end
            obj.Color = value;
        end % set.Color
        
        function obj = set.Radix(obj, value)
            % Radix must be one of 'Default' | 'Hexadecimal' | 'Octal' | 'Binary' |
            % 'Signed decimal' | 'Unsigned decimal'
            propName = 'Radix';
            radixSet = getLogicAnalyzerDisplayRadixSet;
            radixSet = {'Default', radixSet{:}}; %#ok<CCAT>
            obj.(propName) = validatestring(value, radixSet, '', propName);
        end
        
        function obj = set.FontSize(obj, value)
            % Height must be a non-negative scalar integer
            propName = 'FontSize';
            obj.validateScalarInteger(value, propName);
            obj.(propName) = value;
        end
        
        function obj = set.Format(obj, value)
            % Specify Format to be one of 'Default' | 'Automatic' |'Digital'| 'Analog'
            propName = 'Format';
            formatSet = getLogicAnalyzerDisplayFormatSet;
            formatSet = {'Default', formatSet{:}}; %#ok<CCAT>
            obj.(propName) = validatestring(value, formatSet, '', propName);
        end
    end
    
    methods (Static, Hidden)
        function validateScalarInteger(value, propName)
            % value of propname must be a scalar integer
            % non-negative and positi
            validateattributes(value, ...
                {'numeric'}, {'real','finite','scalar','integer','nonnegative'},'', ...
                propName);
        end

        function this = fromGraphicalSettings(gs, inputIds)
            inputs = {'Name', gs.name, ...
                 'Tag', sprintf('G%d', gs.instanceNumber)};
            if isfield(gs, 'height')
                inputs = [inputs {'Height', gs.height}];
            end
            if isfield(gs, 'radix')
                switch gs.radix
                    case 'unsigneddecimal'
                        radix = 'Unsigned decimal';
                    case 'signeddecimal'
                        radix = 'Signed decimal';
                    otherwise
                        radix = [upper(gs.radix(1)) gs.radix(2:end)];
                end
                inputs = [inputs {'Radix', radix}];
            end
            if isfield(gs, 'format')
                inputs = [inputs {'Format', [upper(gs.format(1)) gs.format(2:end)]}];
            end
            if isfield(gs, 'height')
                inputs = [inputs {'Height', gs.height}];
            end
            if isfield(gs, 'fontSize')
                inputs = [inputs {'FontSize', gs.fontSize}];
            end
            if isfield(gs, 'color')
                color = lower(gs.color);
                if strncmpi(color(1), '#', 1)
                    color = uiservices.hexColorToRGB(color);
                end
                inputs = [inputs {'Color', color}];
            end

            this = dsp.LogicAnalyzerGroup(inputs{:});
            if isfield(gs, 'subWaves')
                children = cell(1, numel(gs.subWaves));
                for indx = 1:numel(gs.subWaves)
                    if iscell(gs.subWaves)
                        sub = gs.subWaves{indx};
                    else
                        sub = gs.subWaves(indx);
                    end
                    switch sub.type
                        case 'wave'
                            c = 'dsp.LogicAnalyzerWave';
                        case 'divider'
                            c = 'dsp.LogicAnalyzerDivider';
                        case 'group'
                            c = 'dsp.LogicAnalyzerGroup';
                    end
                    children{indx} = feval([c '.fromGraphicalSettings'], sub, inputIds);
                end
                this.Children = children;
            end
        end
    end
    
    methods (Hidden)
        function s = struct(this)
            s = builtin('struct', this);
            s = rmfield(s, 'Children');
        end
        function gs = toGraphicalSettings(this, inputIds, varargin)
            gs = toGraphicalSettings@dsp.AbstractLogicAnalyzerDisplay(this, varargin{:});
            gs.type = 'group';
            if nargin < 3 || any(strcmp(varargin, 'Color'))
                color = this.Color;
                if strcmpi(color, 'default')
                    gs.color = 'default';
                elseif ischar(color)
                    gs.color = uiservices.stringColorToHexColor(color);
                else
                    gs.color = uiservices.rgbToHexColor(color);
                end
            end
            if nargin < 3 || any(strcmp(varargin, 'Format'))
                gs.format = lower(this.Format);
                if strcmp(gs.format, 'automatic')
                    gs.format = 'auto';
                end
            end
            if nargin < 3 || any(strcmp(varargin, 'Radix'))
                gs.radix = strrep(lower(this.Radix), ' ', '');
            end
            if nargin < 3 || any(strcmp(varargin, 'FontSize'))
                gs.fontSize = this.FontSize;
            end
            children = this.Children;
            for indx = 1:numel(children)
                children{indx} = children{indx}.toGraphicalSettings(inputIds, varargin{:});
            end
            if ~isempty(children)
                gs.subWaves = children;
            end
        end
        function tags = getAllTags(obj)
            children = obj.Children;
            tags{1} = obj.getTag;
            for indx = 1:numel(children)
                tags = [tags children{indx}.getAllTags()];
            end
        end
        function found = findByTag(obj, tag)
            if strcmpi(obj.getTag(), tag)
                found = obj;
            else
                children = obj.Children;
                for indx = 1:numel(children)
                    found = children{indx}.findByTag(tag);
                    if ~isempty(found)
                        return;
                    end
                end
                found = [];
            end
        end
    end
    
end
