PageRenderTime 29ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/core/third_parties/uipickfiles.m

http://brainstream.googlecode.com/
MATLAB | 809 lines | 695 code | 29 blank | 85 comment | 47 complexity | 3bcab7c86f8dfa884b60d6e4dde2d31d MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, LGPL-2.0, GPL-3.0, GPL-2.0, LGPL-2.1, LGPL-3.0, BSD-2-Clause
  1. function out = uipickfiles(varargin)
  2. %uipickfiles: GUI program to select file(s) and/or directories.
  3. %
  4. % Syntax:
  5. % files = uipickfiles('PropertyName',PropertyValue,...)
  6. %
  7. % The current directory can be changed by operating in the file navigator:
  8. % double-clicking on a directory in the list to move further down the tree,
  9. % using the popup menu to move up the tree, typing a path in the box to
  10. % move to any directory or right-clicking on the path box to revisit a
  11. % previously-listed directory.
  12. %
  13. % Files can be added to the list by double-clicking or selecting files
  14. % (non-contiguous selections are possible with the control key) and
  15. % pressing the Add button. Files in the list can be removed or re-ordered.
  16. % When finished, a press of the Done button will return the full paths to
  17. % the selected files in a cell array, structure array or character array.
  18. % If the Cancel button is pressed then zero is returned.
  19. %
  20. % The following optional property/value pairs can be specified as arguments
  21. % to control the indicated behavior:
  22. %
  23. % Property Value
  24. % ---------- ----------------------------------------------------------
  25. % FilterSpec String to specify starting directory and/or file filter.
  26. % Ex: 'C:\bin' will start up in that directory. '*.txt'
  27. % will list only files ending in '.txt'. 'c:\bin\*.txt' will
  28. % do both. Default is to start up in the current directory
  29. % and list all files. Can be changed with the GUI.
  30. %
  31. % REFilter String containing a regular expression used to filter the
  32. % file list. Ex: '\.m$|\.mat$' will list files ending in
  33. % '.m' and '.mat'. Default is empty string. Can be used
  34. % with FilterSpec and both filters are applied. Can be
  35. % changed with the GUI.
  36. %
  37. % Prompt String containing a prompt appearing in the title bar of
  38. % the figure. Default is 'Select files'.
  39. %
  40. % NumFiles Scalar or vector specifying number of files that must be
  41. % selected. A scalar specifies an exact value; a two-element
  42. % vector can be used to specify a range, [min max]. The
  43. % function will not return unless the specified number of
  44. % files have been chosen. Default is [] which accepts any
  45. % number of files.
  46. %
  47. % Output String specifying the data type of the output: 'cell',
  48. % 'struct' or 'char'. Specifying 'cell' produces a cell
  49. % array of strings, the strings containing the full paths of
  50. % the chosen files. 'Struct' returns a structure array like
  51. % the result of the dir function except that the 'name' field
  52. % contains a full path instead of just the file name. 'Char'
  53. % returns a character array of the full paths. This is most
  54. % useful when you have just one file and want it in a string
  55. % instead of a cell array containing just one string. The
  56. % default is 'cell'.
  57. %
  58. % All properties and values are case-insensitive and need only be
  59. % unambiguous. For example,
  60. %
  61. % files = uipickfiles('num',1,'out','ch')
  62. %
  63. % is valid usage.
  64. % Version: 1.0, 25 April 2006
  65. % Author: Douglas M. Schwarz
  66. % Email: dmschwarz=ieee*org, dmschwarz=urgrad*rochester*edu
  67. % Real_email = regexprep(Email,{'=','*'},{'@','.'})
  68. % Define properties and set default values.
  69. prop.filterspec = '*';
  70. prop.refilter = '';
  71. prop.prompt = 'Select files';
  72. prop.numfiles = [];
  73. prop.output = 'cell';
  74. % Process inputs and set prop fields.
  75. properties = fieldnames(prop);
  76. arg_index = 1;
  77. while arg_index <= nargin
  78. arg = varargin{arg_index};
  79. if ischar(arg)
  80. prop_index = find(strncmpi(arg,properties,length(arg)));
  81. if length(prop_index) == 1
  82. prop.(properties{prop_index}) = varargin{arg_index + 1};
  83. else
  84. error('Property ''%s'' does not exist or is ambiguous.',arg)
  85. end
  86. arg_index = arg_index + 2;
  87. elseif isstruct(arg)
  88. arg_fn = fieldnames(arg);
  89. for i = 1:length(arg_fn)
  90. prop_index = find(strncmpi(arg_fn{i},properties,...
  91. length(arg_fn{i})));
  92. if length(prop_index) == 1
  93. prop.(properties{prop_index}) = arg.(arg_fn{i});
  94. else
  95. error('Property ''%s'' does not exist or is ambiguous.',...
  96. arg_fn{i})
  97. end
  98. end
  99. arg_index = arg_index + 1;
  100. else
  101. error(['Properties must be specified by property/value pairs',...
  102. ' or structures.'])
  103. end
  104. end
  105. % Validate FilterSpec property.
  106. if isempty(prop.filterspec)
  107. prop.filterspec = '*';
  108. end
  109. if ~ischar(prop.filterspec)
  110. error('FilterSpec property must contain a string.')
  111. end
  112. % Validate REFilter property.
  113. if ~ischar(prop.refilter)
  114. error('REFilter property must contain a string.')
  115. end
  116. % Validate Prompt property.
  117. if ~ischar(prop.prompt)
  118. error('Prompt property must contain a string.')
  119. end
  120. % Validate NumFiles property.
  121. if numel(prop.numfiles) > 2 || any(prop.numfiles < 0)
  122. error('NumFiles must be empty, a scalar or two-element vector.')
  123. end
  124. prop.numfiles = unique(prop.numfiles);
  125. if isequal(prop.numfiles,1)
  126. numstr = 'Select exactly 1 file.';
  127. elseif length(prop.numfiles) == 1
  128. numstr = sprintf('Select exactly %d files.',prop.numfiles);
  129. else
  130. numstr = sprintf('Select %d to %d files.',prop.numfiles);
  131. end
  132. % Validate Output property.
  133. legal_outputs = {'cell','struct','char'};
  134. out_idx = find(strncmpi(prop.output,legal_outputs,length(prop.output)));
  135. if length(out_idx) == 1
  136. prop.output = legal_outputs{out_idx};
  137. else
  138. error(['Value of ''Output'' property, ''%s'', is illegal or '...
  139. 'ambiguous.'],prop.output)
  140. end
  141. % Initialize file lists.
  142. [current_dir,f,e] = fileparts(prop.filterspec);
  143. filter = [f,e];
  144. if isempty(current_dir)
  145. current_dir = pwd;
  146. end
  147. if isempty(filter)
  148. filter = '*';
  149. end
  150. re_filter = prop.refilter;
  151. full_filter = fullfile(current_dir,filter);
  152. path_cell = path2cell(current_dir);
  153. fdir = filtered_dir(full_filter,re_filter);
  154. filenames = {fdir.name}';
  155. filenames = annotate_file_names(filenames,fdir);
  156. % Initialize some data.
  157. file_picks = {};
  158. full_file_picks = {};
  159. dir_picks = struct('name',{},'date','','bytes',[],'isdir',[],'datenum',[]);
  160. %dir_picks = struct('name',{},'date','','bytes',[],'isdir',[]);
  161. show_full_path = false;
  162. nodupes = true;
  163. history = {current_dir};
  164. % Create figure.
  165. gray = get(0,'DefaultUIControlBackgroundColor');
  166. fig = figure('Position',[0 0 740 445],...
  167. 'Color',gray,...
  168. 'WindowStyle','modal',...
  169. 'Resize','off',...
  170. 'NumberTitle','off',...
  171. 'Name',prop.prompt,...
  172. 'IntegerHandle','off',...
  173. 'CloseRequestFcn',@cancel,...
  174. 'CreateFcn',{@movegui,'north'});
  175. % Create uicontrols.
  176. uicontrol('Style','frame',...
  177. 'Position',[255 260 110 70])
  178. uicontrol('Style','frame',...
  179. 'Position',[275 135 110 100])
  180. navlist = uicontrol('Style','listbox',...
  181. 'Position',[10 10 250 320],...
  182. 'String',filenames,...
  183. 'Value',[],...
  184. 'BackgroundColor','w',...
  185. 'Callback',@clicknav,...
  186. 'Max',2);
  187. pickslist = uicontrol('Style','listbox',...
  188. 'Position',[380 10 350 320],...
  189. 'String',{},...
  190. 'BackgroundColor','w',...
  191. 'Callback',@clickpicks,...
  192. 'Max',2);
  193. openbut = uicontrol('Style','pushbutton',...
  194. 'Position',[270 300 80 20],...
  195. 'String','Open',...
  196. 'Enable','off',...
  197. 'Callback',@open);
  198. arrow = [2 2 2 2 2 2 2 2 1 2 2 2;...
  199. 2 2 2 2 2 2 2 2 2 0 2 2;...
  200. 2 2 2 2 2 2 2 2 2 2 0 2;...
  201. 0 0 0 0 0 0 0 0 0 0 0 0;...
  202. 2 2 2 2 2 2 2 2 2 2 0 2;...
  203. 2 2 2 2 2 2 2 2 2 0 2 2;...
  204. 2 2 2 2 2 2 2 2 1 2 2 2];
  205. arrow(arrow == 2) = NaN;
  206. arrow_im = NaN*ones(16,76);
  207. arrow_im(6:12,45:56) = arrow/2;
  208. im = repmat(arrow_im,[1 1 3]);
  209. addbut = uicontrol('Style','pushbutton',...
  210. 'Position',[270 270 80 20],...
  211. 'String','Add ',...
  212. 'Enable','off',...
  213. 'CData',im,...
  214. 'Callback',@add);
  215. removebut = uicontrol('Style','pushbutton',...
  216. 'Position',[290 205 80 20],...
  217. 'String','Remove',...
  218. 'Enable','off',...
  219. 'Callback',@remove);
  220. moveupbut = uicontrol('Style','pushbutton',...
  221. 'Position',[290 175 80 20],...
  222. 'String','Move Up',...
  223. 'Enable','off',...
  224. 'Callback',@moveup);
  225. movedownbut = uicontrol('Style','pushbutton',...
  226. 'Position',[290 145 80 20],...
  227. 'String','Move Down',...
  228. 'Enable','off',...
  229. 'Callback',@movedown);
  230. uicontrol('Position',[10 380 250 16],...
  231. 'Style','text',...
  232. 'String','Current Directory',...
  233. 'HorizontalAlignment','center')
  234. dir_popup = uicontrol('Style','popupmenu',...
  235. 'Position',[10 335 250 20],...
  236. 'BackgroundColor','w',...
  237. 'String',path_cell(end:-1:1),...
  238. 'Value',1,...
  239. 'Callback',@dirpopup);
  240. hist_cm = uicontextmenu;
  241. pathbox = uicontrol('Position',[10 360 250 20],...
  242. 'Style','edit',...
  243. 'BackgroundColor','w',...
  244. 'String',current_dir,...
  245. 'HorizontalAlignment','left',...
  246. 'Callback',@change_path,...
  247. 'UIContextMenu',hist_cm);
  248. hist_menus = [];
  249. hist_cb = @history_cb;
  250. hist_menus = make_history_cm(hist_cb,hist_cm,hist_menus,history);
  251. uicontrol('Position',[10 425 80 16],...
  252. 'Style','text',...
  253. 'String','File Filter',...
  254. 'HorizontalAlignment','left')
  255. uicontrol('Position',[100 425 160 16],...
  256. 'Style','text',...
  257. 'String','Reg. Exp. Filter',...
  258. 'HorizontalAlignment','left')
  259. showallfiles = uicontrol('Position',[270 405 100 20],...
  260. 'Style','checkbox',...
  261. 'String','Show All Files',...
  262. 'Value',0,...
  263. 'HorizontalAlignment','left',...
  264. 'Callback',@togglefilter);
  265. filter_ed = uicontrol('Position',[10 405 80 20],...
  266. 'Style','edit',...
  267. 'BackgroundColor','w',...
  268. 'String',filter,...
  269. 'HorizontalAlignment','left',...
  270. 'Callback',@setfilspec);
  271. refilter_ed = uicontrol('Position',[100 405 160 20],...
  272. 'Style','edit',...
  273. 'BackgroundColor','w',...
  274. 'String',re_filter,...
  275. 'HorizontalAlignment','left',...
  276. 'Callback',@setrefilter);
  277. viewfullpath = uicontrol('Style','checkbox',...
  278. 'Position',[380 335 230 20],...
  279. 'String','Show full paths',...
  280. 'Value',show_full_path,...
  281. 'HorizontalAlignment','left',...
  282. 'Callback',@showfullpath);
  283. remove_dupes = uicontrol('Style','checkbox',...
  284. 'Position',[380 360 230 20],...
  285. 'String','Remove duplicates (as per full path)',...
  286. 'Value',nodupes,...
  287. 'HorizontalAlignment','left',...
  288. 'Callback',@removedupes);
  289. uicontrol('Position',[380 405 350 20],...
  290. 'Style','text',...
  291. 'String','Selected Files',...
  292. 'HorizontalAlignment','center')
  293. uicontrol('Position',[280 80 80 30],'String','Done',...
  294. 'Callback',@done);
  295. uicontrol('Position',[280 30 80 30],'String','Cancel',...
  296. 'Callback',@cancel);
  297. if ~isempty(prop.numfiles)
  298. uicontrol('Position',[380 385 350 16],...
  299. 'Style','text',...
  300. 'String',numstr,...
  301. 'ForegroundColor','r',...
  302. 'HorizontalAlignment','center')
  303. end
  304. set(fig,'HandleVisibility','off')
  305. uiwait(fig)
  306. % Compute desired output.
  307. switch prop.output
  308. case 'cell'
  309. out = full_file_picks;
  310. case 'struct'
  311. out = dir_picks(:);
  312. case 'char'
  313. out = char(full_file_picks);
  314. case 'cancel'
  315. out = [];
  316. end
  317. % -------------------- Callback functions --------------------
  318. function add(varargin)
  319. values = get(navlist,'Value');
  320. for i = 1:length(values)
  321. dir_pick = fdir(values(i));
  322. pick = dir_pick.name;
  323. pick_full = fullfile(current_dir,pick);
  324. dir_pick.name = pick_full;
  325. if ~nodupes || ~any(strcmp(full_file_picks,pick_full))
  326. file_picks{end + 1} = pick;
  327. full_file_picks{end + 1} = pick_full;
  328. sz=numel(dir_picks);
  329. % if isfield(dir_pick,'datenum')
  330. % dir_pick = rmfield(dir_pick,'datenum');
  331. % end
  332. dir_picks(sz + 1) = dir_pick;
  333. end
  334. end
  335. if show_full_path
  336. set(pickslist,'String',full_file_picks,'Value',[]);
  337. else
  338. set(pickslist,'String',file_picks,'Value',[]);
  339. end
  340. set([removebut,moveupbut,movedownbut],'Enable','off');
  341. end
  342. function remove(varargin)
  343. values = get(pickslist,'Value');
  344. file_picks(values) = [];
  345. full_file_picks(values) = [];
  346. dir_picks(values) = [];
  347. top = get(pickslist,'ListboxTop');
  348. num_above_top = sum(values < top);
  349. top = top - num_above_top;
  350. num_picks = length(file_picks);
  351. new_value = min(min(values) - num_above_top,num_picks);
  352. if num_picks == 0
  353. new_value = [];
  354. set([removebut,moveupbut,movedownbut],'Enable','off')
  355. end
  356. if show_full_path
  357. set(pickslist,'String',full_file_picks,'Value',new_value,...
  358. 'ListboxTop',top)
  359. else
  360. set(pickslist,'String',file_picks,'Value',new_value,...
  361. 'ListboxTop',top)
  362. end
  363. end
  364. function open(varargin)
  365. values = get(navlist,'Value');
  366. if fdir(values).isdir
  367. if strcmp(fdir(values).name,'.')
  368. return
  369. elseif strcmp(fdir(values).name,'..')
  370. set(dir_popup,'Value',min(2,length(path_cell)))
  371. dirpopup();
  372. return
  373. end
  374. current_dir = fullfile(current_dir,fdir(values).name);
  375. history{end+1} = current_dir;
  376. history = unique(history);
  377. hist_menus = make_history_cm(hist_cb,hist_cm,hist_menus,...
  378. history);
  379. full_filter = fullfile(current_dir,filter);
  380. path_cell = path2cell(current_dir);
  381. fdir = filtered_dir(full_filter,re_filter);
  382. filenames = {fdir.name}';
  383. filenames = annotate_file_names(filenames,fdir);
  384. set(dir_popup,'String',path_cell(end:-1:1),'Value',1)
  385. set(pathbox,'String',current_dir)
  386. set(navlist,'ListboxTop',1,'Value',[],'String',filenames)
  387. set(addbut,'Enable','off')
  388. set(openbut,'Enable','off')
  389. end
  390. end
  391. function clicknav(varargin)
  392. value = get(navlist,'Value');
  393. nval = length(value);
  394. dbl_click_fcn = @add;
  395. switch nval
  396. case 0
  397. set([addbut,openbut],'Enable','off')
  398. case 1
  399. set(addbut,'Enable','on');
  400. if fdir(value).isdir
  401. set(openbut,'Enable','on')
  402. dbl_click_fcn = @open;
  403. else
  404. set(openbut,'Enable','off')
  405. end
  406. otherwise
  407. set(addbut,'Enable','on')
  408. set(openbut,'Enable','off')
  409. end
  410. if strcmp(get(fig,'SelectionType'),'open')
  411. dbl_click_fcn();
  412. end
  413. end
  414. function clickpicks(varargin)
  415. value = get(pickslist,'Value');
  416. if isempty(value)
  417. set([removebut,moveupbut,movedownbut],'Enable','off')
  418. else
  419. set(removebut,'Enable','on')
  420. if min(value) == 1
  421. set(moveupbut,'Enable','off')
  422. else
  423. set(moveupbut,'Enable','on')
  424. end
  425. if max(value) == length(file_picks)
  426. set(movedownbut,'Enable','off')
  427. else
  428. set(movedownbut,'Enable','on')
  429. end
  430. end
  431. if strcmp(get(fig,'SelectionType'),'open')
  432. remove();
  433. end
  434. end
  435. function dirpopup(varargin)
  436. value = get(dir_popup,'Value');
  437. len = length(path_cell);
  438. path_cell = path_cell(1:end-value+1);
  439. if ispc && value == len
  440. current_dir = '';
  441. full_filter = filter;
  442. fdir = struct('name',getdrives,'date',datestr(now),...
  443. 'bytes',0,'isdir',1);
  444. else
  445. current_dir = cell2path(path_cell);
  446. history{end+1} = current_dir;
  447. history = unique(history);
  448. hist_menus = make_history_cm(hist_cb,hist_cm,hist_menus,...
  449. history);
  450. full_filter = fullfile(current_dir,filter);
  451. fdir = filtered_dir(full_filter,re_filter);
  452. end
  453. filenames = {fdir.name}';
  454. filenames = annotate_file_names(filenames,fdir);
  455. set(dir_popup,'String',path_cell(end:-1:1),'Value',1)
  456. set(pathbox,'String',current_dir)
  457. set(navlist,'String',filenames,'Value',[])
  458. set(addbut,'Enable','off')
  459. end
  460. function change_path(varargin)
  461. proposed_path = get(pathbox,'String');
  462. % Process any directories named '..'.
  463. proposed_path_cell = path2cell(proposed_path);
  464. ddots = strcmp(proposed_path_cell,'..');
  465. ddots(find(ddots) - 1) = true;
  466. proposed_path_cell(ddots) = [];
  467. proposed_path = cell2path(proposed_path_cell);
  468. % Check for existance of directory.
  469. if ~exist(proposed_path,'dir')
  470. uiwait(errordlg(['Directory "',proposed_path,...
  471. '" does not exist.'],'','modal'))
  472. return
  473. end
  474. current_dir = proposed_path;
  475. history{end+1} = current_dir;
  476. history = unique(history);
  477. hist_menus = make_history_cm(hist_cb,hist_cm,hist_menus,history);
  478. full_filter = fullfile(current_dir,filter);
  479. path_cell = path2cell(current_dir);
  480. fdir = filtered_dir(full_filter,re_filter);
  481. filenames = {fdir.name}';
  482. filenames = annotate_file_names(filenames,fdir);
  483. set(dir_popup,'String',path_cell(end:-1:1),'Value',1)
  484. set(pathbox,'String',current_dir)
  485. set(navlist,'String',filenames,'Value',[])
  486. set(addbut,'Enable','off')
  487. set(openbut,'Enable','off')
  488. end
  489. function showfullpath(varargin)
  490. show_full_path = get(viewfullpath,'Value');
  491. if show_full_path
  492. set(pickslist,'String',full_file_picks)
  493. else
  494. set(pickslist,'String',file_picks)
  495. end
  496. end
  497. function removedupes(varargin)
  498. nodupes = get(remove_dupes,'Value');
  499. if nodupes
  500. num_picks = length(full_file_picks);
  501. [unused,rev_order] = unique(full_file_picks(end:-1:1));
  502. order = sort(num_picks + 1 - rev_order);
  503. full_file_picks = full_file_picks(order);
  504. file_picks = file_picks(order);
  505. if show_full_path
  506. set(pickslist,'String',full_file_picks,'Value',[])
  507. else
  508. set(pickslist,'String',file_picks,'Value',[])
  509. end
  510. set([removebut,moveupbut,movedownbut],'Enable','off')
  511. end
  512. end
  513. function moveup(varargin)
  514. value = get(pickslist,'Value');
  515. set(removebut,'Enable','on')
  516. n = length(file_picks);
  517. omega = 1:n;
  518. index = zeros(1,n);
  519. index(value - 1) = omega(value);
  520. index(setdiff(omega,value - 1)) = omega(setdiff(omega,value));
  521. file_picks = file_picks(index);
  522. full_file_picks = full_file_picks(index);
  523. value = value - 1;
  524. if show_full_path
  525. set(pickslist,'String',full_file_picks,'Value',value)
  526. else
  527. set(pickslist,'String',file_picks,'Value',value)
  528. end
  529. if min(value) == 1
  530. set(moveupbut,'Enable','off')
  531. end
  532. set(movedownbut,'Enable','on')
  533. end
  534. function movedown(varargin)
  535. value = get(pickslist,'Value');
  536. set(removebut,'Enable','on')
  537. n = length(file_picks);
  538. omega = 1:n;
  539. index = zeros(1,n);
  540. index(value + 1) = omega(value);
  541. index(setdiff(omega,value + 1)) = omega(setdiff(omega,value));
  542. file_picks = file_picks(index);
  543. full_file_picks = full_file_picks(index);
  544. value = value + 1;
  545. if show_full_path
  546. set(pickslist,'String',full_file_picks,'Value',value)
  547. else
  548. set(pickslist,'String',file_picks,'Value',value)
  549. end
  550. if max(value) == n
  551. set(movedownbut,'Enable','off')
  552. end
  553. set(moveupbut,'Enable','on')
  554. end
  555. function togglefilter(varargin)
  556. value = get(showallfiles,'Value');
  557. if value
  558. filter = '*';
  559. re_filter = '';
  560. set([filter_ed,refilter_ed],'Enable','off')
  561. else
  562. filter = get(filter_ed,'String');
  563. re_filter = get(refilter_ed,'String');
  564. set([filter_ed,refilter_ed],'Enable','on')
  565. end
  566. full_filter = fullfile(current_dir,filter);
  567. fdir = filtered_dir(full_filter,re_filter);
  568. filenames = {fdir.name}';
  569. filenames = annotate_file_names(filenames,fdir);
  570. set(navlist,'String',filenames,'Value',[])
  571. set(addbut,'Enable','off')
  572. end
  573. function setfilspec(varargin)
  574. filter = get(filter_ed,'String');
  575. if isempty(filter)
  576. filter = '*';
  577. set(filter_ed,'String',filter)
  578. end
  579. % Process file spec if a subdirectory was included.
  580. [p,f,e] = fileparts(filter);
  581. if ~isempty(p)
  582. newpath = fullfile(current_dir,p,'');
  583. set(pathbox,'String',newpath)
  584. filter = [f,e];
  585. if isempty(filter)
  586. filter = '*';
  587. end
  588. set(filter_ed,'String',filter)
  589. change_path();
  590. end
  591. full_filter = fullfile(current_dir,filter);
  592. fdir = filtered_dir(full_filter,re_filter);
  593. filenames = {fdir.name}';
  594. filenames = annotate_file_names(filenames,fdir);
  595. set(navlist,'String',filenames,'Value',[])
  596. set(addbut,'Enable','off')
  597. end
  598. function setrefilter(varargin)
  599. re_filter = get(refilter_ed,'String');
  600. fdir = filtered_dir(full_filter,re_filter);
  601. filenames = {fdir.name}';
  602. filenames = annotate_file_names(filenames,fdir);
  603. set(navlist,'String',filenames,'Value',[])
  604. set(addbut,'Enable','off')
  605. end
  606. function done(varargin)
  607. % Optional shortcut: click on a file and press 'Done'.
  608. % if isempty(full_file_picks) && strcmp(get(addbut,'Enable'),'on')
  609. % add();
  610. % end
  611. numfiles = length(full_file_picks);
  612. if ~isempty(prop.numfiles)
  613. if numfiles < prop.numfiles(1)
  614. msg = {'Too few files selected.',numstr};
  615. uiwait(errordlg(msg,'','modal'))
  616. return
  617. elseif numfiles > prop.numfiles(end)
  618. msg = {'Too many files selected.',numstr};
  619. uiwait(errordlg(msg,'','modal'))
  620. return
  621. end
  622. end
  623. delete(fig)
  624. end
  625. function cancel(varargin)
  626. prop.output = 'cancel';
  627. delete(fig)
  628. end
  629. function history_cb(varargin)
  630. current_dir = history{varargin{3}};
  631. full_filter = fullfile(current_dir,filter);
  632. path_cell = path2cell(current_dir);
  633. fdir = filtered_dir(full_filter,re_filter);
  634. filenames = {fdir.name}';
  635. filenames = annotate_file_names(filenames,fdir);
  636. set(dir_popup,'String',path_cell(end:-1:1),'Value',1)
  637. set(pathbox,'String',current_dir)
  638. set(navlist,'ListboxTop',1,'Value',[],'String',filenames)
  639. set(addbut,'Enable','off')
  640. set(openbut,'Enable','off')
  641. end
  642. end
  643. % -------------------- Subfunctions --------------------
  644. function c = path2cell(p)
  645. % Turns a path string into a cell array of path elements.
  646. c = strread(p,'%s','delimiter','\\/');
  647. if ispc
  648. c = [{'My Computer'};c];
  649. else
  650. c = [{filesep};c(2:end)];
  651. end
  652. end
  653. function p = cell2path(c)
  654. % Turns a cell array of path elements into a path string.
  655. if ispc
  656. p = fullfile(c{2:end},'');
  657. else
  658. p = fullfile(c{:},'');
  659. end
  660. end
  661. function d = filtered_dir(full_filter,re_filter)
  662. % Like dir, but applies filters and sorting.
  663. p = fileparts(full_filter);
  664. if isempty(p) && full_filter(1) == '/'
  665. p = '/';
  666. end
  667. if exist(full_filter,'dir')
  668. c = cell(0,1);
  669. dfiles = struct('name',c,'date',c,'bytes',c,'isdir',c);
  670. else
  671. dfiles = dir(full_filter);
  672. end
  673. if ~isempty(dfiles)
  674. dfiles([dfiles.isdir]) = [];
  675. end
  676. ddir = dir(p);
  677. ddir = ddir([ddir.isdir]);
  678. % Additional regular expression filter.
  679. if nargin > 1 && ~isempty(re_filter)
  680. if ispc
  681. no_match = cellfun('isempty',regexpi({dfiles.name},re_filter));
  682. else
  683. no_match = cellfun('isempty',regexp({dfiles.name},re_filter));
  684. end
  685. dfiles(no_match) = [];
  686. end
  687. % Set navigator style:
  688. % 1 => mix file and directory names
  689. % 2 => means list all files before all directories
  690. % 3 => means list all directories before all files
  691. % 4 => same as 2 except put . and .. directories first
  692. if isunix
  693. style = 4;
  694. else
  695. style = 4;
  696. end
  697. switch style
  698. case 1
  699. d = [dfiles;ddir];
  700. [unused,index] = sort({d.name});
  701. d = d(index);
  702. case 2
  703. [unused,index1] = sort({dfiles.name});
  704. [unused,index2] = sort({ddir.name});
  705. d = [dfiles(index1);ddir(index2)];
  706. case 3
  707. [unused,index1] = sort({dfiles.name});
  708. [unused,index2] = sort({ddir.name});
  709. d = [ddir(index2);dfiles(index1)];
  710. case 4
  711. [unused,index1] = sort({dfiles.name});
  712. dot1 = find(strcmp({ddir.name},'.'));
  713. dot2 = find(strcmp({ddir.name},'..'));
  714. ddot1 = ddir(dot1);
  715. ddot2 = ddir(dot2);
  716. ddir([dot1,dot2]) = [];
  717. [unused,index2] = sort({ddir.name});
  718. d = [ddot1;ddot2;dfiles(index1);ddir(index2)];
  719. end
  720. end
  721. function drives = getdrives
  722. % Returns a cell array of drive names on Windows.
  723. letters = char('A':'Z');
  724. num_letters = length(letters);
  725. drives = cell(1,num_letters);
  726. for i = 1:num_letters
  727. if exist([letters(i),':\'],'dir');
  728. drives{i} = [letters(i),':'];
  729. end
  730. end
  731. drives(cellfun('isempty',drives)) = [];
  732. end
  733. function filenames = annotate_file_names(filenames,dir_listing)
  734. % Adds a trailing filesep character to directory names.
  735. fs = filesep;
  736. for i = 1:length(filenames)
  737. if dir_listing(i).isdir
  738. filenames{i} = [filenames{i},fs];
  739. end
  740. end
  741. end
  742. function hist_menus = make_history_cm(cb,hist_cm,hist_menus,history)
  743. % Make context menu for history.
  744. if ~isempty(hist_menus)
  745. delete(hist_menus)
  746. end
  747. num_hist = length(history);
  748. hist_menus = zeros(1,num_hist);
  749. for i = 1:num_hist
  750. hist_menus(i) = uimenu(hist_cm,'Label',history{i},...
  751. 'Callback',{cb,i});
  752. end
  753. end