function hilite_system(sys,hilite,varargin)
%HILITE_SYSTEM Highlight a Simulink object.
%   HILITE_SYSTEM(SYS) highlights a Simulink object by first opening the system
%   window that contains the object and then highlighting the object using the
%   HiliteAncestors property.
%
%   You can specify the highlighting options as additional right hand side
%   arguments to HILITE_SYSTEM.  Options include:
%
%     default     highlight with the 'default' highlight scheme
%     none        turn off highlighting
%     find        highlight with the 'find' highlight scheme
%     unique      highlight with the 'unique' highlight scheme
%     different   highlight with the 'different' highlight scheme
%     user1       highlight with the 'user1' highlight scheme
%     user2       highlight with the 'user2' highlight scheme
%     user3       highlight with the 'user3' highlight scheme
%     user4       highlight with the 'user4' highlight scheme
%     user5       highlight with the 'user5' highlight scheme
%
%   To alter the colors of a highlighting scheme, use the following command:
%
%     set_param(0, 'HiliteAncestorsData', HILITEDATA)
%
%   where HILITEDATA is a MATLAB structure array with the following fields:
%
%     HiliteType       one of the highlighting schemes listed above
%     ForegroundColor  a color string (listed below)
%     BackgroundColor  a color string (listed below)
%
%   Available colors to set are 'black', 'white', 'red', 'green', 'blue',
%   'yellow', 'magenta', 'cyan', 'gray', 'orange', 'lightBlue', and
%   'darkGreen'.
%  
%   Examples:
%
%       % highlight the subsystem 'f14/Controller/Stick Prefilter'
%       hilite_system('f14/Controller/Stick Prefilter')
%
%       % highlight the subsystem 'f14/Controller/Stick Prefilter'
%       % in the 'error' highlighting scheme.
%       hilite_system('f14/Controller/Stick Prefilter', 'error')
%
%   See also OPEN_SYSTEM, FIND_SYSTEM, SET_PARAM

%   Copyright 1990-2018 The MathWorks, Inc.

%
% massage the input data for easier management below:
%   chars  --> cell arrays
%   scalar --> vector of length 2 with repeat of scalar (a hack, yes, but
%              it does make things simpler...)
%
blockPath = [];
if nargin > 0
    if(isa(sys,'Simulink.BlockPath'))
        blockPath = sys;
        sys = blockPath.convertToCell();
        blockPath.openParent('force','on','openType','NEW_TAB'); % open parent. also make sure the model is loaded
    end
    sys = convertStringsToChars(sys);
end

if nargin > 1
    hilite = convertStringsToChars(hilite);
end

if nargin > 2
    [varargin{:}] = convertStringsToChars(varargin{:});
end
    
if ischar(sys)
  sys = { sys, sys };
elseif iscell(sys) && (length(sys) == 1)
  sys = { cell2mat(sys(1)), cell2mat(sys(1)) };
elseif isreal(sys) && (length(sys) == 1)
  sys = [sys sys];
elseif isa(sys,'Simulink.ObjectRef') && (length(sys) == 1)
  sys = [sys sys];
end

%
% it's easier to use handles instead of strings, it simplifies things
% in the code below
%
sys = get_param(sys,'Handle');
sys = [ sys{:} ];

% Unfortunately, port highlighting is currently not 
% supported. If possible, we use a connected segment.
% Otherwise, we return unsuccessfully. See g411096.
ports = find(strcmp(get_param(sys,'type'),'port'));
if(~isempty(ports))
    portLines =  get_param(sys(ports),'Line');
    if(~eq(portLines{1}, -1) && ~eq(portLines{2},-1))
        if iscell(portLines)
          sys(ports) = [ portLines{:} ];
        else
          sys(ports) = portLines;
        end
    else
        return;
    end
end

%
% construct a list of parent windows for each of the specified objects
%
parents = get_param(sys,'Parent');

%
% weed out objects with no parent, they're models
%
mdls = find(strcmp(parents,''));
parents(mdls) = [];
sys(mdls) = [];

% weed out objects in models being closed
numParents = length(parents);
for pIdx = numParents : -1 : 1
    parent = parents{pIdx};
    isClosing = slInternal('isBDClosing', bdroot(parent));
    if isClosing
        parents(pIdx) = [];
        sys(pIdx) = [];
    end
end

if(isempty(blockPath))
    open_system(unique(parents), 'force');
end

%
% set the HiliteAncestors property for each of the blocks
%
if nargin == 1
  hilite = 'on';
end

hiliteArgs = { 'HiliteAncestors', hilite };

%
% for each 'sys', set the HiliteAncestors property
%
for i = 1:length(sys)
  set_param(sys(i), hiliteArgs{:},varargin{:});
end

% Scroll and zoom the window so that our objects are visible.  Don't allow
% the window to zoom out to more than 100% (for backwards compatibility).
Simulink.scrollToVisible(sys, 'ensureFit', 'off', 'panMode', 'minimal');
