function [h,menu_strs] = render_menus(hFig,ud)
%RENDER_MENUS   Render the menus for the Filter Designer.
%
%   Inputs:
%     hFig - Handle to the current figure
%     ud   - GUI's data structure stored in the figure's userdata
%
%   Outputs:
%     h  - structure containing arrays of handles
%     menu_strs - structure:
%     menu_strs.type.common - cell array containing the common filter type strs
%     menu_strs.type.other - cell array containing the other filter type strs
%     menu_strs.method.fir - cell array containing the fir design methods
%     menu_strs.method.iir - cell array containing the iir design methods
%     menu_strs.method.window - cell array containing the windows avail. for fir window design

%   Author(s): P Pacheco R. Losada
%   Copyright 1988-2000 The MathWorks, Inc.
%   $Revision: 1.16 $  $Date: 2000/08/30 18:53:47 $ 

% Flag indicating if the Filter Design Tbx is installed.
fdqexists = ud.flags.fdqexists;

[h,menus] = render_main_menu(hFig);
h = render_file_menu(h,menus);
[h,type_menu_items,other_type_items] = render_type_menu(h,menus,fdqexists);
[h,fir_methods,iir_methods,fir_window_methods] = ...
                          render_method_menu(h,menus,fdqexists);
h = render_analysis_menu(h,menus,hFig,ud);
h = render_filter_menu(h,menus);
% h = render_code_menu(h,menus);
render_window_menu(hFig);
h = render_help_menu(h,menus);

% generate menu strings
menu_strs = gen_menu_strs(type_menu_items,other_type_items,...
    fir_methods,iir_methods,fir_window_methods);
%------------------------------------------------------------------------
function [h,menus] = render_main_menu(hFig)

% Set up main menus
menus = {...
        '&File',...
        'F&ilter',...
        '&Type',...
        '&Method',...
        '&Analysis',...
        '&Window',...
        '&Help'};
callbacks = {[],[],[],[],[],'winmenu(gcbo);',[]};
tags = {'file',...
        'filter',...
        'type',...
        'method',...
        'analysis',...
        'winmenu',...
        'help'};

for i=1:length(menus),
    h.main(i) = uimenu(hFig,'label',menus{i},...
        'tag',tags{i}, ...
 	    'Callback',callbacks{i});
end

% ----------------------------------------------------------------------
function h = render_file_menu(h,menus)
% string to look for
str2match = '&File';

% setup File menu items. 
file_menu_items = {...
        '&New Session',...
        '&Open Session',...
        '&Save Session',...
        'Save Session &As...',...      
        '&Export...',...
        '&Print',...
        'Close'}; % Used to be exit
tags = {...
        'new',...
        'open',...
        'save',...
        'saveas',...
        'export',...
        'print',...
        'exit'};
      
menuscbs = menus_cbs;  % get structure of all local callback functions
file_cbStr = {...
       menuscbs.new_cb,...
       menuscbs.open_cb,...
       menuscbs.save_cb,...
       menuscbs.saveas_cb,...
       menuscbs.export_cb,...
       menuscbs.print_cb,...
       menuscbs.exit_cb};
accelerators = {...,
        'n',...
        'o',...
        's',...
        '',...
        'e',...
        'p',...
        ''};
% indicate which items have separators and which don't
separator_indx = [5 6 7];


h.file = add_menu_items(tags,h.main,str2match,menus,...
    file_menu_items,file_cbStr,separator_indx,accelerators);
    
%------------------------------------------------------------------------
function h = render_filter_menu(h,menus)

str2match = 'F&ilter';

% Menu choices.
menuChoices = {...
        '&Design Filter',...
        '&Import Filter',...
        '&Undo Changes'};

tags = {'design','specifycoef','undochanges'};

accelerators = {...,
        'd',...
        'i',...
        'u'};

% indicate which items have separators and which don't
separator_indx = [3];

% Share the callback function of the mode (tab) buttons.
menuscbs = menus_cbs;  % get structure of all local callback functions
filter_cbStr = { {@modebtns_cbs,1},{@modebtns_cbs,2}, {menuscbs.undochanges_cb}};

% Add menu choices.
h.filter = add_menu_items(tags,h.main,str2match,menus,...
    menuChoices,filter_cbStr,separator_indx,accelerators);

%-----------------------------------------------------------------------
function [h,type_menu_items,other_type_items] =  render_type_menu(...
                                                      h,menus,fdqexists)

% look for position of handle to the type menu
str2match = '&Type';

% setup type menu items. 
type_menu_items = {...
        '&Lowpass',...
        '&Highpass',...
        '&Bandpass',...
        'Band&stop',...
        '&Other'};

tags = {...
        'lp',...
        'hp',...
        'bp',...
        'bs',...
        ''};

menuscbs = menus_cbs;  % get structure of all local callback functions
type_cbStr = {...
        menuscbs.type_menu, ...
        menuscbs.type_menu, ...
        menuscbs.type_menu, ...
        menuscbs.type_menu, ...
        []};

accelerators = {...
        'l',...
        'h',...
        'b',...
        't',...
        ''};
    
% add items to the type menu
h.type = add_menu_items(tags,h.main,str2match,menus,...
    type_menu_items,type_cbStr,0,accelerators);

% Render the other filter types
[h,other_type_items] = render_other_types(...
                                h,type_menu_items,type_cbStr,fdqexists);

% ---------------------------------------------------------------------
function [h,other_type_items] = render_other_types(...
                                h,type_menu_items,type_cbStr,fdqexists)

% look for position of handle to the 'other' item
str2match = '&Other';

if fdqexists,
    other_type_items = {...
            '&Differentiator',...
            '&Hilbert Transformer',...
            '&Multiband',...
            '&Arbitrary Magnitude',...
            'Arbitrary &Group Delay'};
    separator_indx = [3,4,6,8,11,12];
    tags = {...
            'diff',...
            'hilb',...
            'multiband',...
            'arbitrarymag',...
            'arbitrarygrp'};
else
    other_type_items = {...
            '&Differentiator',...
            '&Hilbert Transformer',...
            '&Multiband',...
            '&Arbitrary Magnitude'};
    separator_indx = [3,4,5,6,7,8];
    tags = {...
            'diff',...
            'hilb',...
            'multiband',...
            'arbitrarymag'};
end

menuscbs = menus_cbs;  % get structure of all local callback functions
other_type_cbStr = { menuscbs.type_menu };

% add other items 
h.other_type = add_menu_items(tags,h.type,str2match,...
    type_menu_items,other_type_items,other_type_cbStr,separator_indx);
       

%----------------------------------------------------------------------
function [h,fir_methods,iir_methods,fir_window_methods] = ...
    render_method_menu(h,menus,fdqexists)
% look for position of handle to the method menu
str2match = '&Method';

% setup method menu items. 
method_menu_items = {'&FIR','&IIR'};

tags = {'fir','iir'};

method_cbStr = {[]};

% add method menu items
h.method = add_menu_items(tags,h.main,str2match,menus,...
    method_menu_items,method_cbStr);

% add FIR & IIR methods
[h,fir_methods,fir_window_methods] = render_fir_methods(...
                                       h,method_menu_items,fdqexists);
[h,iir_methods] = render_iir_methods(h,method_menu_items,fdqexists);

%----------------------------------------------------------------------
function [h,fir_methods,fir_window_methods] = render_fir_methods(...
    h,method_menu_items,fdqexists)

% search for position of handle to FIR item
str2match = '&FIR';

if fdqexists,
    fir_methods = {...
            '&Equiripple',...
            '&Least-Squares',...
            '&Window'};
    tags = {...
            'remez',...           
            'firls',...
            'fir1'};
	menuscbs = menus_cbs;  % get structure of all local callback functions
    fir_cbStr = {...
            menuscbs.method_menu,...
            menuscbs.method_menu,...
            []};

else
     fir_methods = {...
            '&Equiripple',...
            '&Least-Squares',...
            '&Window'};
    tags = {...
            'remez',...
            'firls',...
            'fir1'};
		menuscbs = menus_cbs;  % get structure of all local callback functions
        fir_cbStr = {...
            menuscbs.method_menu,...
            menuscbs.method_menu,...
            []};
end	

% add FIR items
h.fir_methods = add_menu_items(tags,h.method,str2match,...
    method_menu_items,fir_methods,fir_cbStr);
        
% add the windows for the window method
[h,fir_window_methods] = render_window_methods(h,fir_methods,fdqexists);

%------------------------------------------------------------------------
function [h,fir_window_methods] = render_window_methods(h,fir_methods,fdqexists)

% search for position of handle to window FIR
str2match = '&Window';

% setup window methods

fir_window_methods = {...
        '&Chebyshev',...
        '&Kaiser',...
        '&Bartlett',...
        'B&lackman',...
        'Bo&xcar',...
        '&Hamming',...
        'Ha&nn',...
        'Trian&gular'};
% separators for window items
separator_indx = [3];

tags = {...
        'chebwin',...
        'kaiser',...
        'bartlett',...
        'blackman',...
        'boxcar',...
        'hamming',...
        'hann',...
        'triang'};

menuscbs = menus_cbs;  % get structure of all local callback functions
firwin_cbStr = { menuscbs.method_menu };

h.fir_window_methods = add_menu_items(tags,h.fir_methods,...
    str2match,fir_methods,fir_window_methods,firwin_cbStr,separator_indx);


%------------------------------------------------------------------------
function [h,iir_methods] = render_iir_methods(h,method_menu_items,fdqexists)
% search for position of handle to IIR item
str2match = '&IIR';

if fdqexists,
    iir_methods = {...
            '&Butterworth',...
            'Cheby&shev Type I',...
            'Chebyshev &Type II',...
            '&Constrained least Pth-norm',...
            '&Elliptic',...
            '&Least Pth-norm'};
    tags = {...
            'butter',...
            'cheb1',...
            'cheb2',...
            'iirlpnormc',...
            'ellip',...
            'iirlpnorm'};
else
    iir_methods = {...
            '&Butterworth',...
            'Cheby&shev Type I',...
            'Chebyshev &Type II',...
            '&Elliptic'};
    tags = {...
            'butter',...
            'cheb1',...
            'cheb2',...
            'ellip'};
end

menuscbs = menus_cbs;  % get structure of all local callback functions
iir_cbStr = { menuscbs.method_menu };

% add IIR items
h.iir_methods = add_menu_items(tags,h.method,str2match,...
    method_menu_items,iir_methods,iir_cbStr);


%------------------------------------------------------------------------
function h = render_analysis_menu(h,menus,hFig,ud)

str2match = '&Analysis';

% set view menu items
analysis_items = {...
        '&Filter Specifications',...
        '&Magnitude Response',...
        '&Phase Response',...
        'Magnitude &and Phase',...
        '&Group Delay',...
        '&Impulse Response',...
        '&Step Response',...
        'Pole/&Zero Plot',...
        '&View Filter Coefficients'};

tags = {ud.tags.analysis{1:9}};
        
% setup analysis menu separators
separator_indx = [2,5,6,8,9];

menuscbs = menus_cbs;  % get structure of all local callback functions
analysis_cbStr = {...
        menuscbs.filterspecs_cb,...
        menuscbs.magresp_cb,...
        menuscbs.phaseresp_cb,...
        menuscbs.magnphaseresp_cb,...
        menuscbs.groupdelay_cb,...
        menuscbs.impresp_cb,...
        menuscbs.stepresp_cb,...
        menuscbs.pzplot_cb,...
        menuscbs.filtercoeffs_cb};

accelerators = {...
        '1',...
        '2',...
        '3',...
        '4',...
        '5',...
        '6',...
        '7',...
        '8',...
        '9'};

% add analysis menu items
h.analysis = add_menu_items(tags,h.main,str2match,menus,...
    analysis_items,analysis_cbStr,separator_indx,accelerators);

% %------------------------------------------------------------------------
% function h = render_code_menu(h,menus)
% 
% str2match = '&Code';
% 
% % set code menu items
% code_items = {'&Generate M-code'};
% 
% tags = {'mcode'};
% 
% menuscbs = menus_cbs;  % get structure of all local callback functions
% code_cbStr = { menuscbs.mcode_cb };
% 
% % add code menu items
% h.code = add_menu_items(tags,h.main,str2match,menus,...
%     code_items,code_cbStr);
% 
%------------------------------------------------------------------------
function render_window_menu(hFig)

winmenu(hFig);  % Initialize the submenu

%------------------------------------------------------------------------
function h = render_help_menu(h,menus)

str2match = '&Help';

% List submenu items
help_items = {'FDATool &Help'....
		'Signal Processing &Toolbox Help',...
		'&What''s This?',...
		'&Importing Filters',...
		'&Exporting Filters',...
		'&Saving/Opening Sessions',...
		'&Demos',...
		'&About Signal Processing Toolbox'};

tags = {'toolhelp',...
		'producthelp',...
		'whatsthis',...
		'importhelp',...
		'exporthelp',...
		'saveopensessionhelp',...
		'demos',...
		'about'};

separator_indx = [3 4 7 8];

help_handles = fdatool_help;  % get structure of all local callback functions
help_cbStr = {help_handles.toolhelp_cb,...
		help_handles.producthelp_cb,...
		help_handles.HelpWhatsThis_cb,...
		help_handles.importhelp_cb,...
		help_handles.exporthelp_cb,...
		help_handles.saveopensessionshelp_cb,...
		help_handles.demos_cb,...
		help_handles.about_cb};

% Add submenus.
h.help = add_menu_items(tags,h.main,str2match,menus,...
    help_items,help_cbStr,separator_indx);

%------------------------------------------------------------------------
function menu_strs = gen_menu_strs(type_menu_items,other_type_items,...
    fir_methods,iir_methods,fir_window_methods)

menu_strs.type.common = {type_menu_items{1:end-1}};  % Don't include "Other"
menu_strs.type.other = other_type_items;
menu_strs.method.fir = fir_methods;
menu_strs.method.iir = iir_methods;
menu_strs.method.window = fir_window_methods;

% Remove the ampersands that are added to the strings used 
% for the menu accelerations.
menu_strs = cleanStrs(menu_strs);

%------------------------------------------------------------------------------------
function hndls_out = add_menu_items(tags,hndls_in,str2match,...
    stropts,items2add,cbStrs,separator_indx,accelerators)
%ADD_MENU_ITEMS   Add items to a menu or to a menu item
%
%   Inputs:
%     hndls     = vector of handles to the menus or menu items
%     str2match = The string to match against stropts
%     stropts   = cell of strings to match against
%     items2add = cell 0f items to add to the menu or menu item
%     cbStr     = a cell array of callback strings
%     separator_indx = (optional) a vector indicating the position of items 
%                       with separators
%     accelerators = (optional) ctrl- key accelerators.
%  Outputs:
%     handls_out = handles of menu items

% look for position of handle to the file menu
n = strmatch(str2match,stropts);

if nargin == 6,
    separator_indx = 0;
end

% Determine the number of callback strings being passed.
k = length(cbStrs);

for i = 1:length(items2add),
    if any(i == separator_indx),
        separator = 'on';
    else
        separator = 'off';
    end
    
    if nargin < 8,
        accelerators{i} = '';
    end
    
    % ONLY increment index into cbStr when there's more than one callback.
    if k == 1, cbStr = cbStrs{k}; 
    else       cbStr = cbStrs{i}; end 
    hndls_out(i) = uimenu(hndls_in(n),...
        'label',items2add{i},...
        'separator',separator,...
        'Callback',cbStr,...
        'Accelerator',accelerators{i},...
        'tag',tags{i});
end

%----------------------------------------------------------------------
function typesNmethods = cleanStrs(typesNmethods)
% CLEANSTRS - Strips the strings of ampersands (&) which are added to 
%             the menu strings.
% Inputs:
%   typesNmethods - a structure containing the list of filter types and 
%                   methods used in the Type and Method menus, but each 
%                   string could contain an ampersand used for the menu
%                   accelerations.
% Outputs:
%   typesNmethods - a structure containing the list of filter types and 
%                   methods used in the Type and Method menus, however, 
%                   the strings have been purged of ampersands.

typesNmethods.type.common = removeampersands(typesNmethods.type.common);
typesNmethods.type.other  = removeampersands(typesNmethods.type.other);
typesNmethods.method.iir  = removeampersands(typesNmethods.method.iir);
typesNmethods.method.fir  = removeampersands(typesNmethods.method.fir);
typesNmethods.method.window = removeampersands(typesNmethods.method.window);

% [EOF] render_menus.m

