Mercurial > hg > ltpda
comparison m-toolbox/m/gui/gltpda/uipickfiles.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f0afece42f48 |
---|---|
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 | |
65 % Version: 1.0, 25 April 2006 | |
66 % Author: Douglas M. Schwarz | |
67 % Email: dmschwarz=ieee*org, dmschwarz=urgrad*rochester*edu | |
68 % Real_email = regexprep(Email,{'=','*'},{'@','.'}) | |
69 % $Id: uipickfiles.m,v 1.1 2008/03/01 13:43:20 nicola Exp $ | |
70 | |
71 | |
72 % Define properties and set default values. | |
73 prop.filterspec = '*'; | |
74 prop.refilter = ''; | |
75 prop.prompt = 'Select files'; | |
76 prop.numfiles = []; | |
77 prop.output = 'cell'; | |
78 | |
79 % Process inputs and set prop fields. | |
80 properties = fieldnames(prop); | |
81 arg_index = 1; | |
82 while arg_index <= nargin | |
83 arg = varargin{arg_index}; | |
84 if ischar(arg) | |
85 prop_index = find(strncmpi(arg,properties,length(arg))); | |
86 if length(prop_index) == 1 | |
87 prop.(properties{prop_index}) = varargin{arg_index + 1}; | |
88 else | |
89 error('Property ''%s'' does not exist or is ambiguous.',arg) | |
90 end | |
91 arg_index = arg_index + 2; | |
92 elseif isstruct(arg) | |
93 arg_fn = fieldnames(arg); | |
94 for i = 1:length(arg_fn) | |
95 prop_index = find(strncmpi(arg_fn{i},properties,... | |
96 length(arg_fn{i}))); | |
97 if length(prop_index) == 1 | |
98 prop.(properties{prop_index}) = arg.(arg_fn{i}); | |
99 else | |
100 error('Property ''%s'' does not exist or is ambiguous.',... | |
101 arg_fn{i}) | |
102 end | |
103 end | |
104 arg_index = arg_index + 1; | |
105 else | |
106 error(['Properties must be specified by property/value pairs',... | |
107 ' or structures.']) | |
108 end | |
109 end | |
110 | |
111 % Validate FilterSpec property. | |
112 if isempty(prop.filterspec) | |
113 prop.filterspec = '*'; | |
114 end | |
115 if ~ischar(prop.filterspec) | |
116 error('FilterSpec property must contain a string.') | |
117 end | |
118 | |
119 % Validate REFilter property. | |
120 if ~ischar(prop.refilter) | |
121 error('REFilter property must contain a string.') | |
122 end | |
123 | |
124 % Validate Prompt property. | |
125 if ~ischar(prop.prompt) | |
126 error('Prompt property must contain a string.') | |
127 end | |
128 | |
129 % Validate NumFiles property. | |
130 if numel(prop.numfiles) > 2 || any(prop.numfiles < 0) | |
131 error('NumFiles must be empty, a scalar or two-element vector.') | |
132 end | |
133 prop.numfiles = unique(prop.numfiles); | |
134 if isequal(prop.numfiles,1) | |
135 numstr = 'Select exactly 1 file.'; | |
136 elseif length(prop.numfiles) == 1 | |
137 numstr = sprintf('Select exactly %d files.',prop.numfiles); | |
138 else | |
139 numstr = sprintf('Select %d to %d files.',prop.numfiles); | |
140 end | |
141 | |
142 % Validate Output property. | |
143 legal_outputs = {'cell','struct','char'}; | |
144 out_idx = find(strncmpi(prop.output,legal_outputs,length(prop.output))); | |
145 if length(out_idx) == 1 | |
146 prop.output = legal_outputs{out_idx}; | |
147 else | |
148 error(['Value of ''Output'' property, ''%s'', is illegal or '... | |
149 'ambiguous.'],prop.output) | |
150 end | |
151 | |
152 | |
153 % Initialize file lists. | |
154 [current_dir,f,e] = fileparts(prop.filterspec); | |
155 filter = [f,e]; | |
156 if isempty(current_dir) | |
157 current_dir = pwd; | |
158 end | |
159 if isempty(filter) | |
160 filter = '*'; | |
161 end | |
162 re_filter = prop.refilter; | |
163 full_filter = fullfile(current_dir,filter); | |
164 path_cell = path2cell(current_dir); | |
165 fdir = filtered_dir(full_filter,re_filter); | |
166 filenames = {fdir.name}'; | |
167 filenames = annotate_file_names(filenames,fdir); | |
168 | |
169 % Initialize some data. | |
170 file_picks = {}; | |
171 full_file_picks = {}; | |
172 dir_picks = dir(' '); % Create empty directory structure. | |
173 show_full_path = false; | |
174 nodupes = true; | |
175 history = {current_dir}; | |
176 | |
177 % Create figure. | |
178 gray = get(0,'DefaultUIControlBackgroundColor'); | |
179 fig = figure('Position',[0 0 740 445],... | |
180 'Color',gray,... | |
181 'WindowStyle','modal',... | |
182 'Resize','off',... | |
183 'NumberTitle','off',... | |
184 'Name',prop.prompt,... | |
185 'IntegerHandle','off',... | |
186 'CloseRequestFcn',@cancel,... | |
187 'CreateFcn',{@movegui,'center'}); | |
188 | |
189 % Create uicontrols. | |
190 uicontrol('Style','frame',... | |
191 'Position',[255 260 110 70]) | |
192 uicontrol('Style','frame',... | |
193 'Position',[275 135 110 100]) | |
194 | |
195 navlist = uicontrol('Style','listbox',... | |
196 'Position',[10 10 250 320],... | |
197 'String',filenames,... | |
198 'Value',[],... | |
199 'BackgroundColor','w',... | |
200 'Callback',@clicknav,... | |
201 'Max',2); | |
202 pickslist = uicontrol('Style','listbox',... | |
203 'Position',[380 10 350 320],... | |
204 'String',{},... | |
205 'BackgroundColor','w',... | |
206 'Callback',@clickpicks,... | |
207 'Max',2); | |
208 | |
209 openbut = uicontrol('Style','pushbutton',... | |
210 'Position',[270 300 80 20],... | |
211 'String','Open',... | |
212 'Enable','off',... | |
213 'Callback',@open); | |
214 arrow = [2 2 2 2 2 2 2 2 1 2 2 2;... | |
215 2 2 2 2 2 2 2 2 2 0 2 2;... | |
216 2 2 2 2 2 2 2 2 2 2 0 2;... | |
217 0 0 0 0 0 0 0 0 0 0 0 0;... | |
218 2 2 2 2 2 2 2 2 2 2 0 2;... | |
219 2 2 2 2 2 2 2 2 2 0 2 2;... | |
220 2 2 2 2 2 2 2 2 1 2 2 2]; | |
221 arrow(arrow == 2) = NaN; | |
222 arrow_im = NaN*ones(16,76); | |
223 arrow_im(6:12,45:56) = arrow/2; | |
224 im = repmat(arrow_im,[1 1 3]); | |
225 addbut = uicontrol('Style','pushbutton',... | |
226 'Position',[270 270 80 20],... | |
227 'String','Add ',... | |
228 'Enable','off',... | |
229 'CData',im,... | |
230 'Callback',@add); | |
231 | |
232 removebut = uicontrol('Style','pushbutton',... | |
233 'Position',[290 205 80 20],... | |
234 'String','Remove',... | |
235 'Enable','off',... | |
236 'Callback',@remove); | |
237 moveupbut = uicontrol('Style','pushbutton',... | |
238 'Position',[290 175 80 20],... | |
239 'String','Move Up',... | |
240 'Enable','off',... | |
241 'Callback',@moveup); | |
242 movedownbut = uicontrol('Style','pushbutton',... | |
243 'Position',[290 145 80 20],... | |
244 'String','Move Down',... | |
245 'Enable','off',... | |
246 'Callback',@movedown); | |
247 | |
248 uicontrol('Position',[10 380 250 16],... | |
249 'Style','text',... | |
250 'String','Current Directory',... | |
251 'HorizontalAlignment','center') | |
252 dir_popup = uicontrol('Style','popupmenu',... | |
253 'Position',[10 335 250 20],... | |
254 'BackgroundColor','w',... | |
255 'String',path_cell(end:-1:1),... | |
256 'Value',1,... | |
257 'Callback',@dirpopup); | |
258 hist_cm = uicontextmenu; | |
259 pathbox = uicontrol('Position',[10 360 250 20],... | |
260 'Style','edit',... | |
261 'BackgroundColor','w',... | |
262 'String',current_dir,... | |
263 'HorizontalAlignment','left',... | |
264 'Callback',@change_path,... | |
265 'UIContextMenu',hist_cm); | |
266 hist_menus = []; | |
267 hist_cb = @history_cb; | |
268 hist_menus = make_history_cm(hist_cb,hist_cm,hist_menus,history); | |
269 | |
270 uicontrol('Position',[10 425 80 16],... | |
271 'Style','text',... | |
272 'String','File Filter',... | |
273 'HorizontalAlignment','left') | |
274 uicontrol('Position',[100 425 160 16],... | |
275 'Style','text',... | |
276 'String','Reg. Exp. Filter',... | |
277 'HorizontalAlignment','left') | |
278 showallfiles = uicontrol('Position',[270 405 100 20],... | |
279 'Style','checkbox',... | |
280 'String','Show All Files',... | |
281 'Value',0,... | |
282 'HorizontalAlignment','left',... | |
283 'Callback',@togglefilter); | |
284 filter_ed = uicontrol('Position',[10 405 80 20],... | |
285 'Style','edit',... | |
286 'BackgroundColor','w',... | |
287 'String',filter,... | |
288 'HorizontalAlignment','left',... | |
289 'Callback',@setfilspec); | |
290 refilter_ed = uicontrol('Position',[100 405 160 20],... | |
291 'Style','edit',... | |
292 'BackgroundColor','w',... | |
293 'String',re_filter,... | |
294 'HorizontalAlignment','left',... | |
295 'Callback',@setrefilter); | |
296 | |
297 viewfullpath = uicontrol('Style','checkbox',... | |
298 'Position',[380 335 230 20],... | |
299 'String','Show full paths',... | |
300 'Value',show_full_path,... | |
301 'HorizontalAlignment','left',... | |
302 'Callback',@showfullpath); | |
303 remove_dupes = uicontrol('Style','checkbox',... | |
304 'Position',[380 360 230 20],... | |
305 'String','Remove duplicates (as per full path)',... | |
306 'Value',nodupes,... | |
307 'HorizontalAlignment','left',... | |
308 'Callback',@removedupes); | |
309 uicontrol('Position',[380 405 350 20],... | |
310 'Style','text',... | |
311 'String','Selected Files',... | |
312 'HorizontalAlignment','center') | |
313 uicontrol('Position',[280 80 80 30],'String','Done',... | |
314 'Callback',@done); | |
315 uicontrol('Position',[280 30 80 30],'String','Cancel',... | |
316 'Callback',@cancel); | |
317 | |
318 if ~isempty(prop.numfiles) | |
319 uicontrol('Position',[380 385 350 16],... | |
320 'Style','text',... | |
321 'String',numstr,... | |
322 'ForegroundColor','r',... | |
323 'HorizontalAlignment','center') | |
324 end | |
325 | |
326 set(fig,'HandleVisibility','off') | |
327 | |
328 uiwait(fig) | |
329 | |
330 % Compute desired output. | |
331 switch prop.output | |
332 case 'cell' | |
333 out = full_file_picks; | |
334 case 'struct' | |
335 out = dir_picks(:); | |
336 case 'char' | |
337 out = char(full_file_picks); | |
338 case 'cancel' | |
339 out = 0; | |
340 end | |
341 | |
342 % -------------------- Callback functions -------------------- | |
343 | |
344 function add(varargin) | |
345 values = get(navlist,'Value'); | |
346 for i = 1:length(values) | |
347 dir_pick = fdir(values(i)); | |
348 pick = dir_pick.name; | |
349 pick_full = fullfile(current_dir,pick); | |
350 dir_pick.name = pick_full; | |
351 if ~nodupes || ~any(strcmp(full_file_picks,pick_full)) | |
352 file_picks{end + 1} = pick; | |
353 full_file_picks{end + 1} = pick_full; | |
354 dir_picks(end + 1) = dir_pick; | |
355 end | |
356 end | |
357 if show_full_path | |
358 set(pickslist,'String',full_file_picks,'Value',[]); | |
359 else | |
360 set(pickslist,'String',file_picks,'Value',[]); | |
361 end | |
362 set([removebut,moveupbut,movedownbut],'Enable','off'); | |
363 end | |
364 | |
365 function remove(varargin) | |
366 values = get(pickslist,'Value'); | |
367 file_picks(values) = []; | |
368 full_file_picks(values) = []; | |
369 dir_picks(values) = []; | |
370 top = get(pickslist,'ListboxTop'); | |
371 num_above_top = sum(values < top); | |
372 top = top - num_above_top; | |
373 num_picks = length(file_picks); | |
374 new_value = min(min(values) - num_above_top,num_picks); | |
375 if num_picks == 0 | |
376 new_value = []; | |
377 set([removebut,moveupbut,movedownbut],'Enable','off') | |
378 end | |
379 if show_full_path | |
380 set(pickslist,'String',full_file_picks,'Value',new_value,... | |
381 'ListboxTop',top) | |
382 else | |
383 set(pickslist,'String',file_picks,'Value',new_value,... | |
384 'ListboxTop',top) | |
385 end | |
386 end | |
387 | |
388 function open(varargin) | |
389 values = get(navlist,'Value'); | |
390 if fdir(values).isdir | |
391 if strcmp(fdir(values).name,'.') | |
392 return | |
393 elseif strcmp(fdir(values).name,'..') | |
394 set(dir_popup,'Value',min(2,length(path_cell))) | |
395 dirpopup(); | |
396 return | |
397 end | |
398 current_dir = fullfile(current_dir,fdir(values).name); | |
399 history{end+1} = current_dir; | |
400 history = unique(history); | |
401 hist_menus = make_history_cm(hist_cb,hist_cm,hist_menus,... | |
402 history); | |
403 full_filter = fullfile(current_dir,filter); | |
404 path_cell = path2cell(current_dir); | |
405 fdir = filtered_dir(full_filter,re_filter); | |
406 filenames = {fdir.name}'; | |
407 filenames = annotate_file_names(filenames,fdir); | |
408 set(dir_popup,'String',path_cell(end:-1:1),'Value',1) | |
409 set(pathbox,'String',current_dir) | |
410 set(navlist,'ListboxTop',1,'Value',[],'String',filenames) | |
411 set(addbut,'Enable','off') | |
412 set(openbut,'Enable','off') | |
413 end | |
414 end | |
415 | |
416 function clicknav(varargin) | |
417 value = get(navlist,'Value'); | |
418 nval = length(value); | |
419 dbl_click_fcn = @add; | |
420 switch nval | |
421 case 0 | |
422 set([addbut,openbut],'Enable','off') | |
423 case 1 | |
424 set(addbut,'Enable','on'); | |
425 if fdir(value).isdir | |
426 set(openbut,'Enable','on') | |
427 dbl_click_fcn = @open; | |
428 else | |
429 set(openbut,'Enable','off') | |
430 end | |
431 otherwise | |
432 set(addbut,'Enable','on') | |
433 set(openbut,'Enable','off') | |
434 end | |
435 if strcmp(get(fig,'SelectionType'),'open') | |
436 dbl_click_fcn(); | |
437 end | |
438 end | |
439 | |
440 function clickpicks(varargin) | |
441 value = get(pickslist,'Value'); | |
442 if isempty(value) | |
443 set([removebut,moveupbut,movedownbut],'Enable','off') | |
444 else | |
445 set(removebut,'Enable','on') | |
446 if min(value) == 1 | |
447 set(moveupbut,'Enable','off') | |
448 else | |
449 set(moveupbut,'Enable','on') | |
450 end | |
451 if max(value) == length(file_picks) | |
452 set(movedownbut,'Enable','off') | |
453 else | |
454 set(movedownbut,'Enable','on') | |
455 end | |
456 end | |
457 if strcmp(get(fig,'SelectionType'),'open') | |
458 remove(); | |
459 end | |
460 end | |
461 | |
462 function dirpopup(varargin) | |
463 value = get(dir_popup,'Value'); | |
464 len = length(path_cell); | |
465 path_cell = path_cell(1:end-value+1); | |
466 if ispc && value == len | |
467 current_dir = ''; | |
468 full_filter = filter; | |
469 fdir = struct('name',getdrives,'date',datestr(now),... | |
470 'bytes',0,'isdir',1); | |
471 else | |
472 current_dir = cell2path(path_cell); | |
473 history{end+1} = current_dir; | |
474 history = unique(history); | |
475 hist_menus = make_history_cm(hist_cb,hist_cm,hist_menus,... | |
476 history); | |
477 full_filter = fullfile(current_dir,filter); | |
478 fdir = filtered_dir(full_filter,re_filter); | |
479 end | |
480 filenames = {fdir.name}'; | |
481 filenames = annotate_file_names(filenames,fdir); | |
482 set(dir_popup,'String',path_cell(end:-1:1),'Value',1) | |
483 set(pathbox,'String',current_dir) | |
484 set(navlist,'String',filenames,'Value',[]) | |
485 set(addbut,'Enable','off') | |
486 end | |
487 | |
488 function change_path(varargin) | |
489 proposed_path = get(pathbox,'String'); | |
490 % Process any directories named '..'. | |
491 proposed_path_cell = path2cell(proposed_path); | |
492 ddots = strcmp(proposed_path_cell,'..'); | |
493 ddots(find(ddots) - 1) = true; | |
494 proposed_path_cell(ddots) = []; | |
495 proposed_path = cell2path(proposed_path_cell); | |
496 % Check for existance of directory. | |
497 if ~exist(proposed_path,'dir') | |
498 uiwait(errordlg(['Directory "',proposed_path,... | |
499 '" does not exist.'],'','modal')) | |
500 return | |
501 end | |
502 current_dir = proposed_path; | |
503 history{end+1} = current_dir; | |
504 history = unique(history); | |
505 hist_menus = make_history_cm(hist_cb,hist_cm,hist_menus,history); | |
506 full_filter = fullfile(current_dir,filter); | |
507 path_cell = path2cell(current_dir); | |
508 fdir = filtered_dir(full_filter,re_filter); | |
509 filenames = {fdir.name}'; | |
510 filenames = annotate_file_names(filenames,fdir); | |
511 set(dir_popup,'String',path_cell(end:-1:1),'Value',1) | |
512 set(pathbox,'String',current_dir) | |
513 set(navlist,'String',filenames,'Value',[]) | |
514 set(addbut,'Enable','off') | |
515 set(openbut,'Enable','off') | |
516 end | |
517 | |
518 function showfullpath(varargin) | |
519 show_full_path = get(viewfullpath,'Value'); | |
520 if show_full_path | |
521 set(pickslist,'String',full_file_picks) | |
522 else | |
523 set(pickslist,'String',file_picks) | |
524 end | |
525 end | |
526 | |
527 function removedupes(varargin) | |
528 nodupes = get(remove_dupes,'Value'); | |
529 if nodupes | |
530 num_picks = length(full_file_picks); | |
531 [unused,rev_order] = unique(full_file_picks(end:-1:1)); | |
532 order = sort(num_picks + 1 - rev_order); | |
533 full_file_picks = full_file_picks(order); | |
534 file_picks = file_picks(order); | |
535 if show_full_path | |
536 set(pickslist,'String',full_file_picks,'Value',[]) | |
537 else | |
538 set(pickslist,'String',file_picks,'Value',[]) | |
539 end | |
540 set([removebut,moveupbut,movedownbut],'Enable','off') | |
541 end | |
542 end | |
543 | |
544 function moveup(varargin) | |
545 value = get(pickslist,'Value'); | |
546 set(removebut,'Enable','on') | |
547 n = length(file_picks); | |
548 omega = 1:n; | |
549 index = zeros(1,n); | |
550 index(value - 1) = omega(value); | |
551 index(setdiff(omega,value - 1)) = omega(setdiff(omega,value)); | |
552 file_picks = file_picks(index); | |
553 full_file_picks = full_file_picks(index); | |
554 value = value - 1; | |
555 if show_full_path | |
556 set(pickslist,'String',full_file_picks,'Value',value) | |
557 else | |
558 set(pickslist,'String',file_picks,'Value',value) | |
559 end | |
560 if min(value) == 1 | |
561 set(moveupbut,'Enable','off') | |
562 end | |
563 set(movedownbut,'Enable','on') | |
564 end | |
565 | |
566 function movedown(varargin) | |
567 value = get(pickslist,'Value'); | |
568 set(removebut,'Enable','on') | |
569 n = length(file_picks); | |
570 omega = 1:n; | |
571 index = zeros(1,n); | |
572 index(value + 1) = omega(value); | |
573 index(setdiff(omega,value + 1)) = omega(setdiff(omega,value)); | |
574 file_picks = file_picks(index); | |
575 full_file_picks = full_file_picks(index); | |
576 value = value + 1; | |
577 if show_full_path | |
578 set(pickslist,'String',full_file_picks,'Value',value) | |
579 else | |
580 set(pickslist,'String',file_picks,'Value',value) | |
581 end | |
582 if max(value) == n | |
583 set(movedownbut,'Enable','off') | |
584 end | |
585 set(moveupbut,'Enable','on') | |
586 end | |
587 | |
588 function togglefilter(varargin) | |
589 value = get(showallfiles,'Value'); | |
590 if value | |
591 filter = '*'; | |
592 re_filter = ''; | |
593 set([filter_ed,refilter_ed],'Enable','off') | |
594 else | |
595 filter = get(filter_ed,'String'); | |
596 re_filter = get(refilter_ed,'String'); | |
597 set([filter_ed,refilter_ed],'Enable','on') | |
598 end | |
599 full_filter = fullfile(current_dir,filter); | |
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 | |
607 function setfilspec(varargin) | |
608 filter = get(filter_ed,'String'); | |
609 if isempty(filter) | |
610 filter = '*'; | |
611 set(filter_ed,'String',filter) | |
612 end | |
613 % Process file spec if a subdirectory was included. | |
614 [p,f,e] = fileparts(filter); | |
615 if ~isempty(p) | |
616 newpath = fullfile(current_dir,p,''); | |
617 set(pathbox,'String',newpath) | |
618 filter = [f,e]; | |
619 if isempty(filter) | |
620 filter = '*'; | |
621 end | |
622 set(filter_ed,'String',filter) | |
623 change_path(); | |
624 end | |
625 full_filter = fullfile(current_dir,filter); | |
626 fdir = filtered_dir(full_filter,re_filter); | |
627 filenames = {fdir.name}'; | |
628 filenames = annotate_file_names(filenames,fdir); | |
629 set(navlist,'String',filenames,'Value',[]) | |
630 set(addbut,'Enable','off') | |
631 end | |
632 | |
633 function setrefilter(varargin) | |
634 re_filter = get(refilter_ed,'String'); | |
635 fdir = filtered_dir(full_filter,re_filter); | |
636 filenames = {fdir.name}'; | |
637 filenames = annotate_file_names(filenames,fdir); | |
638 set(navlist,'String',filenames,'Value',[]) | |
639 set(addbut,'Enable','off') | |
640 end | |
641 | |
642 function done(varargin) | |
643 % Optional shortcut: click on a file and press 'Done'. | |
644 % if isempty(full_file_picks) && strcmp(get(addbut,'Enable'),'on') | |
645 % add(); | |
646 % end | |
647 numfiles = length(full_file_picks); | |
648 if ~isempty(prop.numfiles) | |
649 if numfiles < prop.numfiles(1) | |
650 msg = {'Too few files selected.',numstr}; | |
651 uiwait(errordlg(msg,'','modal')) | |
652 return | |
653 elseif numfiles > prop.numfiles(end) | |
654 msg = {'Too many files selected.',numstr}; | |
655 uiwait(errordlg(msg,'','modal')) | |
656 return | |
657 end | |
658 end | |
659 delete(fig) | |
660 end | |
661 | |
662 function cancel(varargin) | |
663 prop.output = 'cancel'; | |
664 delete(fig) | |
665 end | |
666 | |
667 function history_cb(varargin) | |
668 current_dir = history{varargin{3}}; | |
669 full_filter = fullfile(current_dir,filter); | |
670 path_cell = path2cell(current_dir); | |
671 fdir = filtered_dir(full_filter,re_filter); | |
672 filenames = {fdir.name}'; | |
673 filenames = annotate_file_names(filenames,fdir); | |
674 set(dir_popup,'String',path_cell(end:-1:1),'Value',1) | |
675 set(pathbox,'String',current_dir) | |
676 set(navlist,'ListboxTop',1,'Value',[],'String',filenames) | |
677 set(addbut,'Enable','off') | |
678 set(openbut,'Enable','off') | |
679 end | |
680 end | |
681 | |
682 | |
683 % -------------------- Subfunctions -------------------- | |
684 | |
685 function c = path2cell(p) | |
686 % Turns a path string into a cell array of path elements. | |
687 c = strread(p,'%s','delimiter','\\/'); | |
688 if ispc | |
689 c = [{'My Computer'};c]; | |
690 else | |
691 c = [{filesep};c(2:end)]; | |
692 end | |
693 end | |
694 | |
695 | |
696 function p = cell2path(c) | |
697 % Turns a cell array of path elements into a path string. | |
698 if ispc | |
699 p = fullfile(c{2:end},''); | |
700 else | |
701 p = fullfile(c{:},''); | |
702 end | |
703 end | |
704 | |
705 | |
706 function d = filtered_dir(full_filter,re_filter) | |
707 % Like dir, but applies filters and sorting. | |
708 p = fileparts(full_filter); | |
709 if isempty(p) && full_filter(1) == '/' | |
710 p = '/'; | |
711 end | |
712 if exist(full_filter,'dir') | |
713 c = cell(0,1); | |
714 dfiles = struct('name',c,'date',c,'bytes',c,'isdir',c); | |
715 else | |
716 dfiles = dir(full_filter); | |
717 end | |
718 if ~isempty(dfiles) | |
719 dfiles([dfiles.isdir]) = []; | |
720 end | |
721 ddir = dir(p); | |
722 ddir = ddir([ddir.isdir]); | |
723 % Additional regular expression filter. | |
724 if nargin > 1 && ~isempty(re_filter) | |
725 if ispc | |
726 no_match = cellfun('isempty',regexpi({dfiles.name},re_filter)); | |
727 else | |
728 no_match = cellfun('isempty',regexp({dfiles.name},re_filter)); | |
729 end | |
730 dfiles(no_match) = []; | |
731 end | |
732 % Set navigator style: | |
733 % 1 => mix file and directory names | |
734 % 2 => means list all files before all directories | |
735 % 3 => means list all directories before all files | |
736 % 4 => same as 2 except put . and .. directories first | |
737 if isunix | |
738 style = 4; | |
739 else | |
740 style = 4; | |
741 end | |
742 switch style | |
743 case 1 | |
744 d = [dfiles;ddir]; | |
745 [unused,index] = sort({d.name}); | |
746 d = d(index); | |
747 case 2 | |
748 [unused,index1] = sort({dfiles.name}); | |
749 [unused,index2] = sort({ddir.name}); | |
750 d = [dfiles(index1);ddir(index2)]; | |
751 case 3 | |
752 [unused,index1] = sort({dfiles.name}); | |
753 [unused,index2] = sort({ddir.name}); | |
754 d = [ddir(index2);dfiles(index1)]; | |
755 case 4 | |
756 [unused,index1] = sort({dfiles.name}); | |
757 dot1 = find(strcmp({ddir.name},'.')); | |
758 dot2 = find(strcmp({ddir.name},'..')); | |
759 ddot1 = ddir(dot1); | |
760 ddot2 = ddir(dot2); | |
761 ddir([dot1,dot2]) = []; | |
762 [unused,index2] = sort({ddir.name}); | |
763 d = [ddot1;ddot2;dfiles(index1);ddir(index2)]; | |
764 end | |
765 end | |
766 | |
767 | |
768 function drives = getdrives | |
769 % Returns a cell array of drive names on Windows. | |
770 letters = char('A':'Z'); | |
771 num_letters = length(letters); | |
772 drives = cell(1,num_letters); | |
773 for i = 1:num_letters | |
774 if exist([letters(i),':\'],'dir'); | |
775 drives{i} = [letters(i),':']; | |
776 end | |
777 end | |
778 drives(cellfun('isempty',drives)) = []; | |
779 end | |
780 | |
781 | |
782 function filenames = annotate_file_names(filenames,dir_listing) | |
783 % Adds a trailing filesep character to directory names. | |
784 fs = filesep; | |
785 for i = 1:length(filenames) | |
786 if dir_listing(i).isdir | |
787 filenames{i} = [filenames{i},fs]; | |
788 end | |
789 end | |
790 end | |
791 | |
792 | |
793 function hist_menus = make_history_cm(cb,hist_cm,hist_menus,history) | |
794 % Make context menu for history. | |
795 if ~isempty(hist_menus) | |
796 delete(hist_menus) | |
797 end | |
798 num_hist = length(history); | |
799 hist_menus = zeros(1,num_hist); | |
800 for i = 1:num_hist | |
801 hist_menus(i) = uimenu(hist_cm,'Label',history{i},... | |
802 'Callback',{cb,i}); | |
803 end | |
804 end |