1 | function theResult = guido(theStruct, theFigureName, isModal, thePrecision) |
---|
2 | |
---|
3 | % guido -- Get info via Matlab struct. |
---|
4 | % guido('demo') demonstrates itself, using the commands |
---|
5 | % given below. |
---|
6 | % guido(theStruct, 'theFigureName') presents a dialog |
---|
7 | % representing the fieldnames and values of theStruct, |
---|
8 | % a Matlab "struct" which must be compatible with |
---|
9 | % "getinfo" and "setinfo". If theStruct contains |
---|
10 | % embedded structs, nested dialogs are produced for |
---|
11 | % them as needed. The empty-matrix [] is returned |
---|
12 | % if the main "Cancel" button is pressed. Also, use |
---|
13 | % "Cancel" to escape a sub-dialog without saving its |
---|
14 | % most recent changes. Fields named "help_..." are |
---|
15 | % shown in a separate dialog. If theFigureName is |
---|
16 | % not given or is empty, the external name of |
---|
17 | % theStruct will be used. |
---|
18 | % guido(theStruct, 'theFigureName', isModal) uses modal |
---|
19 | % dialogs on non-PCWIN machines if "isModal" evaluates |
---|
20 | % to logical(1) TRUE. The default is to use non-modal |
---|
21 | % dialogs, which allows interactions with other windows, |
---|
22 | % except the Matlab command window. In either case, the |
---|
23 | % the routine prevents dialogs from being dismissed out |
---|
24 | % of sequence. |
---|
25 | % guido(theStruct, 'theFigureName', isModal, thePrecision) |
---|
26 | % uses thePrecision (default = 4) when displaying numbers |
---|
27 | % in an "edit" control. |
---|
28 | % |
---|
29 | % Commands used in the demonstration: |
---|
30 | % |
---|
31 | % s.help = help(mfilename); |
---|
32 | % s.anEdit = 'some text'; |
---|
33 | % s.aNumber = pi; |
---|
34 | % s.aCheckbox = {'checkbox' 0}; |
---|
35 | % s.aRadiobutton = {'radiobutton' 0}; |
---|
36 | % s.aPopupmenu = {{'red', 'blue', 'green'}, 1}; |
---|
37 | % s.aSubdialog.aPopupmenu = {{10 20 30}, 1}; |
---|
38 | % guido(s, [mfilename ' demo']) |
---|
39 | |
---|
40 | % Note: the present m-file can be renamed without |
---|
41 | % requiring any changes to the Matlab code itself. |
---|
42 | |
---|
43 | % Copyright (C) 1999 Dr. Charles R. Denham, ZYDECO. |
---|
44 | % All Rights Reserved. |
---|
45 | % Disclosure without explicit written consent from the |
---|
46 | % copyright owner does not constitute publication. |
---|
47 | |
---|
48 | % Version of 15-Dec-1999 13:39:54. |
---|
49 | % Updated 25-Jan-2000 11:47:42. |
---|
50 | |
---|
51 | persistent CURRENT_STRUCT |
---|
52 | persistent CURRENT_FIGURES |
---|
53 | |
---|
54 | LF = char(10); |
---|
55 | CR = char(13); |
---|
56 | CRLF = [CR LF]; |
---|
57 | BABY_BLUE = [8 10 10]/10; |
---|
58 | |
---|
59 | if nargout > 0, theResult = []; end |
---|
60 | |
---|
61 | % Launch a demo if this is not a callback. |
---|
62 | |
---|
63 | if nargin < 1 & isempty(gcbo) |
---|
64 | help(mfilename) |
---|
65 | ans = feval(mfilename, 'demo'); |
---|
66 | if nargout > 0 |
---|
67 | theResult = CURRENT_STRUCT; |
---|
68 | else |
---|
69 | assignin('caller', 'ans', CURRENT_STRUCT) |
---|
70 | end |
---|
71 | return |
---|
72 | end |
---|
73 | |
---|
74 | % Do the demo. |
---|
75 | |
---|
76 | if nargin > 0 & isequal(theStruct, 'demo') |
---|
77 | if nargin < 2, theFigureName = [mfilename ' demo']; end |
---|
78 | s = []; |
---|
79 | s.help = help(mfilename); |
---|
80 | s.anEdit = 'some text'; |
---|
81 | s.aNumber = pi; |
---|
82 | s.aCheckbox = {'checkbox' 0}; |
---|
83 | s.aRadiobutton = {'radiobutton' 0}; |
---|
84 | s.aPopupmenu = {{'red', 'blue', 'green'}, 1}; |
---|
85 | s.aSubdialog.aPopupmenu = {{10 20 30}, 1}; |
---|
86 | % s.aSubdialog.bSubdialog.bPopupmenu = {{100 200 300}, 1}; |
---|
87 | disp(s) |
---|
88 | |
---|
89 | assign([mfilename '_demo'], s) |
---|
90 | result = feval(mfilename, eval([mfilename '_demo']), '', 0); |
---|
91 | assign([mfilename '_result'], result) |
---|
92 | |
---|
93 | if ~isempty(eval([mfilename '_result'])) |
---|
94 | result = feval(mfilename, eval([mfilename '_result']), '', 0); |
---|
95 | assign([mfilename '_result'], result) |
---|
96 | end |
---|
97 | if nargout > 0 |
---|
98 | assign('theResult', [mfilename '_result']) |
---|
99 | end |
---|
100 | return |
---|
101 | end |
---|
102 | |
---|
103 | if nargin > 0 & ischar(theStruct) |
---|
104 | theCommand = lower(theStruct); |
---|
105 | end |
---|
106 | |
---|
107 | if 0 & nargin > 0 & ischar(theStruct) |
---|
108 | switch theCommand |
---|
109 | case '_keypress_' |
---|
110 | theKey = get(gcbf, 'CurrentCharacter'); |
---|
111 | if any(abs(theKey) < 32) |
---|
112 | theCommand = '_okay_'; |
---|
113 | end |
---|
114 | end |
---|
115 | end |
---|
116 | |
---|
117 | % Dismiss dialogs in sequence. |
---|
118 | |
---|
119 | if nargin > 0 & ischar(theStruct) |
---|
120 | switch theCommand |
---|
121 | case {'_okay_', '_cancel_'} |
---|
122 | CURRENT_FIGURES(~ishandle(CURRENT_FIGURES)) = []; |
---|
123 | if ~isempty(CURRENT_FIGURES) & gcbf ~= CURRENT_FIGURES(end) |
---|
124 | figure(CURRENT_FIGURES(end)) |
---|
125 | h = helpdlg('Dismiss dialogs in sequence.', 'Please...'); |
---|
126 | tic |
---|
127 | while ishandle(h) & toc < 3 |
---|
128 | drawnow |
---|
129 | end |
---|
130 | if ishandle(h), delete(h), end |
---|
131 | return |
---|
132 | end |
---|
133 | end |
---|
134 | end |
---|
135 | |
---|
136 | % Process a command: okay or cancel. |
---|
137 | |
---|
138 | if nargin > 0 & ischar(theStruct) |
---|
139 | switch theCommand |
---|
140 | case '_okay_' |
---|
141 | CURRENT_STRUCT = get(gcbf, 'UserData'); |
---|
142 | theControls = findobj(gcbf, 'Type', 'uicontrol', 'Tag', mfilename); |
---|
143 | theControls = sort(theControls); |
---|
144 | for i = 2:2:length(theControls) |
---|
145 | theField = get(theControls(i-1), 'String'); |
---|
146 | theControl = theControls(i); |
---|
147 | theStyle = get(theControl, 'Style'); |
---|
148 | switch theStyle |
---|
149 | case 'pushbutton' |
---|
150 | okay = 0; |
---|
151 | case 'checkbox' |
---|
152 | theValue = get(theControl, 'Value'); |
---|
153 | okay = 1; |
---|
154 | case 'radiobutton' |
---|
155 | theValue = get(theControl, 'Value'); |
---|
156 | okay = 1; |
---|
157 | case 'edit' |
---|
158 | if isequal(theField, 'help') |
---|
159 | okay = 0; |
---|
160 | else |
---|
161 | theValue = eval(get(theControl, 'String')); |
---|
162 | okay = 1; |
---|
163 | end |
---|
164 | case 'popupmenu' |
---|
165 | theValue = get(theControl, 'Value'); |
---|
166 | okay = 1; |
---|
167 | otherwise |
---|
168 | okay = 0; |
---|
169 | warning([' ## Unsupported control style: ' theStyle]) |
---|
170 | end |
---|
171 | if okay |
---|
172 | CURRENT_STRUCT = setinfo(CURRENT_STRUCT, theField, theValue); |
---|
173 | end |
---|
174 | end |
---|
175 | if ~isempty(CURRENT_FIGURES) & any(CURRENT_FIGURES == gcbf) |
---|
176 | CURRENT_FIGURES(CURRENT_FIGURES == gcbf) = []; |
---|
177 | end |
---|
178 | delete(gcbf) |
---|
179 | case '_cancel_' |
---|
180 | CURRENT_STRUCT = []; |
---|
181 | if ~isempty(CURRENT_FIGURES) & any(CURRENT_FIGURES == gcbf) |
---|
182 | CURRENT_FIGURES(CURRENT_FIGURES == gcbf) = []; |
---|
183 | end |
---|
184 | delete(gcbf) |
---|
185 | otherwise |
---|
186 | disp([' ## Unknown command: ' theCommand]) |
---|
187 | end |
---|
188 | return |
---|
189 | end |
---|
190 | |
---|
191 | % Build the dialog if it does not already exist. |
---|
192 | |
---|
193 | if nargin > 0 & isstruct(theStruct) |
---|
194 | theStruct = setinfo(theStruct); |
---|
195 | if nargin < 2 | isempty(theFigureName) |
---|
196 | theFigureName = inputname(1); |
---|
197 | if isempty(theFigureName) |
---|
198 | theFigureName = 'unnamed'; |
---|
199 | end |
---|
200 | end |
---|
201 | if isempty(theFigureName), theFigureName = mfilename; end |
---|
202 | |
---|
203 | f = findobj('Type', 'figure', 'Name', theFigureName, 'Tag', mfilename); |
---|
204 | if any(f) |
---|
205 | figure(f) |
---|
206 | return |
---|
207 | end |
---|
208 | |
---|
209 | if nargin < 3, isModal = 0; end |
---|
210 | if nargin < 4, thePrecision = 4; end |
---|
211 | |
---|
212 | if all(isModal(:)) & ~any(findstr(computer, 'PCWIN')) |
---|
213 | theWindowStyle = 'modal'; |
---|
214 | else |
---|
215 | theWindowStyle = 'normal'; |
---|
216 | end |
---|
217 | theFigures = findobj('Type', 'figure', 'Tag', mfilename); |
---|
218 | theFigure = figure( ... |
---|
219 | 'Name', theFigureName, ... |
---|
220 | 'WindowStyle', theWindowStyle, ... |
---|
221 | 'Visible', 'off', ... |
---|
222 | 'KeyPressFcn', [mfilename ' _keypress_'], ... |
---|
223 | 'CloseRequestFcn', [mfilename ' _cancel_'], ... |
---|
224 | 'Tag', mfilename); |
---|
225 | if any(theFigures) |
---|
226 | pos = get(theFigures(1), 'Position'); |
---|
227 | left = pos(1); |
---|
228 | top = pos(2) + pos(4); |
---|
229 | for i = 2:length(theFigures) |
---|
230 | p = get(theFigures(i), 'Position'); |
---|
231 | left = max(pos(1), p(1)); |
---|
232 | top = min(top, p(2) + p(4)); |
---|
233 | end |
---|
234 | thePosition = get(theFigure, 'Position'); |
---|
235 | thePosition(1) = left + 20; |
---|
236 | thePosition(2) = top - thePosition(4) - 20; |
---|
237 | set(theFigure, 'Position', thePosition) |
---|
238 | end |
---|
239 | theFrame = uicontrol( ... |
---|
240 | 'Style', 'frame', ... |
---|
241 | 'Units', 'normalized', ... |
---|
242 | 'Position', [0 0 1 1], ... |
---|
243 | 'BackgroundColor', BABY_BLUE); |
---|
244 | theControls = []; |
---|
245 | theStruct = setinfo(theStruct); % Canonical form. |
---|
246 | theFields = fieldnames(theStruct); |
---|
247 | for i = 1:length(theFields) |
---|
248 | theField = theFields{i}; |
---|
249 | theValue = getfield(theStruct, theField); |
---|
250 | switch class(theValue) |
---|
251 | case 'cell' |
---|
252 | switch class(theValue{1}) |
---|
253 | case 'cell' |
---|
254 | if length(theValue) > 1 |
---|
255 | theSetting = theValue{2}; |
---|
256 | else |
---|
257 | theSetting = 1; |
---|
258 | theValue = {theValue, theSetting}; |
---|
259 | theStruct = setfield(theStruct, theField, theValue); |
---|
260 | end |
---|
261 | theStyle = 'popupmenu'; |
---|
262 | case 'char' |
---|
263 | switch theValue{1} |
---|
264 | case 'checkbox' |
---|
265 | theStyle = 'checkbox'; |
---|
266 | if length(theValue) > 1 |
---|
267 | theSetting = theValue{2}; |
---|
268 | else |
---|
269 | theSetting = 0; |
---|
270 | end |
---|
271 | case 'radiobutton' |
---|
272 | theStyle = 'radiobutton'; |
---|
273 | if length(theValue) > 1 |
---|
274 | theSetting = theValue{2}; |
---|
275 | else |
---|
276 | theSetting = 0; |
---|
277 | end |
---|
278 | otherwise |
---|
279 | error([' ## Incompatible control style: ' theValue{1}]) |
---|
280 | end |
---|
281 | end |
---|
282 | theControls(end+1) = uicontrol( ... |
---|
283 | 'Style', 'text', ... |
---|
284 | 'String', theField); |
---|
285 | theControls(end+1) = uicontrol( ... |
---|
286 | 'Style', theStyle, ... |
---|
287 | 'String', theValue{1}, ... |
---|
288 | 'Value', theSetting); |
---|
289 | case 'char' |
---|
290 | f = findstr(theField, 'help_'); |
---|
291 | if ~any(f) | f(1) ~= 1 |
---|
292 | theControls(end+1) = uicontrol( ... |
---|
293 | 'Style', 'text', ... |
---|
294 | 'String', theField); |
---|
295 | theControls(end+1) = uicontrol( ... |
---|
296 | 'Style', 'edit', ... |
---|
297 | 'Max', 1000, ... |
---|
298 | 'String', ['''' theValue '''']); |
---|
299 | else |
---|
300 | theHintName = [theField ' ' theFigureName]; |
---|
301 | theCallback = ... |
---|
302 | ['hint(get(gcbo, ''UserData''), ''' theHintName ''')']; |
---|
303 | theControls(end+1) = uicontrol( ... |
---|
304 | 'Style', 'text', ... |
---|
305 | 'String', theField); |
---|
306 | theControls(end+1) = uicontrol( ... |
---|
307 | 'Style', 'pushbutton', ... |
---|
308 | 'Callback', theCallback, ... |
---|
309 | 'UserData', theValue, ... |
---|
310 | 'String', 'Help...'); |
---|
311 | end |
---|
312 | case 'double' |
---|
313 | theControls(end+1) = uicontrol( ... |
---|
314 | 'Style', 'text', ... |
---|
315 | 'String', theField); |
---|
316 | theControls(end+1) = uicontrol( ... |
---|
317 | 'Style', 'edit', ... |
---|
318 | 'Max', 1000, ... |
---|
319 | 'String', mat2str(theValue, thePrecision)); |
---|
320 | case 'struct' |
---|
321 | theCallback = ... |
---|
322 | [mfilename '(get(gcbo, ''UserData''), ''' theField ''')']; |
---|
323 | theControls(end+1) = uicontrol( ... |
---|
324 | 'Style', 'text', ... |
---|
325 | 'String', theField); |
---|
326 | theControls(end+1) = uicontrol( ... |
---|
327 | 'Style', 'pushbutton', ... |
---|
328 | 'String', 'More...', ... |
---|
329 | 'Callback', theCallback, ... |
---|
330 | 'UserData', theValue); |
---|
331 | otherwise |
---|
332 | disp(class(theValue)) |
---|
333 | error([' ## Incompatible data type. ' class(theValue)]) |
---|
334 | end |
---|
335 | end |
---|
336 | set(theControls(1:2:end), ... |
---|
337 | 'HorizontalAlignment', 'right', ... |
---|
338 | 'BackgroundColor', BABY_BLUE) |
---|
339 | theControls(end+1) = uicontrol( ... |
---|
340 | 'Style', 'pushbutton', ... |
---|
341 | 'String', 'Cancel', ... |
---|
342 | 'BackgroundColor', [10 2 2]/10, ... |
---|
343 | 'Callback', [mfilename ' _cancel_']); |
---|
344 | theControls(end+1) = uicontrol( ... |
---|
345 | 'Style', 'pushbutton', ... |
---|
346 | 'String', 'Okay', ... |
---|
347 | 'BackgroundColor', [2 10 2]/10, ... |
---|
348 | 'Callback', [mfilename ' _okay_']); |
---|
349 | set(theControls, 'Tag', mfilename) |
---|
350 | theLayout = []; |
---|
351 | for i = 1:length(theControls)/2 |
---|
352 | theLayout = [(1:2:length(theControls)); |
---|
353 | (2:2:length(theControls))].'; |
---|
354 | end |
---|
355 | theLayout = theLayout(:, [1 2 2]); |
---|
356 | uilayout(theControls, theLayout, [1 1 18 18]/20) |
---|
357 | pos = get(0, 'DefaultUIControlPosition'); |
---|
358 | width = pos(3) * 6; |
---|
359 | height = 0.5 * length(theControls) * pos(4) * 20 / 15; |
---|
360 | thePosition = get(theFigure, 'Position'); |
---|
361 | thePosition(2) = thePosition(2) + thePosition(4) - height; |
---|
362 | thePosition(3) = width; |
---|
363 | thePosition(4) = height; |
---|
364 | set(theFigure, 'Position', thePosition, 'Visible', 'on', ... |
---|
365 | 'UserData', theStruct) |
---|
366 | if any(CURRENT_FIGURES) |
---|
367 | CURRENT_FIGURES(~ishandle(CURRENT_FIGURES)) = []; |
---|
368 | end |
---|
369 | CURRENT_FIGURES(end+1) = theFigure; |
---|
370 | |
---|
371 | % Wait here for the new figure to be deleted. By then, it will |
---|
372 | % already have placed its contents in the persistent CURRENT_STRUCT |
---|
373 | % item. |
---|
374 | |
---|
375 | waitfor(theFigure) |
---|
376 | |
---|
377 | % Now get the new info from CURRENT_STRUCT and update. |
---|
378 | |
---|
379 | theNewStruct = CURRENT_STRUCT; |
---|
380 | |
---|
381 | theFieldName = theFigureName; |
---|
382 | |
---|
383 | if length(theFigures) < 1 |
---|
384 | theStruct = theNewStruct; |
---|
385 | else |
---|
386 | theFigure = gcf; |
---|
387 | theStruct = get(theFigure, 'UserData'); |
---|
388 | if ~isfield(theStruct, theFieldName) & ~isequal(theField, 'help') |
---|
389 | disp([' ## No such field: ' theField]) |
---|
390 | elseif ~isempty(theNewStruct) |
---|
391 | theStruct = setfield(theStruct, theFieldName, theNewStruct); |
---|
392 | set(theFigure, 'UserData', theStruct) |
---|
393 | f = findobj(theFigure, 'Type', 'uicontrol', 'Tag', mfilename); |
---|
394 | f = sort(f); |
---|
395 | for i = 2:2:length(f) |
---|
396 | theField = get(f(i-1), 'String'); |
---|
397 | if isequal(theField, theFieldName) |
---|
398 | set(f(i), 'UserData', theNewStruct) |
---|
399 | break |
---|
400 | end |
---|
401 | end |
---|
402 | end |
---|
403 | end |
---|
404 | |
---|
405 | if nargout > 0 |
---|
406 | theResult = theStruct; |
---|
407 | else |
---|
408 | assignin('caller', 'ans', theStruct); |
---|
409 | end |
---|
410 | |
---|
411 | end |
---|
412 | |
---|
413 | % ---------- assign ----------% |
---|
414 | |
---|
415 | function assign(theName, theValue) |
---|
416 | |
---|
417 | % assign -- Assign a value to a name. |
---|
418 | % assign('theName', theValue) assigns theValue |
---|
419 | % to 'theName' in the caller's workspace. It |
---|
420 | % avoids the need to construct an explicit |
---|
421 | % assignment statement to be eval-ed. |
---|
422 | |
---|
423 | % Copyright (C) 1997 Dr. Charles R. Denham, ZYDECO. |
---|
424 | % All Rights Reserved. |
---|
425 | % Disclosure without explicit written consent from the |
---|
426 | % copyright owner does not constitute publication. |
---|
427 | |
---|
428 | % Version of 28-May-1998 00:43:58. |
---|
429 | |
---|
430 | if nargin < 2, help(mfilename), return, end |
---|
431 | |
---|
432 | % The following scheme permits the assignment |
---|
433 | % of items that have complicated subscripts, |
---|
434 | % such as "a{1}(2).b{3}.c = pi". |
---|
435 | |
---|
436 | hasAns = (evalin('caller', 'exist(''ans'', ''var'')') == 1); |
---|
437 | if hasAns |
---|
438 | ans = evalin('caller', 'ans'); % Save. |
---|
439 | end |
---|
440 | assignin('caller', 'ans', theValue) |
---|
441 | evalin('caller', [theName ' = ans;']) |
---|
442 | evalin('caller', 'clear(''ans'')') |
---|
443 | if hasAns |
---|
444 | assignin('caller', 'ans', ans) % Restore. |
---|
445 | end |
---|
446 | |
---|
447 | % ---------- getinfo ----------% |
---|
448 | |
---|
449 | function [theResult, isOkay] = getinfo(theInfo, theField) |
---|
450 | |
---|
451 | % getinfo -- Get field value from an "Info" struct. |
---|
452 | % getinfo(theInfo, 'theField') returns the current |
---|
453 | % value of 'theField' in theInfo, a struct that |
---|
454 | % is compatible with the "uigetinfo" function. |
---|
455 | % Non-existent fields return the empty-matrix. |
---|
456 | % [theResult, isOkay] = ... returns isOkay = 0 |
---|
457 | % if an error occurred; otherwise, non-zero. |
---|
458 | % getinfo(theInfo) returns a struct containing |
---|
459 | % the fields and current selections of theInfo. |
---|
460 | |
---|
461 | % Copyright (C) 1997 Dr. Charles R. Denham, ZYDECO. |
---|
462 | % All Rights Reserved. |
---|
463 | % Disclosure without explicit written consent from the |
---|
464 | % copyright owner does not constitute publication. |
---|
465 | |
---|
466 | % Version of 07-Feb-1998 09:45:56. |
---|
467 | % Updated 14-Nov-2001 15:07:51. |
---|
468 | |
---|
469 | if nargout > 0, theResult = []; end |
---|
470 | if nargin < 1, help(mfilename), return, end |
---|
471 | |
---|
472 | % Get current selections, recursively if needed. |
---|
473 | |
---|
474 | if nargin < 2 |
---|
475 | result = theInfo; |
---|
476 | theFields = fieldnames(result); |
---|
477 | isOkay = 1; |
---|
478 | for i = 1:length(theFields) |
---|
479 | [theValue, okay] = getinfo(theInfo, theFields{i}); |
---|
480 | isOkay = isOkay & okay; |
---|
481 | switch class(theValue) |
---|
482 | case 'struct' |
---|
483 | [res, okay] = getinfo(theValue); |
---|
484 | isOkay = isOkay & okay; |
---|
485 | result = setfield(result, theFields{i}, res); |
---|
486 | otherwise |
---|
487 | result = setfield(result, theFields{i}, theValue); |
---|
488 | end |
---|
489 | end |
---|
490 | if nargout > 0 |
---|
491 | theResult = result; |
---|
492 | else |
---|
493 | disp(result) |
---|
494 | end |
---|
495 | return |
---|
496 | end |
---|
497 | |
---|
498 | % Note: Matlab 6+ does not allow "getfield(a, 'b.c')", |
---|
499 | % unlike previous versions. We need to parse the |
---|
500 | % 'b.c' ourselves, then call "getfield(a, 'b', 'c')". |
---|
501 | |
---|
502 | if ischar(theField) & any(theField == '.') |
---|
503 | theField = [theField '.']; |
---|
504 | f = find(theField == '.'); |
---|
505 | theParts = cell(1, length(f)); |
---|
506 | k = 0; |
---|
507 | for i = 1:length(f) |
---|
508 | theParts{i} = theField(k+1:f(i)-1); |
---|
509 | k = f(i); |
---|
510 | end |
---|
511 | theField = theParts; |
---|
512 | elseif ~iscell(theField) |
---|
513 | theField = {theField}; |
---|
514 | end |
---|
515 | |
---|
516 | theValue = []; |
---|
517 | |
---|
518 | isOkay = 1; |
---|
519 | % eval('theValue = getfield(theInfo, theField);', 'isOkay = 0;'); |
---|
520 | eval('theValue = getfield(theInfo, theField{:});', 'isOkay = 0;'); |
---|
521 | |
---|
522 | result = theValue; |
---|
523 | |
---|
524 | if all(isOkay) |
---|
525 | switch class(theValue) |
---|
526 | case 'cell' |
---|
527 | if isequal(theValue{1}, 'checkbox') | ... |
---|
528 | isequal(theValue{1}, 'radiobutton') |
---|
529 | if length(theValue) < 2, theValue{2} = 0; end |
---|
530 | result = theValue{2}; |
---|
531 | else |
---|
532 | if ~iscell(theValue{1}), theValue = {theValue{1}}; end |
---|
533 | if length(theValue) < 2, theValue{2} = 1; end |
---|
534 | result = theValue{1}{theValue{2}}; |
---|
535 | end |
---|
536 | otherwise |
---|
537 | result = theValue; |
---|
538 | end |
---|
539 | end |
---|
540 | |
---|
541 | if nargout > 0 |
---|
542 | theResult = result; |
---|
543 | else |
---|
544 | disp(result) |
---|
545 | end |
---|
546 | |
---|
547 | % ---------- setinfo ----------% |
---|
548 | |
---|
549 | function [theResult, isOkay] = setinfo(theInfo, theField, theValue) |
---|
550 | |
---|
551 | % setinfo -- Set field value in an "Info" struct. |
---|
552 | % setinfo(theInfo, 'theField', theValue) updates |
---|
553 | % 'theField' to theValue in theInfo, a struct |
---|
554 | % that is compatible with the "uigetinfo" function. |
---|
555 | % If 'theField' does not exist, it will be created |
---|
556 | % to receive theValue. |
---|
557 | % [theResult, isOkay] = ... returns isOkay = 0 |
---|
558 | % if an error occurred; otherwise, non-zero. |
---|
559 | % setinfo(theInfo, 'theField') invokes "getinfo". |
---|
560 | % setinfo(theInfo) adjusts theInfo to canonical |
---|
561 | % form. |
---|
562 | |
---|
563 | % Copyright (C) 1997 Dr. Charles R. Denham, ZYDECO. |
---|
564 | % All Rights Reserved. |
---|
565 | % Disclosure without explicit written consent from the |
---|
566 | % copyright owner does not constitute publication. |
---|
567 | |
---|
568 | % Version of 07-Feb-1998 09:45:56. |
---|
569 | % Updated 14-Nov-2001 15:21:24. |
---|
570 | |
---|
571 | if nargout > 0, theResult = []; end |
---|
572 | if nargin < 1, help(mfilename), return, end |
---|
573 | |
---|
574 | % Put all fields into canonical form. |
---|
575 | |
---|
576 | if nargin < 2 |
---|
577 | result = theInfo; |
---|
578 | theFields = fieldnames(result); |
---|
579 | isOkay = 1; |
---|
580 | for i = 1:length(theFields) |
---|
581 | theValue = getfield(result, theFields{i}); |
---|
582 | switch class(theValue) |
---|
583 | case 'struct' |
---|
584 | [res, okay] = setinfo(theValue); |
---|
585 | isOkay = isOkay & okay; |
---|
586 | result = setfield(result, theFields{i}, res); |
---|
587 | case 'cell' |
---|
588 | if length(theValue) == 1 & ... |
---|
589 | (isequal(theValue{1}, 'radiobutton') | ... |
---|
590 | isequal(theValue{1}, 'checkbox')) |
---|
591 | theValue{2} = 0; |
---|
592 | result = setfield(result, theFields{i}, theValue); |
---|
593 | elseif length(theValue) == 1 & iscell(theValue{1}) |
---|
594 | theValue{2} = 1; |
---|
595 | result = setfield(result, theFields{i}, theValue); |
---|
596 | elseif ~isequal(theValue{1}, 'radiobutton') & ... |
---|
597 | ~isequal(theValue{1}, 'checkbox') |
---|
598 | theValue{1} = {theValue{1}}; |
---|
599 | theValue{2} = 1; |
---|
600 | else |
---|
601 | theValue; |
---|
602 | end |
---|
603 | otherwise |
---|
604 | end |
---|
605 | end |
---|
606 | if nargout > 0, theResult = result; end |
---|
607 | return |
---|
608 | end |
---|
609 | |
---|
610 | [theVal, isOkay] = getinfo(theInfo, theField); |
---|
611 | |
---|
612 | if nargin == 2 |
---|
613 | if nargout > 0 |
---|
614 | theResult = theVal; |
---|
615 | else |
---|
616 | disp(theVal) |
---|
617 | end |
---|
618 | return |
---|
619 | end |
---|
620 | |
---|
621 | if ischar(theField) & any(theField == '.') |
---|
622 | theField = [theField '.']; |
---|
623 | f = find(theField == '.'); |
---|
624 | theParts = cell(1, length(f)); |
---|
625 | k = 0; |
---|
626 | for i = 1:length(f) |
---|
627 | theParts{i} = theField(k+1:f(i)-1); |
---|
628 | k = f(i); |
---|
629 | end |
---|
630 | theField = theParts; |
---|
631 | elseif ~iscell(theField) |
---|
632 | theField = {theField}; |
---|
633 | end |
---|
634 | |
---|
635 | result = theInfo; |
---|
636 | |
---|
637 | if ~all(isOkay) % Create a new field. |
---|
638 | isOkay = 1; |
---|
639 | % eval('result = setfield(theInfo, theField, theValue);', 'isOkay = 0;'); |
---|
640 | eval('result = setfield(theInfo, theField{:}, theValue);', 'isOkay = 0;'); |
---|
641 | else % Update an existing field. |
---|
642 | isokay = 1; |
---|
643 | % eval('theVal = getfield(theInfo, theField);', 'isOkay = 0;'); |
---|
644 | eval('theVal = getfield(theInfo, theField{:});', 'isOkay = 0;'); |
---|
645 | if ~isOkay, theVal = []; end |
---|
646 | switch class(theVal) |
---|
647 | case 'cell' |
---|
648 | if isequal(theVal{1}, 'checkbox') | isequal(theVal{1}, 'radiobutton') |
---|
649 | % Do nothing. |
---|
650 | elseif ~iscell(theVal{1}) |
---|
651 | theVal{1} = {theVal{1}}; |
---|
652 | theVal{2} = 1; |
---|
653 | end |
---|
654 | end |
---|
655 | switch class(theVal) |
---|
656 | case 'cell' |
---|
657 | if isequal(theVal{1}, 'checkbox') | isequal(theVal{1}, 'radiobutton') |
---|
658 | theVal{2} = any(any(theValue)); |
---|
659 | else |
---|
660 | switch class(theValue) |
---|
661 | case 'double' |
---|
662 | if theValue > 0 & theValue <= length(theVal{1}) |
---|
663 | theVal{2} = theValue; |
---|
664 | end |
---|
665 | otherwise |
---|
666 | flag = 0; |
---|
667 | for i = 1:length(theVal{1}) |
---|
668 | if isequal(theVal{1}{i}, theValue) |
---|
669 | theVal{2} = i; |
---|
670 | flag = 1 |
---|
671 | end |
---|
672 | end |
---|
673 | if ~any(flag) % Append. |
---|
674 | theVal{1} = [theVal(:); {theValue}]; |
---|
675 | theVal{2} = length(theVal{1}); |
---|
676 | end |
---|
677 | end |
---|
678 | % else |
---|
679 | % theVal{1} = [{theValue}; theVal(:)]; |
---|
680 | end |
---|
681 | otherwise |
---|
682 | theVal = theValue; |
---|
683 | end |
---|
684 | isOkay = 1; |
---|
685 | % eval('result = setfield(theInfo, theField, theVal);', 'isOkay = 0;'); |
---|
686 | eval('result = setfield(theInfo, theField{:}, theVal);', 'isOkay = 0;'); |
---|
687 | end |
---|
688 | |
---|
689 | if nargout > 0 |
---|
690 | theResult = result; |
---|
691 | else |
---|
692 | disp(result) |
---|
693 | end |
---|
694 | |
---|
695 | % ---------- uilayout ----------% |
---|
696 | |
---|
697 | function theResult = uilayout(theControls, theLayout, thePosition) |
---|
698 | |
---|
699 | % uilayout -- Layout for ui controls. |
---|
700 | % uilayout(theControls, theLayout) positions theControls |
---|
701 | % according to theLayout, an array whose entries, taken |
---|
702 | % in sorted order, define the rectangular extents occupied |
---|
703 | % by each control. TheLayout defaults to a simple vertical |
---|
704 | % arrangement of theControls. A one-percent margin is |
---|
705 | % imposed between controls. To define a layout region |
---|
706 | % containing no control, use Inf. |
---|
707 | % uilayout(..., thePosition) confines the controls to the |
---|
708 | % given normalized position of the figure. This syntax |
---|
709 | % is useful for embedding controls within a frame. |
---|
710 | % uilayout (no argument) demonstrates itself. |
---|
711 | |
---|
712 | % Copyright (C) 1997 Dr. Charles R. Denham, ZYDECO. |
---|
713 | % All Rights Reserved. |
---|
714 | % Disclosure without explicit written consent from the |
---|
715 | % copyright owner does not constitute publication. |
---|
716 | |
---|
717 | % Version of 18-Apr-1997 08:07:54. |
---|
718 | % Updated 27-Dec-1999 06:03:57. |
---|
719 | |
---|
720 | if nargin < 1, theControls = 'demo'; help(mfilename), end |
---|
721 | |
---|
722 | if strcmp(theControls, 'demo') |
---|
723 | theLayout = [1 2; |
---|
724 | 3 4; |
---|
725 | 5 Inf; |
---|
726 | 5 6; |
---|
727 | 5 Inf; |
---|
728 | 7 8; |
---|
729 | 9 10; |
---|
730 | 11 12; |
---|
731 | 13 14]; |
---|
732 | [m, n] = size(theLayout); |
---|
733 | thePos = get(0, 'DefaultUIControlPosition'); |
---|
734 | theSize = [n+2 m+2] .* thePos(3:4); |
---|
735 | theFigure = figure('Name', 'UILayout', ... |
---|
736 | 'NumberTitle', 'off', ... |
---|
737 | 'Resize', 'off', ... |
---|
738 | 'Units', 'pixels'); |
---|
739 | thePos = get(theFigure, 'Position'); |
---|
740 | theTop = thePos(2) + thePos(4); |
---|
741 | thePos = thePos .* [1 1 0 0] + [0 0 theSize]; |
---|
742 | thePos(2) = theTop - (thePos(2) + thePos(4)); |
---|
743 | set(theFigure, 'Position', thePos); |
---|
744 | theFrame = uicontrol('Style', 'frame', ... |
---|
745 | 'Units', 'normalized', ... |
---|
746 | 'Position', [0 0 1 1], ... |
---|
747 | 'BackgroundColor', [0.5 1 1]); |
---|
748 | theStyles = {'checkbox'; 'text'; ... |
---|
749 | 'edit'; 'text'; ... |
---|
750 | 'listbox'; 'text'; ... |
---|
751 | 'popupmenu'; 'text'; ... |
---|
752 | 'pushbutton'; 'text'; ... |
---|
753 | 'radiobutton'; 'text'; ... |
---|
754 | 'text'; 'text'}; |
---|
755 | theStrings = {'Anchovies?', '<-- CheckBox --', ... |
---|
756 | 'Hello World!', '<-- Edit --', ... |
---|
757 | {'Now', 'Is', 'The' 'Time' 'For' 'All' 'Good', ... |
---|
758 | 'Men', 'To', 'Come' 'To' 'The' 'Aid' 'Of', ... |
---|
759 | 'Their' 'Country'}, ... |
---|
760 | '<-- ListBox --', ... |
---|
761 | {'Cheetah', 'Leopard', 'Lion', 'Tiger', 'Wildcat'}, ... |
---|
762 | '<-- PopupMenu --', ... |
---|
763 | 'Okay', '<-- PushButton --', ... |
---|
764 | 'Cream?', '<-- RadioButton --', ... |
---|
765 | 'UILayout', '<-- Text --'}; |
---|
766 | theControls = zeros(size(theStyles)); |
---|
767 | for i = 1:length(theStyles) |
---|
768 | theControls(i) = uicontrol('Style', theStyles{i}, ... |
---|
769 | 'String', theStrings{i}, ... |
---|
770 | 'Callback', ... |
---|
771 | 'disp(int2str(get(gcbo, ''Value'')))'); |
---|
772 | end |
---|
773 | set(theControls(1:2:length(theControls)), 'BackGroundColor', [1 1 0.5]) |
---|
774 | set(theControls(2:2:length(theControls)), 'BackGroundColor', [0.5 1 1]) |
---|
775 | thePosition = [1 1 98 98] ./ 100; |
---|
776 | uilayout(theControls, theLayout, thePosition) |
---|
777 | set(theFrame, 'UserData', theControls) |
---|
778 | theStyles, theLayout, thePosition |
---|
779 | if nargout > 0, theResult = theFrame; end |
---|
780 | return |
---|
781 | end |
---|
782 | |
---|
783 | if nargin < 2, theLayout = (1:length(theControls)).'; end |
---|
784 | if nargin < 3, thePosition = [0 0 1 1]; end |
---|
785 | |
---|
786 | a = theLayout(:); |
---|
787 | a = a(finite(a)); |
---|
788 | a = sort(a); |
---|
789 | a(diff(a) == 0) = []; |
---|
790 | |
---|
791 | b = zeros(size(theLayout)); |
---|
792 | |
---|
793 | for k = 1:length(a) |
---|
794 | b(theLayout == a(k)) = k; |
---|
795 | end |
---|
796 | |
---|
797 | [m, n] = size(theLayout); |
---|
798 | |
---|
799 | set(theControls, 'Units', 'Normalized') |
---|
800 | theMargin = [1 1 -2 -2] ./ 100; |
---|
801 | for k = 1:min(length(theControls), length(a)) |
---|
802 | [i, j] = find(b == k); |
---|
803 | xmin = (min(j) - 1) ./ n; |
---|
804 | xmax = max(j) ./ n; |
---|
805 | ymin = 1 - max(i) ./ m; |
---|
806 | ymax = 1 - (min(i) - 1) ./ m; |
---|
807 | thePos = [xmin ymin (xmax-xmin) (ymax-ymin)] + theMargin; |
---|
808 | thePos = thePos .* thePosition([3 4 3 4]); |
---|
809 | thePos(1:2) = thePos(1:2) + thePosition(1:2); |
---|
810 | set(theControls(k), 'Position', thePos); |
---|
811 | end |
---|
812 | |
---|
813 | if nargout > 0, theResult = theControls; end |
---|
814 | |
---|
815 | % ---------- hint ----------% |
---|
816 | |
---|
817 | function theResult = hint(theText, theFigureName) |
---|
818 | |
---|
819 | % hint -- Post a message. |
---|
820 | % hint('theText', 'theFigureName') posts 'theText' in the |
---|
821 | % figure named 'theFigureName', which will be created if |
---|
822 | % it does not already exist. The text can be a string |
---|
823 | % separated by newlines, or a cell of strings. |
---|
824 | % hint('demo') demonstrates itself. |
---|
825 | |
---|
826 | % Copyright (C) 1999 Dr. Charles R. Denham, ZYDECO. |
---|
827 | % All Rights Reserved. |
---|
828 | % Disclosure without explicit written consent from the |
---|
829 | % copyright owner does not constitute publication. |
---|
830 | |
---|
831 | % Version of 17-Dec-1999 11:31:03. |
---|
832 | % Updated 04-Jan-2000 13:40:41. |
---|
833 | |
---|
834 | if nargin < 1, theText = 'demo'; end |
---|
835 | |
---|
836 | if isequal(theText, 'demo') |
---|
837 | hint(help(mfilename), 'Hint Hint') |
---|
838 | return |
---|
839 | end |
---|
840 | |
---|
841 | CR = char(13); |
---|
842 | LF = char(10); |
---|
843 | CRLF = [CR LF]; |
---|
844 | |
---|
845 | if nargout > 0, theResult = []; end |
---|
846 | if nargin < 1 |
---|
847 | help(mfilename) |
---|
848 | theText = help(mfilename); |
---|
849 | for i = 1:3 |
---|
850 | theText = [theText theText]; |
---|
851 | end |
---|
852 | end |
---|
853 | if nargin < 2, theFigureName = 'Help'; end |
---|
854 | |
---|
855 | if min(size(theText)) == 1 |
---|
856 | theText = theText(:).'; |
---|
857 | end |
---|
858 | |
---|
859 | if ischar(theText) & size(theText, 1) == 1 |
---|
860 | theText = strrep(theText, CRLF, CR); |
---|
861 | theText = strrep(theText, LF, CR); |
---|
862 | if theText(end) ~= CR, theText(end+1) = CR; end |
---|
863 | if theText(1) ~= CR, theText = [CR theText]; end |
---|
864 | f = find(theText == CR); |
---|
865 | if any(f) |
---|
866 | s = cell(length(f)-1, 1); |
---|
867 | for i = 1:length(f)-1 |
---|
868 | if f(i)+1 < f(i+1)-1 |
---|
869 | s{i} = theText(f(i)+1:f(i+1)-1); |
---|
870 | else |
---|
871 | s{i} = ' '; |
---|
872 | end |
---|
873 | end |
---|
874 | theText = s; |
---|
875 | end |
---|
876 | end |
---|
877 | |
---|
878 | theLineCount = size(theText, 1); |
---|
879 | |
---|
880 | theFigure = findobj( ... |
---|
881 | 'Type', 'figure', ... |
---|
882 | 'Name', theFigureName, ... |
---|
883 | 'Tag', [mfilename ' hint'] ... |
---|
884 | ); |
---|
885 | if isempty(theFigure) |
---|
886 | theFigures = findobj('Type', 'figure'); |
---|
887 | if any(theFigures) |
---|
888 | thePosition = get(gcf, 'Position'); |
---|
889 | left = thePosition(1); |
---|
890 | top = thePosition(2) + thePosition(4); |
---|
891 | end |
---|
892 | theFigure = figure( ... |
---|
893 | 'Name', theFigureName, ... |
---|
894 | 'Tag', mfilename, ... |
---|
895 | 'Visible', 'off' ... |
---|
896 | ); |
---|
897 | if any(theFigures) |
---|
898 | set(theFigure, 'Position', thePosition + [20 -20 0 0]) |
---|
899 | end |
---|
900 | end |
---|
901 | |
---|
902 | delete(get(theFigure, 'Children')) |
---|
903 | |
---|
904 | theColor = [9 9 9]/10; |
---|
905 | theFontName = 'Courier'; |
---|
906 | if any(findstr(lower(computer), 'mac')) |
---|
907 | theFontName = 'Monaco'; |
---|
908 | end |
---|
909 | theFontSize = 12; |
---|
910 | theListBox = uicontrol( ... |
---|
911 | theFigure, ... |
---|
912 | 'Style', 'listbox', ... |
---|
913 | 'String', theText, ... |
---|
914 | 'FontName', theFontName, ... |
---|
915 | 'FontSize', theFontSize, ... |
---|
916 | 'HorizontalAlignment', 'left', ... |
---|
917 | 'BackgroundColor', theColor ... |
---|
918 | ); |
---|
919 | |
---|
920 | uilayout(theListBox, 1) |
---|
921 | |
---|
922 | set(theFigure, 'Visible', 'on') |
---|
923 | figure(theFigure) |
---|
924 | |
---|
925 | if nargout > 0 |
---|
926 | theResult = theFigure; |
---|
927 | end |
---|