Created
March 29, 2011 12:33
-
-
Save iandol/892280 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function out = uipickfiles(varargin) | |
%uipickfiles: GUI program to select files and/or folders. | |
% | |
% Syntax: | |
% files = uipickfiles('PropertyName',PropertyValue,...) | |
% | |
% The current folder can be changed by operating in the file navigator: | |
% double-clicking on a folder in the list or pressing Enter to move further | |
% down the tree, using the popup menu, clicking the up arrow button or | |
% pressing Backspace to move up the tree, typing a path in the box to move | |
% to any folder or right-clicking (control-click on Mac) on the path box to | |
% revisit a previously-visited folder. These folders are listed in order | |
% of when they were last visited (most recent at the top) and the list is | |
% saved between calls to uipickfiles. The list can be cleared or its | |
% maximum length changed with the items at the bottom of the menu. | |
% (Windows only: To go to a UNC-named resource you will have to type the | |
% UNC name in the path box, but all such visited resources will be | |
% remembered and listed along with the mapped drives.) The items in the | |
% file navigator can be sorted by name, modification date or size by | |
% clicking on the headers, though neither date nor size are displayed. All | |
% folders have zero size. | |
% | |
% Files can be added to the list by double-clicking or selecting files | |
% (non-contiguous selections are possible with the control key) and | |
% pressing the Add button. Control-F will select all the files listed in | |
% the navigator while control-A will select everything (Command instead of | |
% Control on the Mac). Since double-clicking a folder will open it, | |
% folders can be added only by selecting them and pressing the Add button. | |
% Files/folders in the list can be removed or re-ordered. Recall button | |
% will insert whatever files were returned the last time uipickfiles was | |
% run into the Selected Files list. When finished, a press of the Done | |
% button will return the full paths to the selected items in a cell array, | |
% structure array or character array. If the Cancel button is pressed then | |
% zero is returned. | |
% | |
% The following optional property/value pairs can be specified as arguments | |
% to control the indicated behavior: | |
% | |
% Property Value | |
% ---------- ---------------------------------------------------------- | |
% FilterSpec String to specify starting folder and/or file filter. | |
% Ex: 'C:\bin' will start up in that folder. '*.txt' | |
% will list only files ending in '.txt'. 'c:\bin\*.txt' will | |
% do both. Default is to start up in the current folder and | |
% list all files. Can be changed with the GUI. | |
% | |
% REFilter String containing a regular expression used to filter the | |
% file list. Ex: '\.m$|\.mat$' will list files ending in | |
% '.m' and '.mat'. Default is empty string. Can be used | |
% with FilterSpec and both filters are applied. Can be | |
% changed with the GUI. | |
% | |
% REDirs Logical flag indicating whether to apply the regular | |
% expression filter to folder names. Default is false which | |
% means that all folders are listed. Can be changed with the | |
% GUI. | |
% | |
% Type Two-column cell array where the first column contains file | |
% filters and the second column contains descriptions. If | |
% this property is specified an additional popup menu will | |
% appear below the File Filter and selecting an item will put | |
% that item into the File Filter. By default, the first item | |
% will be entered into the File Filter. For example, | |
% { '*.m', 'M-files' ; | |
% '*.mat', 'MAT-files' }. | |
% Can also be a cell vector of file filter strings in which | |
% case the descriptions will be the same as the file filters | |
% themselves. | |
% Must be a cell array even if there is only one entry. | |
% | |
% Prompt String containing a prompt appearing in the title bar of | |
% the figure. Default is 'Select files'. | |
% | |
% NumFiles Scalar or vector specifying number of files that must be | |
% selected. A scalar specifies an exact value; a two-element | |
% vector can be used to specify a range, [min max]. The | |
% function will not return unless the specified number of | |
% files have been chosen. Default is [] which accepts any | |
% number of files. | |
% | |
% Append Cell array of strings, structure array or char array | |
% containing a previously returned output from uipickfiles. | |
% Used to start up program with some entries in the Selected | |
% Files list. Any included files that no longer exist will | |
% not appear. Default is empty cell array, {}. | |
% | |
% Output String specifying the data type of the output: 'cell', | |
% 'struct' or 'char'. Specifying 'cell' produces a cell | |
% array of strings, the strings containing the full paths of | |
% the chosen files. 'Struct' returns a structure array like | |
% the result of the dir function except that the 'name' field | |
% contains a full path instead of just the file name. 'Char' | |
% returns a character array of the full paths. This is most | |
% useful when you have just one file and want it in a string | |
% instead of a cell array containing just one string. The | |
% default is 'cell'. | |
% | |
% All properties and values are case-insensitive and need only be | |
% unambiguous. For example, | |
% | |
% files = uipickfiles('num',1,'out','ch') | |
% | |
% is valid usage. | |
% Version: 1.11, 21 March 2011 | |
% Author: Douglas M. Schwarz | |
% Email: dmschwarz=ieee*org, dmschwarz=urgrad*rochester*edu | |
% Real_email = regexprep(Email,{'=','*'},{'@','.'}) | |
% Define properties and set default values. | |
prop.filterspec = '*'; | |
prop.refilter = ''; | |
prop.redirs = false; | |
prop.type = {}; | |
prop.prompt = 'Select files'; | |
prop.numfiles = []; | |
prop.append = []; | |
prop.output = 'cell'; | |
% Process inputs and set prop fields. | |
prop = parsepropval(prop,varargin{:}); | |
% Validate FilterSpec property. | |
if isempty(prop.filterspec) | |
prop.filterspec = '*'; | |
end | |
if ~ischar(prop.filterspec) | |
error('FilterSpec property must contain a string.') | |
end | |
% Validate REFilter property. | |
if ~ischar(prop.refilter) | |
error('REFilter property must contain a string.') | |
end | |
% Validate REDirs property. | |
if ~isscalar(prop.redirs) | |
error('REDirs property must contain a scalar.') | |
end | |
% Validate Type property. | |
if isempty(prop.type) | |
elseif iscellstr(prop.type) && isscalar(prop.type) | |
prop.type = repmat(prop.type(:),1,2); | |
elseif iscellstr(prop.type) && size(prop.type,2) == 2 | |
else | |
error(['Type property must be empty or a cellstr vector or ',... | |
'a 2-column cellstr matrix.']) | |
end | |
% Validate Prompt property. | |
if ~ischar(prop.prompt) | |
error('Prompt property must contain a string.') | |
end | |
% Validate NumFiles property. | |
if numel(prop.numfiles) > 2 || any(prop.numfiles < 0) | |
error('NumFiles must be empty, a scalar or two-element vector.') | |
end | |
prop.numfiles = unique(prop.numfiles); | |
if isequal(prop.numfiles,1) | |
numstr = 'Select exactly 1 file.'; | |
elseif length(prop.numfiles) == 1 | |
numstr = sprintf('Select exactly %d files.',prop.numfiles); | |
else | |
numstr = sprintf('Select %d to %d files.',prop.numfiles); | |
end | |
% Validate Append property and initialize pick data. | |
if isstruct(prop.append) && isfield(prop.append,'name') | |
prop.append = {prop.append.name}; | |
elseif ischar(prop.append) | |
prop.append = cellstr(prop.append); | |
end | |
if isempty(prop.append) | |
file_picks = {}; | |
full_file_picks = {}; | |
dir_picks = dir(' '); % Create empty directory structure. | |
elseif iscellstr(prop.append) && isvector(prop.append) | |
num_items = length(prop.append); | |
file_picks = cell(1,num_items); | |
full_file_picks = cell(1,num_items); | |
dir_fn = fieldnames(dir(' ')); | |
dir_picks = repmat(cell2struct(cell(length(dir_fn),1),dir_fn(:)),... | |
num_items,1); | |
for item = 1:num_items | |
if exist(prop.append{item},'dir') && ... | |
~any(strcmp(full_file_picks,prop.append{item})) | |
full_file_picks{end + 1} = prop.append{item}; %#ok<AGROW> | |
[unused,fn,ext] = fileparts(prop.append{item}); | |
file_picks{end + 1} = [fn,ext]; %#ok<AGROW> | |
temp = dir(fullfile(prop.append{item},'..')); | |
if ispc || ismac | |
thisdir = strcmpi({temp.name},[fn,ext]); | |
else | |
thisdir = strcmp({temp.name},[fn,ext]); | |
end | |
dir_picks(end + 1) = temp(thisdir); %#ok<AGROW> | |
dir_picks(end).name = prop.append{item}; | |
elseif exist(prop.append{item},'file') && ... | |
~any(strcmp(full_file_picks,prop.append{item})) | |
full_file_picks{end + 1} = prop.append{item}; %#ok<AGROW> | |
[unused,fn,ext] = fileparts(prop.append{item}); | |
file_picks{end + 1} = [fn,ext]; %#ok<AGROW> | |
dir_picks(end + 1) = dir(prop.append{item}); %#ok<AGROW> | |
dir_picks(end).name = prop.append{item}; | |
else | |
continue | |
end | |
end | |
% Remove items which no longer exist. | |
missing = cellfun(@isempty,full_file_picks); | |
full_file_picks(missing) = []; | |
file_picks(missing) = []; | |
dir_picks(missing) = []; | |
else | |
error('Append must be a cell, struct or char array.') | |
end | |
% Validate Output property. | |
legal_outputs = {'cell','struct','char'}; | |
out_idx = find(strncmpi(prop.output,legal_outputs,length(prop.output))); | |
if length(out_idx) == 1 | |
prop.output = legal_outputs{out_idx}; | |
else | |
error(['Value of ''Output'' property, ''%s'', is illegal or '... | |
'ambiguous.'],prop.output) | |
end | |
% Set style preference for display of folders. | |
% 1 => folder icon before and filesep after | |
% 2 => bullet before and filesep after | |
% 3 => filesep after only | |
folder_style_pref = 1; | |
fsdata = set_folder_style(folder_style_pref); | |
% Initialize file lists. | |
if exist(prop.filterspec,'dir') | |
current_dir = prop.filterspec; | |
filter = '*'; | |
else | |
[current_dir,f,e] = fileparts(prop.filterspec); | |
filter = [f,e]; | |
end | |
if isempty(current_dir) | |
current_dir = pwd; | |
end | |
if isempty(filter) | |
filter = '*'; | |
end | |
re_filter = prop.refilter; | |
full_filter = fullfile(current_dir,filter); | |
network_volumes = {}; | |
[path_cell,new_network_vol] = path2cell(current_dir); | |
if exist(new_network_vol,'dir') | |
network_volumes = unique([network_volumes,{new_network_vol}]); | |
end | |
fdir = filtered_dir(full_filter,re_filter,prop.redirs,@(x)file_sort(x,[1 0 0])); | |
filenames = {fdir.name}'; | |
filenames = annotate_file_names(filenames,fdir,fsdata); | |
% Initialize some data. | |
show_full_path = false; | |
nodupes = true; | |
% Get preferences and set history. | |
history = getpref('uipickfiles','history',... | |
struct('name',current_dir,'time',now)); | |
default_history_size = 15; | |
history_size = getpref('uipickfiles','history_size',default_history_size); | |
history = update_history(history,current_dir,now,history_size); | |
% Create figure. | |
gray = get(0,'DefaultUIControlBackgroundColor'); | |
fig = figure('Position',[0 0 740 460+34],... | |
'Color',gray,... | |
'MenuBar','none',... | |
'WindowStyle','modal',... | |
'Resize','off',... | |
'NumberTitle','off',... | |
'Name',prop.prompt,... | |
'IntegerHandle','off',... | |
'CloseRequestFcn',@cancel,... | |
'CreateFcn',{@movegui,'center'}); | |
% Set system-dependent items. | |
if ismac | |
set(fig,'DefaultUIControlFontName','Lucida Grande') | |
set(fig,'DefaultUIControlFontSize',9) | |
sort_ctrl_size = 8; | |
mod_key = 'command'; | |
action = 'Control-click'; | |
elseif ispc | |
set(fig,'DefaultUIControlFontName','Tahoma') | |
set(fig,'DefaultUIControlFontSize',8) | |
sort_ctrl_size = 7; | |
mod_key = 'control'; | |
action = 'Right-click'; | |
else | |
sort_ctrl_size = get(fig,'DefaultUIControlFontSize') - 1; | |
mod_key = 'control'; | |
action = 'Right-click'; | |
end | |
% Create uicontrols. | |
uicontrol('Style','frame',... | |
'Position',[255 260 110 70]) | |
uicontrol('Style','frame',... | |
'Position',[275 135 110 100]) | |
navlist = uicontrol('Style','listbox',... | |
'Position',[10 10 250 320],... | |
'String',filenames,... | |
'Value',[],... | |
'BackgroundColor','w',... | |
'Callback',@clicknav,... | |
'KeyPressFcn',@keypressnav,... | |
'Max',2); | |
tri_up = repmat([1 1 1 1 0 1 1 1 1;1 1 1 0 0 0 1 1 1;1 1 0 0 0 0 0 1 1;... | |
1 0 0 0 0 0 0 0 1],[1 1 3]); | |
tri_up(tri_up == 1) = NaN; | |
tri_down = tri_up(end:-1:1,:,:); | |
tri_null = NaN(4,9,3); | |
tri_icon = {tri_down,tri_null,tri_up}; | |
sort_state = [1 0 0]; | |
last_sort_state = [1 1 1]; | |
sort_cb = zeros(1,3); | |
sort_cb(1) = uicontrol('Style','checkbox',... | |
'Position',[15 331 70 15],... | |
'String','Name',... | |
'FontSize',sort_ctrl_size,... | |
'Value',sort_state(1),... | |
'CData',tri_icon{sort_state(1)+2},... | |
'Callback',{@sort_type,1}); | |
sort_cb(2) = uicontrol('Style','checkbox',... | |
'Position',[85 331 70 15],... | |
'String','Date',... | |
'FontSize',sort_ctrl_size,... | |
'Value',sort_state(2),... | |
'CData',tri_icon{sort_state(2)+2},... | |
'Callback',{@sort_type,2}); | |
sort_cb(3) = uicontrol('Style','checkbox',... | |
'Position',[155 331 70 15],... | |
'String','Size',... | |
'FontSize',sort_ctrl_size,... | |
'Value',sort_state(3),... | |
'CData',tri_icon{sort_state(3)+2},... | |
'Callback',{@sort_type,3}); | |
pickslist = uicontrol('Style','listbox',... | |
'Position',[380 10 350 320],... | |
'String',file_picks,... | |
'BackgroundColor','w',... | |
'Callback',@clickpicks,... | |
'KeyPressFcn',@keypresslist,... | |
'Max',2,... | |
'Value',[]); | |
openbut = uicontrol('Style','pushbutton',... | |
'Position',[270 300 80 20],... | |
'String','Open',... | |
'Enable','off',... | |
'Callback',@open); | |
arrow = [ ... | |
' 1 '; | |
' 10 '; | |
' 10 '; | |
'000000000000'; | |
' 10 '; | |
' 10 '; | |
' 1 ']; | |
cmap = NaN(128,3); | |
cmap(double('10'),:) = [0.5 0.5 0.5;0 0 0]; | |
arrow_im = NaN(7,76,3); | |
arrow_im(:,45:56,:) = ind2rgb(double(arrow),cmap); | |
addbut = uicontrol('Style','pushbutton',... | |
'Position',[270 270 80 20],... | |
'String','Add ',... | |
'Enable','off',... | |
'CData',arrow_im,... | |
'Callback',@add); | |
removebut = uicontrol('Style','pushbutton',... | |
'Position',[290 205 80 20],... | |
'String','Remove',... | |
'Enable','off',... | |
'Callback',@remove); | |
moveupbut = uicontrol('Style','pushbutton',... | |
'Position',[290 175 80 20],... | |
'String','Move Up',... | |
'Enable','off',... | |
'Callback',@moveup); | |
movedownbut = uicontrol('Style','pushbutton',... | |
'Position',[290 145 80 20],... | |
'String','Move Down',... | |
'Enable','off',... | |
'Callback',@movedown); | |
dir_popup = uicontrol('Style','popupmenu',... | |
'Position',[10 350 225 20],... | |
'BackgroundColor','w',... | |
'String',path_cell,... | |
'Value',length(path_cell),... | |
'Callback',@dirpopup); | |
uparrow = [ ... | |
' 0 '; | |
' 000 '; | |
'00000 '; | |
' 0 '; | |
' 0 '; | |
' 0 '; | |
' 000000']; | |
cmap = NaN(128,3); | |
cmap(double('0'),:) = [0 0 0]; | |
uparrow_im = ind2rgb(double(uparrow),cmap); | |
up_dir_but = uicontrol('Style','pushbutton',... | |
'Position',[240 350 20 20],... | |
'CData',uparrow_im,... | |
'Callback',@dir_up_one,... | |
'ToolTip','Go to parent folder'); | |
if length(path_cell) > 1 | |
set(up_dir_but','Enable','on') | |
else | |
set(up_dir_but','Enable','off') | |
end | |
hist_cm = uicontextmenu; | |
pathbox = uicontrol('Position',[10 375 250 26],... | |
'Style','edit',... | |
'BackgroundColor','w',... | |
'String',current_dir,... | |
'HorizontalAlignment','left',... | |
'TooltipString',[action,' to display folder history'],... | |
'Callback',@change_path,... | |
'UIContextMenu',hist_cm); | |
uicontrol('Position',[10 401 250 16],... | |
'Style','text',... | |
'String','Current Folder',... | |
'HorizontalAlignment','center',... | |
'TooltipString',[action,' to display folder history'],... | |
'UIContextMenu',hist_cm) | |
hist_menus = []; | |
make_history_cm() | |
uicontrol('Position',[10 440+36 80 17],... | |
'Style','text',... | |
'String','File Filter',... | |
'HorizontalAlignment','left') | |
uicontrol('Position',[100 440+36 160 17],... | |
'Style','text',... | |
'String','Reg. Exp. Filter',... | |
'HorizontalAlignment','left') | |
showallfiles = uicontrol('Position',[270 420+32 100 20],... | |
'Style','checkbox',... | |
'String','Show All Files',... | |
'Value',0,... | |
'HorizontalAlignment','left',... | |
'Callback',@togglefilter); | |
refilterdirs = uicontrol('Position',[270 420+10 100 20],... | |
'Style','checkbox',... | |
'String','RE Filter Dirs',... | |
'Value',prop.redirs,... | |
'HorizontalAlignment','left',... | |
'Callback',@toggle_refiltdirs); | |
filter_ed = uicontrol('Position',[10 420+30 80 26],... | |
'Style','edit',... | |
'BackgroundColor','w',... | |
'String',filter,... | |
'HorizontalAlignment','left',... | |
'Callback',@setfilspec); | |
refilter_ed = uicontrol('Position',[100 420+30 160 26],... | |
'Style','edit',... | |
'BackgroundColor','w',... | |
'String',re_filter,... | |
'HorizontalAlignment','left',... | |
'Callback',@setrefilter); | |
if ~isempty(prop.type) | |
type_value = 1; | |
set(filter_ed,'String',prop.type{type_value,1}) | |
setfilspec() | |
type_popup = uicontrol('Position',[10 422 250 20],... | |
'Style','popupmenu',... | |
'String',prop.type(:,2),... | |
'BackgroundColor','w',... | |
'Value',type_value,... | |
'Callback',@filter_type_callback); | |
end | |
viewfullpath = uicontrol('Style','checkbox',... | |
'Position',[380 335 230 20],... | |
'String','Show full paths',... | |
'Value',show_full_path,... | |
'HorizontalAlignment','left',... | |
'Callback',@showfullpath); | |
remove_dupes = uicontrol('Style','checkbox',... | |
'Position',[380 360 280 20],... | |
'String','Remove duplicates (as per full path)',... | |
'Value',nodupes,... | |
'HorizontalAlignment','left',... | |
'Callback',@removedupes); | |
uicontrol('Position',[665 335 65 20],'String','Recall',... | |
'Callback',@recall,... | |
'ToolTip','Add previously selected files') | |
uicontrol('Position',[380 405 350 20],... | |
'Style','text',... | |
'String','Selected Files',... | |
'HorizontalAlignment','center') | |
uicontrol('Position',[280 80 80 30],'String','Done',... | |
'Callback',@done); | |
uicontrol('Position',[280 30 80 30],'String','Cancel',... | |
'Callback',@cancel); | |
% If necessary, add warning about number of files to be selected. | |
if ~isempty(prop.numfiles) | |
uicontrol('Position',[380 385 350 16],... | |
'Style','text',... | |
'String',numstr,... | |
'ForegroundColor',[0.8 0 0],... | |
'HorizontalAlignment','center') | |
end | |
set(fig,'HandleVisibility','off') | |
% Wait until figure is closed. | |
uiwait(fig) | |
% Compute desired output. | |
switch prop.output | |
case 'cell' | |
out = full_file_picks; | |
case 'struct' | |
out = dir_picks(:); | |
case 'char' | |
out = char(full_file_picks); | |
case 'cancel' | |
out = 0; | |
end | |
% Update history preference. | |
setpref('uipickfiles','history',history) | |
if ~isempty(full_file_picks) && ~strcmp(prop.output,'cancel') | |
setpref('uipickfiles','full_file_picks',full_file_picks) | |
end | |
% ----------------- Callback nested functions ---------------- | |
function add(varargin) | |
values = get(navlist,'Value'); | |
for i = 1:length(values) | |
dir_pick = fdir(values(i)); | |
pick = dir_pick.name; | |
pick_full = fullfile(current_dir,pick); | |
dir_pick.name = pick_full; | |
if ~nodupes || ~any(strcmp(full_file_picks,pick_full)) | |
file_picks{end + 1} = pick; %#ok<AGROW> | |
full_file_picks{end + 1} = pick_full; %#ok<AGROW> | |
dir_picks(end + 1) = dir_pick; %#ok<AGROW> | |
end | |
end | |
if show_full_path | |
set(pickslist,'String',full_file_picks,'Value',[]); | |
else | |
set(pickslist,'String',file_picks,'Value',[]); | |
end | |
set([removebut,moveupbut,movedownbut],'Enable','off'); | |
end | |
function remove(varargin) | |
values = get(pickslist,'Value'); | |
file_picks(values) = []; | |
full_file_picks(values) = []; | |
dir_picks(values) = []; | |
top = get(pickslist,'ListboxTop'); | |
num_above_top = sum(values < top); | |
top = top - num_above_top; | |
num_picks = length(file_picks); | |
new_value = min(min(values) - num_above_top,num_picks); | |
if num_picks == 0 | |
new_value = []; | |
set([removebut,moveupbut,movedownbut],'Enable','off') | |
end | |
if show_full_path | |
set(pickslist,'String',full_file_picks,'Value',new_value,... | |
'ListboxTop',top) | |
else | |
set(pickslist,'String',file_picks,'Value',new_value,... | |
'ListboxTop',top) | |
end | |
end | |
function open(varargin) | |
values = get(navlist,'Value'); | |
if fdir(values).isdir | |
set(fig,'pointer','watch') | |
drawnow | |
current_dir = fullfile(current_dir,fdir(values).name); | |
history = update_history(history,current_dir,now,history_size); | |
make_history_cm() | |
full_filter = fullfile(current_dir,filter); | |
path_cell = path2cell(current_dir); | |
fdir = filtered_dir(full_filter,re_filter,prop.redirs,... | |
@(x)file_sort(x,sort_state)); | |
filenames = {fdir.name}'; | |
filenames = annotate_file_names(filenames,fdir,fsdata); | |
set(dir_popup,'String',path_cell,'Value',length(path_cell)) | |
if length(path_cell) > 1 | |
set(up_dir_but','Enable','on') | |
else | |
set(up_dir_but','Enable','off') | |
end | |
set(pathbox,'String',current_dir) | |
set(navlist,'ListboxTop',1,'Value',[],'String',filenames) | |
set(addbut,'Enable','off') | |
set(openbut,'Enable','off') | |
set(fig,'pointer','arrow') | |
end | |
end | |
function clicknav(varargin) | |
value = get(navlist,'Value'); | |
nval = length(value); | |
dbl_click_fcn = @add; | |
switch nval | |
case 0 | |
set([addbut,openbut],'Enable','off') | |
case 1 | |
set(addbut,'Enable','on'); | |
if fdir(value).isdir | |
set(openbut,'Enable','on') | |
dbl_click_fcn = @open; | |
else | |
set(openbut,'Enable','off') | |
end | |
otherwise | |
set(addbut,'Enable','on') | |
set(openbut,'Enable','off') | |
end | |
if strcmp(get(fig,'SelectionType'),'open') | |
dbl_click_fcn(); | |
end | |
end | |
function keypressnav(h,evt) %#ok<INUSL> | |
if length(path_cell) > 1 && strcmp(evt.Key,'backspace') | |
% Backspace means go to parent folder. | |
dir_up_one() | |
elseif strcmp(evt.Key,'f') && isequal(evt.Modifier,{mod_key}) | |
% Control-F (Command-F on Mac) means select all files. | |
value = find(~[fdir.isdir]); | |
set(navlist,'Value',value) | |
elseif strcmp(evt.Key,'rightarrow') | |
% Right arrow key means select the file. | |
add() | |
end | |
end | |
function keypresslist(h,evt) %#ok<INUSL> | |
if strcmp(evt.Key,'backspace') | |
% Backspace means remove item from list. | |
remove() | |
end | |
end | |
function clickpicks(varargin) | |
value = get(pickslist,'Value'); | |
if isempty(value) | |
set([removebut,moveupbut,movedownbut],'Enable','off') | |
else | |
set(removebut,'Enable','on') | |
if min(value) == 1 | |
set(moveupbut,'Enable','off') | |
else | |
set(moveupbut,'Enable','on') | |
end | |
if max(value) == length(file_picks) | |
set(movedownbut,'Enable','off') | |
else | |
set(movedownbut,'Enable','on') | |
end | |
end | |
if strcmp(get(fig,'SelectionType'),'open') | |
remove(); | |
end | |
end | |
function recall(varargin) | |
if ispref('uipickfiles','full_file_picks') | |
ffp = getpref('uipickfiles','full_file_picks'); | |
else | |
ffp = {}; | |
end | |
for i = 1:length(ffp) | |
if exist(ffp{i},'dir') && ... | |
(~nodupes || ~any(strcmp(full_file_picks,ffp{i}))) | |
full_file_picks{end + 1} = ffp{i}; %#ok<AGROW> | |
[unused,fn,ext] = fileparts(ffp{i}); | |
file_picks{end + 1} = [fn,ext]; %#ok<AGROW> | |
temp = dir(fullfile(ffp{i},'..')); | |
if ispc || ismac | |
thisdir = strcmpi({temp.name},[fn,ext]); | |
else | |
thisdir = strcmp({temp.name},[fn,ext]); | |
end | |
dir_picks(end + 1) = temp(thisdir); %#ok<AGROW> | |
dir_picks(end).name = ffp{i}; | |
elseif exist(ffp{i},'file') && ... | |
(~nodupes || ~any(strcmp(full_file_picks,ffp{i}))) | |
full_file_picks{end + 1} = ffp{i}; %#ok<AGROW> | |
[unused,fn,ext] = fileparts(ffp{i}); | |
file_picks{end + 1} = [fn,ext]; %#ok<AGROW> | |
dir_picks(end + 1) = dir(ffp{i}); %#ok<AGROW> | |
dir_picks(end).name = ffp{i}; | |
end | |
end | |
if show_full_path | |
set(pickslist,'String',full_file_picks,'Value',[]); | |
else | |
set(pickslist,'String',file_picks,'Value',[]); | |
end | |
set([removebut,moveupbut,movedownbut],'Enable','off'); | |
end | |
function sort_type(h,evt,cb) %#ok<INUSL> | |
if sort_state(cb) | |
sort_state(cb) = -sort_state(cb); | |
last_sort_state(cb) = sort_state(cb); | |
else | |
sort_state = zeros(1,3); | |
sort_state(cb) = last_sort_state(cb); | |
end | |
set(sort_cb,{'CData'},tri_icon(sort_state + 2)') | |
fdir = filtered_dir(full_filter,re_filter,prop.redirs,... | |
@(x)file_sort(x,sort_state)); | |
filenames = {fdir.name}'; | |
filenames = annotate_file_names(filenames,fdir,fsdata); | |
set(dir_popup,'String',path_cell,'Value',length(path_cell)) | |
if length(path_cell) > 1 | |
set(up_dir_but','Enable','on') | |
else | |
set(up_dir_but','Enable','off') | |
end | |
set(pathbox,'String',current_dir) | |
set(navlist,'String',filenames,'Value',[]) | |
set(addbut,'Enable','off') | |
set(openbut,'Enable','off') | |
set(fig,'pointer','arrow') | |
end | |
function dirpopup(varargin) | |
value = get(dir_popup,'Value'); | |
container = path_cell{min(value + 1,length(path_cell))}; | |
path_cell = path_cell(1:value); | |
set(fig,'pointer','watch') | |
drawnow | |
if ispc && value == 1 | |
current_dir = ''; | |
full_filter = filter; | |
drives = getdrives(network_volumes); | |
num_drives = length(drives); | |
temp = tempname; | |
mkdir(temp) | |
dir_temp = dir(temp); | |
rmdir(temp) | |
fdir = repmat(dir_temp(1),num_drives,1); | |
[fdir.name] = deal(drives{:}); | |
else | |
current_dir = cell2path(path_cell); | |
history = update_history(history,current_dir,now,history_size); | |
make_history_cm() | |
full_filter = fullfile(current_dir,filter); | |
fdir = filtered_dir(full_filter,re_filter,prop.redirs,... | |
@(x)file_sort(x,sort_state)); | |
end | |
filenames = {fdir.name}'; | |
selected = find(strcmp(filenames,container)); | |
filenames = annotate_file_names(filenames,fdir,fsdata); | |
set(dir_popup,'String',path_cell,'Value',length(path_cell)) | |
if length(path_cell) > 1 | |
set(up_dir_but','Enable','on') | |
else | |
set(up_dir_but','Enable','off') | |
end | |
set(pathbox,'String',current_dir) | |
set(navlist,'String',filenames,'Value',selected) | |
set(addbut,'Enable','off') | |
set(fig,'pointer','arrow') | |
end | |
function dir_up_one(varargin) | |
value = length(path_cell) - 1; | |
container = path_cell{value + 1}; | |
path_cell = path_cell(1:value); | |
set(fig,'pointer','watch') | |
drawnow | |
if ispc && value == 1 | |
current_dir = ''; | |
full_filter = filter; | |
drives = getdrives(network_volumes); | |
num_drives = length(drives); | |
temp = tempname; | |
mkdir(temp) | |
dir_temp = dir(temp); | |
rmdir(temp) | |
fdir = repmat(dir_temp(1),num_drives,1); | |
[fdir.name] = deal(drives{:}); | |
else | |
current_dir = cell2path(path_cell); | |
history = update_history(history,current_dir,now,history_size); | |
make_history_cm() | |
full_filter = fullfile(current_dir,filter); | |
fdir = filtered_dir(full_filter,re_filter,prop.redirs,... | |
@(x)file_sort(x,sort_state)); | |
end | |
filenames = {fdir.name}'; | |
selected = find(strcmp(filenames,container)); | |
filenames = annotate_file_names(filenames,fdir,fsdata); | |
set(dir_popup,'String',path_cell,'Value',length(path_cell)) | |
if length(path_cell) > 1 | |
set(up_dir_but','Enable','on') | |
else | |
set(up_dir_but','Enable','off') | |
end | |
set(pathbox,'String',current_dir) | |
set(navlist,'String',filenames,'Value',selected) | |
set(addbut,'Enable','off') | |
set(fig,'pointer','arrow') | |
end | |
function change_path(varargin) | |
set(fig,'pointer','watch') | |
drawnow | |
proposed_path = get(pathbox,'String'); | |
% Process any folders named '..'. | |
proposed_path_cell = path2cell(proposed_path); | |
ddots = strcmp(proposed_path_cell,'..'); | |
ddots(find(ddots) - 1) = true; | |
proposed_path_cell(ddots) = []; | |
proposed_path = cell2path(proposed_path_cell); | |
% Check for existance of folder. | |
if ~exist(proposed_path,'dir') | |
set(fig,'pointer','arrow') | |
uiwait(errordlg(['Folder "',proposed_path,... | |
'" does not exist.'],'','modal')) | |
return | |
end | |
current_dir = proposed_path; | |
history = update_history(history,current_dir,now,history_size); | |
make_history_cm() | |
full_filter = fullfile(current_dir,filter); | |
[path_cell,new_network_vol] = path2cell(current_dir); | |
if exist(new_network_vol,'dir') | |
network_volumes = unique([network_volumes,{new_network_vol}]); | |
end | |
fdir = filtered_dir(full_filter,re_filter,prop.redirs,... | |
@(x)file_sort(x,sort_state)); | |
filenames = {fdir.name}'; | |
filenames = annotate_file_names(filenames,fdir,fsdata); | |
set(dir_popup,'String',path_cell,'Value',length(path_cell)) | |
if length(path_cell) > 1 | |
set(up_dir_but','Enable','on') | |
else | |
set(up_dir_but','Enable','off') | |
end | |
set(pathbox,'String',current_dir) | |
set(navlist,'String',filenames,'Value',[]) | |
set(addbut,'Enable','off') | |
set(openbut,'Enable','off') | |
set(fig,'pointer','arrow') | |
end | |
function showfullpath(varargin) | |
show_full_path = get(viewfullpath,'Value'); | |
if show_full_path | |
set(pickslist,'String',full_file_picks) | |
else | |
set(pickslist,'String',file_picks) | |
end | |
end | |
function removedupes(varargin) | |
nodupes = get(remove_dupes,'Value'); | |
if nodupes | |
num_picks = length(full_file_picks); | |
[unused,rev_order] = unique(full_file_picks(end:-1:1)); %#ok<SETNU> | |
order = sort(num_picks + 1 - rev_order); | |
full_file_picks = full_file_picks(order); | |
file_picks = file_picks(order); | |
dir_picks = dir_picks(order); | |
if show_full_path | |
set(pickslist,'String',full_file_picks,'Value',[]) | |
else | |
set(pickslist,'String',file_picks,'Value',[]) | |
end | |
set([removebut,moveupbut,movedownbut],'Enable','off') | |
end | |
end | |
function moveup(varargin) | |
value = get(pickslist,'Value'); | |
set(removebut,'Enable','on') | |
n = length(file_picks); | |
omega = 1:n; | |
index = zeros(1,n); | |
index(value - 1) = omega(value); | |
index(setdiff(omega,value - 1)) = omega(setdiff(omega,value)); | |
file_picks = file_picks(index); | |
full_file_picks = full_file_picks(index); | |
dir_picks = dir_picks(index); | |
value = value - 1; | |
if show_full_path | |
set(pickslist,'String',full_file_picks,'Value',value) | |
else | |
set(pickslist,'String',file_picks,'Value',value) | |
end | |
if min(value) == 1 | |
set(moveupbut,'Enable','off') | |
end | |
set(movedownbut,'Enable','on') | |
end | |
function movedown(varargin) | |
value = get(pickslist,'Value'); | |
set(removebut,'Enable','on') | |
n = length(file_picks); | |
omega = 1:n; | |
index = zeros(1,n); | |
index(value + 1) = omega(value); | |
index(setdiff(omega,value + 1)) = omega(setdiff(omega,value)); | |
file_picks = file_picks(index); | |
full_file_picks = full_file_picks(index); | |
dir_picks = dir_picks(index); | |
value = value + 1; | |
if show_full_path | |
set(pickslist,'String',full_file_picks,'Value',value) | |
else | |
set(pickslist,'String',file_picks,'Value',value) | |
end | |
if max(value) == n | |
set(movedownbut,'Enable','off') | |
end | |
set(moveupbut,'Enable','on') | |
end | |
function togglefilter(varargin) | |
set(fig,'pointer','watch') | |
drawnow | |
value = get(showallfiles,'Value'); | |
if value | |
filter = '*'; | |
re_filter = ''; | |
set([filter_ed,refilter_ed],'Enable','off') | |
else | |
filter = get(filter_ed,'String'); | |
re_filter = get(refilter_ed,'String'); | |
set([filter_ed,refilter_ed],'Enable','on') | |
end | |
full_filter = fullfile(current_dir,filter); | |
fdir = filtered_dir(full_filter,re_filter,prop.redirs,... | |
@(x)file_sort(x,sort_state)); | |
filenames = {fdir.name}'; | |
filenames = annotate_file_names(filenames,fdir,fsdata); | |
set(navlist,'String',filenames,'Value',[]) | |
set(addbut,'Enable','off') | |
set(fig,'pointer','arrow') | |
end | |
function toggle_refiltdirs(varargin) | |
set(fig,'pointer','watch') | |
drawnow | |
value = get(refilterdirs,'Value'); | |
prop.redirs = value; | |
full_filter = fullfile(current_dir,filter); | |
fdir = filtered_dir(full_filter,re_filter,prop.redirs,... | |
@(x)file_sort(x,sort_state)); | |
filenames = {fdir.name}'; | |
filenames = annotate_file_names(filenames,fdir,fsdata); | |
set(navlist,'String',filenames,'Value',[]) | |
set(addbut,'Enable','off') | |
set(fig,'pointer','arrow') | |
end | |
function setfilspec(varargin) | |
set(fig,'pointer','watch') | |
drawnow | |
filter = get(filter_ed,'String'); | |
if isempty(filter) | |
filter = '*'; | |
set(filter_ed,'String',filter) | |
end | |
% Process file spec if a subdirectory was included. | |
[p,f,e] = fileparts(filter); | |
if ~isempty(p) | |
newpath = fullfile(current_dir,p,''); | |
set(pathbox,'String',newpath) | |
filter = [f,e]; | |
if isempty(filter) | |
filter = '*'; | |
end | |
set(filter_ed,'String',filter) | |
change_path(); | |
end | |
full_filter = fullfile(current_dir,filter); | |
fdir = filtered_dir(full_filter,re_filter,prop.redirs,... | |
@(x)file_sort(x,sort_state)); | |
filenames = {fdir.name}'; | |
filenames = annotate_file_names(filenames,fdir,fsdata); | |
set(navlist,'String',filenames,'Value',[]) | |
set(addbut,'Enable','off') | |
set(fig,'pointer','arrow') | |
end | |
function setrefilter(varargin) | |
set(fig,'pointer','watch') | |
drawnow | |
re_filter = get(refilter_ed,'String'); | |
fdir = filtered_dir(full_filter,re_filter,prop.redirs,... | |
@(x)file_sort(x,sort_state)); | |
filenames = {fdir.name}'; | |
filenames = annotate_file_names(filenames,fdir,fsdata); | |
set(navlist,'String',filenames,'Value',[]) | |
set(addbut,'Enable','off') | |
set(fig,'pointer','arrow') | |
end | |
function filter_type_callback(varargin) | |
type_value = get(type_popup,'Value'); | |
set(filter_ed,'String',prop.type{type_value,1}) | |
setfilspec() | |
end | |
function done(varargin) | |
% Optional shortcut: click on a file and press 'Done'. | |
% if isempty(full_file_picks) && strcmp(get(addbut,'Enable'),'on') | |
% add(); | |
% end | |
numfiles = length(full_file_picks); | |
if ~isempty(prop.numfiles) | |
if numfiles < prop.numfiles(1) | |
msg = {'Too few files selected.',numstr}; | |
uiwait(errordlg(msg,'','modal')) | |
return | |
elseif numfiles > prop.numfiles(end) | |
msg = {'Too many files selected.',numstr}; | |
uiwait(errordlg(msg,'','modal')) | |
return | |
end | |
end | |
delete(fig) | |
end | |
function cancel(varargin) | |
prop.output = 'cancel'; | |
delete(fig) | |
end | |
function history_cb(varargin) | |
set(fig,'pointer','watch') | |
drawnow | |
current_dir = history(varargin{3}).name; | |
history = update_history(history,current_dir,now,history_size); | |
make_history_cm() | |
full_filter = fullfile(current_dir,filter); | |
path_cell = path2cell(current_dir); | |
fdir = filtered_dir(full_filter,re_filter,prop.redirs,... | |
@(x)file_sort(x,sort_state)); | |
filenames = {fdir.name}'; | |
filenames = annotate_file_names(filenames,fdir,fsdata); | |
set(dir_popup,'String',path_cell,'Value',length(path_cell)) | |
if length(path_cell) > 1 | |
set(up_dir_but','Enable','on') | |
else | |
set(up_dir_but','Enable','off') | |
end | |
set(pathbox,'String',current_dir) | |
set(navlist,'ListboxTop',1,'Value',[],'String',filenames) | |
set(addbut,'Enable','off') | |
set(openbut,'Enable','off') | |
set(fig,'pointer','arrow') | |
end | |
function clear_history(varargin) | |
history = update_history(history(1),'',[],history_size); | |
make_history_cm() | |
end | |
function set_history_size(varargin) | |
result_cell = inputdlg('Number of Recent Folders:','',1,... | |
{sprintf('%g',history_size)}); | |
if isempty(result_cell) | |
return | |
end | |
result = sscanf(result_cell{1},'%f'); | |
if isempty(result) || result < 1 | |
return | |
end | |
history_size = result; | |
history = update_history(history,'',[],history_size); | |
make_history_cm() | |
setpref('uipickfiles','history_size',history_size) | |
end | |
% ------------------ Other nested functions ------------------ | |
function make_history_cm | |
% Make context menu for history. | |
if ~isempty(hist_menus) | |
delete(hist_menus) | |
end | |
num_hist = length(history); | |
hist_menus = zeros(1,num_hist+2); | |
for i = 1:num_hist | |
hist_menus(i) = uimenu(hist_cm,'Label',history(i).name,... | |
'Callback',{@history_cb,i}); | |
end | |
hist_menus(num_hist+1) = uimenu(hist_cm,... | |
'Label','Clear Menu',... | |
'Separator','on',... | |
'Callback',@clear_history); | |
hist_menus(num_hist+2) = uimenu(hist_cm,'Label',... | |
sprintf('Set Number of Recent Folders (%d) ...',history_size),... | |
'Callback',@set_history_size); | |
end | |
end | |
% -------------------- Subfunctions -------------------- | |
function [c,network_vol] = path2cell(p) | |
% Turns a path string into a cell array of path elements. | |
if ispc | |
p = strrep(p,'/','\'); | |
k = regexp(p,'(^\\\\[^\\]+\\[^\\]+)|(^[A-Za-z]+:)','end'); | |
vol = p(1:k); | |
c1 = strread(p(k+2:end),'%s','delimiter','\\/'); | |
c = [{'My Computer'};{vol};c1]; | |
if strncmp(vol,'\\',2) | |
network_vol = vol; | |
else | |
network_vol = ''; | |
end | |
else | |
c = strread(p,'%s','delimiter','\\/'); | |
c = [{filesep};c(2:end)]; | |
network_vol = ''; | |
end | |
end | |
% -------------------- | |
function p = cell2path(c) | |
% Turns a cell array of path elements into a path string. | |
if ispc | |
p = fullfile(c{2:end},''); | |
else | |
p = fullfile(c{:},''); | |
end | |
end | |
% -------------------- | |
function d = filtered_dir(full_filter,re_filter,filter_both,sort_fcn) | |
% Like dir, but applies filters and sorting. | |
p = fileparts(full_filter); | |
if isempty(p) && full_filter(1) == '/' | |
p = '/'; | |
end | |
if exist(full_filter,'dir') | |
dfiles = dir(' '); | |
else | |
dfiles = dir(full_filter); | |
end | |
if ~isempty(dfiles) | |
dfiles([dfiles.isdir]) = []; | |
end | |
ddir = dir(p); | |
ddir = ddir([ddir.isdir]); | |
[unused,index0] = sort(lower({ddir.name})); | |
ddir = ddir(index0); | |
ddir(strcmp({ddir.name},'.') | strcmp({ddir.name},'..')) = []; | |
% Additional regular expression filter. | |
if nargin > 1 && ~isempty(re_filter) | |
if ispc || ismac | |
no_match = cellfun('isempty',regexpi({dfiles.name},re_filter)); | |
else | |
no_match = cellfun('isempty',regexp({dfiles.name},re_filter)); | |
end | |
dfiles(no_match) = []; | |
end | |
if filter_both | |
if nargin > 1 && ~isempty(re_filter) | |
if ispc || ismac | |
no_match = cellfun('isempty',regexpi({ddir.name},re_filter)); | |
else | |
no_match = cellfun('isempty',regexp({ddir.name},re_filter)); | |
end | |
ddir(no_match) = []; | |
end | |
end | |
% Set navigator style: | |
% 1 => list all folders before all files, case-insensitive sorting | |
% 2 => mix files and folders, case-insensitive sorting | |
% 3 => list all folders before all files, case-sensitive sorting | |
nav_style = 1; | |
switch nav_style | |
case 1 | |
[unused,index1] = sort_fcn(dfiles); | |
[unused,index2] = sort_fcn(ddir); | |
d = [ddir(index2);dfiles(index1)]; | |
case 2 | |
d = [dfiles;ddir]; | |
[unused,index] = sort(lower({d.name})); | |
d = d(index); | |
case 3 | |
[unused,index1] = sort({dfiles.name}); | |
[unused,index2] = sort({ddir.name}); | |
d = [ddir(index2);dfiles(index1)]; | |
end | |
end | |
% -------------------- | |
function [files_sorted,index] = file_sort(files,sort_state) | |
switch find(sort_state) | |
case 1 | |
[files_sorted,index] = sort(lower({files.name})); | |
if sort_state(1) < 0 | |
files_sorted = files_sorted(end:-1:1); | |
index = index(end:-1:1); | |
end | |
case 2 | |
if sort_state(2) > 0 | |
[files_sorted,index] = sort([files.datenum]); | |
else | |
[files_sorted,index] = sort([files.datenum],'descend'); | |
end | |
case 3 | |
if sort_state(3) > 0 | |
[files_sorted,index] = sort([files.bytes]); | |
else | |
[files_sorted,index] = sort([files.bytes],'descend'); | |
end | |
end | |
end | |
% -------------------- | |
function drives = getdrives(other_drives) | |
% Returns a cell array of drive names on Windows. | |
letters = char('A':'Z'); | |
num_letters = length(letters); | |
drives = cell(1,num_letters); | |
for i = 1:num_letters | |
if exist([letters(i),':\'],'dir'); | |
drives{i} = [letters(i),':']; | |
end | |
end | |
drives(cellfun('isempty',drives)) = []; | |
if nargin > 0 && iscellstr(other_drives) | |
drives = [drives,unique(other_drives)]; | |
end | |
end | |
% -------------------- | |
function filenames = annotate_file_names(filenames,dir_listing,fsdata) | |
% Adds a trailing filesep character to folder names and, optionally, | |
% prepends a folder icon or bullet symbol. | |
for i = 1:length(filenames) | |
if dir_listing(i).isdir | |
filenames{i} = sprintf('%s%s%s%s',fsdata.pre,filenames{i},... | |
fsdata.filesep,fsdata.post); | |
end | |
end | |
end | |
% -------------------- | |
function history = update_history(history,current_dir,time,history_size) | |
if ~isempty(current_dir) | |
% Insert or move current_dir to the top of the history. | |
% If current_dir already appears in the history list, delete it. | |
match = strcmp({history.name},current_dir); | |
history(match) = []; | |
% Prepend history with (current_dir,time). | |
history = [struct('name',current_dir,'time',time),history]; | |
end | |
% Trim history to keep at most <history_size> newest entries. | |
history = history(1:min(history_size,end)); | |
end | |
% -------------------- | |
function success = generate_folder_icon(icon_path) | |
% Black = 1, manila color = 2, transparent = 3. | |
im = [ ... | |
3 3 3 1 1 1 1 3 3 3 3 3; | |
3 3 1 2 2 2 2 1 3 3 3 3; | |
3 1 1 1 1 1 1 1 1 1 1 3; | |
1 2 2 2 2 2 2 2 2 2 2 1; | |
1 2 2 2 2 2 2 2 2 2 2 1; | |
1 2 2 2 2 2 2 2 2 2 2 1; | |
1 2 2 2 2 2 2 2 2 2 2 1; | |
1 2 2 2 2 2 2 2 2 2 2 1; | |
1 2 2 2 2 2 2 2 2 2 2 1; | |
1 1 1 1 1 1 1 1 1 1 1 1]; | |
cmap = [0 0 0;255 220 130;255 255 255]/255; | |
fid = fopen(icon_path,'w'); | |
if fid > 0 | |
fclose(fid); | |
imwrite(im,cmap,icon_path,'Transparency',[1 1 0]) | |
end | |
success = exist(icon_path,'file'); | |
end | |
% -------------------- | |
function fsdata = set_folder_style(folder_style_pref) | |
% Set style to preference. | |
fsdata.style = folder_style_pref; | |
% If style = 1, check to make sure icon image file exists. If it doesn't, | |
% try to create it. If that fails set style = 2. | |
if fsdata.style == 1 | |
icon_path = fullfile(prefdir,'uipickfiles_folder_icon.png'); | |
if ~exist(icon_path,'file') | |
success = generate_folder_icon(icon_path); | |
if ~success | |
fsdata.style = 2; | |
end | |
end | |
end | |
% Set pre and post fields. | |
if fsdata.style == 1 | |
icon_url = ['file://localhost/',... | |
strrep(strrep(icon_path,':','|'),'\','/')]; | |
fsdata.pre = sprintf('<html><img src="%s"> ',icon_url); | |
fsdata.post = '</html>'; | |
elseif fsdata.style == 2 | |
fsdata.pre = '<html><b>•</b> '; | |
fsdata.post = '</html>'; | |
elseif fsdata.style == 3 | |
fsdata.pre = ''; | |
fsdata.post = ''; | |
end | |
fsdata.filesep = filesep; | |
end | |
% -------------------- | |
function prop = parsepropval(prop,varargin) | |
% Parse property/value pairs and return a structure. | |
properties = fieldnames(prop); | |
arg_index = 1; | |
while arg_index <= length(varargin) | |
arg = varargin{arg_index}; | |
if ischar(arg) | |
prop_index = match_property(arg,properties); | |
prop.(properties{prop_index}) = varargin{arg_index + 1}; | |
arg_index = arg_index + 2; | |
elseif isstruct(arg) | |
arg_fn = fieldnames(arg); | |
for i = 1:length(arg_fn) | |
prop_index = match_property(arg_fn{i},properties); | |
prop.(properties{prop_index}) = arg.(arg_fn{i}); | |
end | |
arg_index = arg_index + 1; | |
else | |
error(['Properties must be specified by property/value pairs',... | |
' or structures.']) | |
end | |
end | |
end | |
% -------------------- | |
function prop_index = match_property(arg,properties) | |
% Utility function for parsepropval. | |
prop_index = find(strcmpi(arg,properties)); | |
if isempty(prop_index) | |
prop_index = find(strncmpi(arg,properties,length(arg))); | |
end | |
if length(prop_index) ~= 1 | |
error('Property ''%s'' does not exist or is ambiguous.',arg) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment