function varargout = menueditfunc(whichcall, varargin)
%MENUEDITFUNC  Support function for GUIDE Menu Editor

%   Copyright 1984-2019 The MathWorks, Inc.

  switch whichcall
    case 'getMenuStructure'
      menuRoot = newMenuNode;
      cmnuRoot = newMenuNode;
      meditor = varargin{2};
      show = get(0, 'showhiddenhandles');
      set(0, 'showhiddenhandles', 'on');
      tail = getMenuStructure(varargin{1}, menuRoot, 1, 0,0, meditor);
      tail = getMenuStructure(varargin{1}, cmnuRoot, 1, 1,tail,meditor);
      set(0, 'showhiddenhandles', show);
      varargout{1} = requestJavaAdapter(varargin{1});
      varargout{2} = menuRoot;
      varargout{3} = cmnuRoot;
      varargout{4} = num2str(tail);

    case 'getMenuHandles'
      parent = varargin{1};
      show = get(0, 'showhiddenhandles');
      set(0, 'showhiddenhandles', 'on');
      varargout{1} = getMenuHandles(parent);
      set(0, 'showhiddenhandles', show);

    case 'doNewMenu'
      parent = varargin{1};
      label = varargin{2};
      meditor = varargin{3};
      newMenu = uimenu(parent, 'label', label);
      set(newMenu,'callback',guidemfile('AUTOMATIC'));
      set(newMenu,'tag',strrep(label,' ', '_'));
      guidefunc('initLastValidTag', newMenu);
      adapter = requestJavaAdapter(newMenu);
      varargout{1} = newMenuNode(1, newMenu, adapter, meditor);
      varargout{2} = adapter;
      varargout{3} = requestJavaAdapter(parent);

    case 'doNewContextMenu'
      parent = varargin{1};
      tag = varargin{2};
      meditor = varargin{3};
      newCMenu = uicontextmenu('parent', parent, 'tag', tag);
      set(newCMenu,'callback',guidemfile('AUTOMATIC'));
      set(newCMenu,'tag',strrep(tag,' ', '_'));
      guidefunc('initLastValidTag', newCMenu);
      adapter = requestJavaAdapter(newCMenu);
      varargout{1} = newMenuNode(2, newCMenu, adapter,meditor);
      varargout{2} = adapter;
      varargout{3} = requestJavaAdapter(parent);

    case 'getCMenuData'
      [varargout{1}, varargout{2}] = getCMenuData(varargin{1});

    case 'doSetProperty'
      menu = varargin{1};
      if ishandle(menu)
          if strcmpi(char(varargin{2}), 'Callback')
            %need to set the old callback format on object              
            value = guidemfile('toggelGeneratedCallbackSignature',menu,varargin{2},varargin{3},false);                  
            guidemfile('setAutoGeneratedCallbackString',menu,varargin{2},value);
          else
            set(menu,varargin{2},varargin{3});
          end
      end

    case 'doGetProperty'
      varargout{1} = getProperty(varargin{1});
        
    case 'doMoveUp'
      fig = varargin{1};
      item = varargin{2};
      parent = get(item,'Parent');
      if (parent == fig)
        % move in the same group
        uistack(item,'down');
      else
        children = allchild(parent);
        location = find(ismember(children,item));

        if (location + 1 <= length(children))
            % move in the same group
            uistack(item,'down');
        else
            % move out of the current group
            % move in the next group
           parents = findobj(get(get(parent,'parent'),'Children'), 'flat', 'type', get(parent,'type'));
           plocation = find(ismember(parents,parent));
           set(item,'parent',parents(plocation+1));

           uistack(item,'top');
        end
      end

      varargout{1} = 0;

    case 'doMoveDown'
      fig = varargin{1};
      item = varargin{2};
      parent = get(item,'Parent');
      if (parent == fig)
        % move in the same group
        uistack(item,'up');
      else
        children = allchild(parent);
        location = find(ismember(children,item));

        if (location - 1 >= 1)
            % move in the same group
            uistack(item,'up');
        else
            % move out of the current group
            % move in the next group
           parents = findobj(get(get(parent,'parent'),'Children'), 'flat', 'type', get(parent,'type'));
           plocation = find(ismember(parents,parent));
           set(item,'parent',parents(plocation-1));

           uistack(item,'bottom');
        end
      end

      varargout{1} = 0;

    case 'doMoveBackward'
      fig = varargin{1};
      item = varargin{2};
      parent = get(item,'Parent');

      parents = findobj(get(get(parent,'parent'),'Children'), 'flat', 'type', get(parent,'type'));
      plocation = find(ismember(parents,parent));
      set(item,'parent',get(parent,'parent'));

      uistack(item,'bottom');

      uistack(item,'up', length(parents)+1 - plocation);

      varargout{1} = 0;

    case 'doMoveForward'
      fig = varargin{1};
      item = varargin{2};
      parent = get(item,'Parent');

      children = findobj(get(parent,'Children'), 'flat', 'type', get(item,'type'));
      mylocation = find(ismember(children,item));
      set(item,'parent',children(mylocation + 1));

      uistack(item,'top');

      varargout{1} = 0;
      
    case 'viewCallback'
      guidefunc('editCallback',varargin{:});
     
    case 'updateTag'
      menu = varargin{1};
      newTag = varargin{2};
      if ~isempty(menu)
          for i=1:length(menu)
            set(menu{i},'Tag',newTag);
            types{i} = get(menu{i},'type');
          end

          %update GUI MATLAB code file
          guidefunc('updateTag',menu, types, types);
      end
  end

%************************************************
function start = getMenuStructure(handle, node, isRoot, isCMenu, startNum, meditor)
  start=startNum;
  if (isCMenu)
    % get the uicontextmenus
    if (isRoot)
      menus = findobj(allchild(handle), 'flat', 'type', 'uicontextmenu','serializable', 'on');
      for i = length(menus):-1:1
        adapter = requestJavaAdapter(menus(i));
        child = newMenuNode(2, menus(i), adapter,meditor);
        node.addChild(child);
        tail = getUntitledTail(menus(i));
        if (tail > start)
            start = tail;
        end
        start = getMenuStructure(menus(i), child, 0, 0, start, meditor);
      end
    end
  else
    if (isRoot)
      menus = findobj(allchild(handle), 'flat', 'type', 'uimenu', 'serializable', 'on');
    else
      menus = get(handle, 'children');
    end

    % get the uimenus
    for i = length(menus):-1:1
      adapter = requestJavaAdapter(menus(i));
      child = newMenuNode(1, menus(i), adapter,meditor);
      node.addChild(child);
        tail = getUntitledTail(menus(i));
        if (tail > start)
            start = tail;
        end
      start = getMenuStructure(menus(i), child, 0, 0, start,meditor);
    end
  end

%************************************************
% have to use the fully qualified path to
% MenuNode because just using MenuNode(type, adapter)
% attempts to call a method "MenuNode" on the
% object "adapter", rather than calling the constructor
% of "MenuNode" with "adapter" as an argument
function node = newMenuNode(varargin)
  if (nargin == 0)
    node = com.mathworks.toolbox.matlab.guide.menueditor.MenuNode;
  else
    hndl = double(varargin{2});
    node = com.mathworks.toolbox.matlab.guide.menueditor.MenuNode(varargin{1}, ...
                                                        hndl, ...
                                                        varargin{3}, ...
                                                        varargin{4});
  end

%************************************************
function [names, handles] = getCMenuData(adapter)
  fig = getEnclosingFigure(double(handle(adapter)));
  handles = findobj(allchild(fig), 'flat', 'type', 'uicontextmenu');
  names = get(handles, 'tag');

%************************************************
function fig = getEnclosingFigure(fig)
  while ~isempty(fig) & ~strcmp(get(fig, 'type'), 'figure'),
    fig = get(fig, 'parent');
  end;

function tail = getUntitledTail(handle)

tail=0;
tag = [];
try tag = get(handle,'Tag'); catch end
if (~isempty(tag))
    where = findstr('Untitled',tag);
    wherel = findstr('Untitled_',tag);
    if (~isempty(wherel))
        number = str2num(tag(length('Untitled_')+1:length(tag)));
        if (~isempty(number) & number > tail)
            tail = number;
        end
    else
        if (~isempty(where))
            number = str2num(tag(length('Untitled')+1:length(tag)));
            if (~isempty(number) & number > tail)
                tail = number;
            end
        end
    end
end

tag = [];
try tag = get(handle,'Label'); catch end
if (~isempty(tag))
    where = findstr('Untitled',tag);
    wherel = findstr('Untitled_',tag);
    if (~isempty(wherel))
        number = str2num(tag(length('Untitled_')+1:length(tag)));
        if (~isempty(number) & number > tail)
            tail = number;
        end
    else
        if (~isempty(where))
            number = str2num(tag(length('Untitled')+1:length(tag)));
            if (~isempty(number) & number > tail)
                tail = number;
            end
        end
    end
end

function out = getProperty(handle)

properties = get(handle);
name = fieldnames(properties);
value = get(handle,name)';

% The 'Label' and 'Callback' properties for uimenu have been deprecated and
% replaced by the new 'Text' and 'MenuSelectedFcn' properties. 'Label' and
% 'Callback' still exist and are alias for the new properties but they are 
% now hidden and no longer returned by 'get(uimenuHandle)'. GUIDE's menu
% editor Java code relies on this function returning 'Label' and
% 'Callback' as properties of uimenu and so replace 'Text' with 'Label' and
% 'MenuSelectedFcn' with 'Callback'. This is the lease invasive fix for
% g1555876.
name = strrep(name,'Text','Label');
name = strrep(name,'MenuSelectedFcn','Callback');

% UIContextMenu property rename
% 'Callback' renamed to 'ContextMenuOpeningFcn'
% g2098156
name = strrep(name,'ContextMenuOpeningFcn','Callback');

%callback value is function handle now, change to string
index=find(ismember(name,'Callback'));
if ~isempty(index)
    value{index} = guidemfile('getAutoGeneratedCallbackString',handle,'Callback');
    %need to display the new format in menu editor
    value{index} = guidemfile('toggelGeneratedCallbackSignature',handle,'Callback',value{index},true);    
end

% Replace matlab.lang.OnOffSwitchState with char array 'on' or 'off' (g2157944)
for i=1:length(value)
    if isa(value{i}, 'matlab.lang.OnOffSwitchState')
        value{i} = char(value{i});
    end
end

out = {name value};


function menus = getMenuHandles(menuparent)

if strcmpi(get(menuparent,'Type'),'figure')
    menus = findobj(allchild(menuparent), 'flat', 'type', 'uimenu', 'serializable', 'on');
    menus = [menus; findobj(allchild(menuparent), 'flat', 'type', 'uicontextmenu','serializable', 'on')];
else
    menus = findobj(get(menuparent,'Children'), 'serializable', 'on');
end

menus = flipud(menus);

children = [];
if ~isempty(menus)
    for i=1:length(menus)
        children = [children; getMenuHandles(menus(i))];
    end
    menus = [menus; children];
end
