File: ef230-2023-08/www/examples/better_menu_example.m Download
%| Better menu example
%| A simple alternative to MATLAB's menu command - centered and optional sizing
%  University of Tennessee : EF 230 Spring, 2013 : Will Schleter

function better_menu_example
% the main function is an example of how to use the txtmenu command
clear all; close all; clc;

% list of choices
names={'Prof Schleter','LazyDog','Everett','Stephen','Ryan'};
msg = 'Who do you want to kick off the island?';

% specify some options
opts.width = 400;
opts.msg_fontsize = 20;
opts.msg_fontname = 'Times';
opts.choice_fontsize = 15;
opts.msg_height = 30;
choice = better_menu(msg,names,opts);

if choice==0
    msg = 'Everyone lives to fight another day';
else
    msg=sprintf('Bye Bye %s',names{choice});
end
waitfor(msgbox(msg));
end


function choice = better_menu(msg,choices,opts)
% A simple replacement for MATLAB's menu command
% works by displaying a modal figure window with buttons
% the routine returns when the figure window is closed
% Advantage of MATLAB's menu command in are that the menu
% is centered on the screen and you can control is font and size

% Input: msg - text message to be displayed
%        choices - cell array of text choices
%        opts - optional structure to control the display of the menu (see below)
% Output: choice - integer - selection number, 0 if no selection made

if nargin<2
    error('txtmenu must have 2 inputs');
end

if nargin<3
    opts = struct([]); % empty structure
end

% default options
if ~isfield(opts,'width'), opts.width=100; end
if ~isfield(opts,'position'), opts.position=[]; end
if ~isfield(opts,'padding'), opts.padding=5; end
if ~isfield(opts,'shownums'), opts.shownums=0; end
if ~isfield(opts,'msg_height'), opts.msg_height=20; end
if ~isfield(opts,'msg_fontname'), opts.msg_fontname='Helvetica'; end
if ~isfield(opts,'msg_fontsize'), opts.msg_fontsize=12; end
if ~isfield(opts,'button_height'), opts.button_height=20; end
if ~isfield(opts,'button_fontname'), opts.button_fontname='Helvetica'; end
if ~isfield(opts,'button_fontsize'), opts.button_fontsize=12; end

% init
num = length(choices);
choice = 0;

% error check
if num==0
    error('Invalid input');
end

y = opts.msg_height + num*opts.button_height + (num+2)*opts.padding;

% set up a new window
screensize = get(0,'ScreenSize');
screenWidth = screensize(3);
screenHeight = screensize(4);
boxWidth = opts.width + 2*opts.padding + 4;
boxHeight = y + opts.padding + 42;
fig = dialog('position',[(screenWidth-boxWidth)/2
                         screenHeight-boxHeight/2
                         boxWidth
                         boxHeight],...
             'keypressfcn',@txtmenu_keypress );


% show the message
uicontrol(fig,'style','text',...
    'string',msg,...
    'fontsize',opts.msg_fontsize,...
    'fontname',opts.msg_fontname,...
    'position',[opts.padding,y,opts.width,opts.msg_height]);

y = y - opts.msg_height - opts.padding;

% show the choices as buttons
for i=1:num
  txt = choices{i};
  if opts.shownums
      txt = sprintf('%u. %s',i,choices{i});
  else
      txt = choices{i};
  end
  uicontrol('parent',fig',...
      'style','pushbutton',...
      'string',txt,...
      'fontname',opts.button_fontname,...
      'fontsize',opts.button_fontsize,...
      'position',[opts.padding,y,opts.width,opts.button_height],...
      'callback',{@txtmenu_choice,i});
  y = y - opts.button_height - opts.padding;
end


% wait for selection (the callbacks set the choice)
waitfor(fig);

% the figure window was closed - return the selection
return

%-----------
% nested functions
%   these are the callbacks - they are nested so they have access
%   to the parent variables choice and fig

function txtmenu_choice(hObj,event,c)
% callback routine for txtmenu button click
choice = c;
close(fig);
end

function txtmenu_keypress(hObj,event)
% callback routine for txtmenu key press
c = str2double(event.Character); % get the character of the key
if isnumeric(c)
    choice=c;
    if choice==0, choice=10; end
    close(fig);
end
end
% end nested functions
%-----------------
end