spm_input.m 88 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387
  1. function varargout = spm_input(varargin)
  2. % Comprehensive graphical and command line input function
  3. % FORMATs (given in Programmers Help)
  4. %_______________________________________________________________________
  5. %
  6. % spm_input handles most forms of interactive user input for SPM.
  7. % (File selection is handled by spm_select.m)
  8. %
  9. % There are five types of input: String, Evaluated, Conditions, Buttons
  10. % and Menus: These prompt for string input; string input which is
  11. % evaluated to give a numerical result; selection of one item from a
  12. % set of buttons; selection of an item from a menu.
  13. %
  14. % - STRING, EVALUATED & CONDITION input -
  15. % For STRING, EVALUATED and CONDITION input types, a prompt is
  16. % displayed adjacent to an editable text entry widget (with a lilac
  17. % background!). Clicking in the entry widget allows editing, pressing
  18. % <RETURN> or <ENTER> enters the result. You must enter something,
  19. % empty answers are not accepted. A default response may be pre-specified
  20. % in the entry widget, which will then be outlined. Clicking the border
  21. % accepts the default value.
  22. %
  23. % Basic editing of the entry widget is supported *without* clicking in
  24. % the widget, provided no other graphics widget has the focus. (If a
  25. % widget has the focus, it is shown highlighted with a thin coloured
  26. % line. Clicking on the window background returns the focus to the
  27. % window, enabling keyboard accelerators.). This enables you to type
  28. % responses to a sequence of questions without having to repeatedly
  29. % click the mouse in the text widgets. Supported are BackSpace and
  30. % Delete, line kill (^U). Other standard ASCII characters are appended
  31. % to the text in the entry widget. Press <RETURN> or <ENTER> to submit
  32. % your response.
  33. %
  34. % A ContextMenu is provided (in the figure background) giving access to
  35. % relevant utilities including the facility to load input from a file
  36. % (see spm_load.m and examples given below): Click the right button on
  37. % the figure background.
  38. %
  39. % For EVALUATED input, the string submitted is evaluated in the base
  40. % MatLab workspace (see MatLab's `eval` command) to give a numerical
  41. % value. This permits the entry of numerics, matrices, expressions,
  42. % functions or workspace variables. I.e.:
  43. % i) - a number, vector or matrix e.g. "[1 2 3 4]"
  44. % "[1:4]"
  45. % "1:4"
  46. % ii) - an expression e.g. "pi^2"
  47. % "exp(-[1:36]/5.321)"
  48. % iii) - a function (that will be invoked) e.g. "spm_load('tmp.dat')"
  49. % (function must be on MATLABPATH) "input_cov(36,5.321)"
  50. % iv) - a variable from the base workspace
  51. % e.g. "tmp"
  52. %
  53. % The last three options provide a great deal of power: spm_load will
  54. % load a matrix from an ASCII data file and return the results. When
  55. % called without an argument, spm_load will pop up a file selection
  56. % dialog. Alternatively, this facility can be gained from the
  57. % ContextMenu. The second example assummes a custom funcion called
  58. % input_cov has been written which expects two arguments, for example
  59. % the following file saved as input_cov.m somewhere on the MATLABPATH
  60. % (~/matlab, the matlab subdirectory of your home area, and the current
  61. % directory, are on the MATLABPATH by default):
  62. %
  63. % function [x] = input_cov(n,decay)
  64. % % data input routine - mono-exponential covariate
  65. % % FORMAT [x] = input_cov(n,decay)
  66. % % n - number of time points
  67. % % decay - decay constant
  68. % x = exp(-[1:n]/decay);
  69. %
  70. % Although this example is trivial, specifying large vectors of
  71. % empirical data (e.g. reaction times for 72 scans) is efficient and
  72. % reliable using this device. In the last option, a variable called tmp
  73. % is picked up from the base workspace. To use this method, set the
  74. % variables in the MatLab base workspace before starting an SPM
  75. % procedure (but after starting the SPM interface). E.g.
  76. % >> tmp=exp(-[1:36]/5.321)
  77. %
  78. % Occasionally a vector of a specific length will be required: This
  79. % will be indicated in the prompt, which will start with "[#]", where
  80. % # is the length of vector(s) required. (If a matrix is entered then
  81. % at least one dimension should equal #.)
  82. %
  83. % Occasionally a specific type of number will be required. This should
  84. % be obvious from the context. If you enter a number of the wrong type,
  85. % you'll be alerted and asked to re-specify. The types are i) Real
  86. % numbers; ii) Integers; iii) Whole numbers [0,1,2,3,...] & iv) Natural
  87. % numbers [1,2,3,...]
  88. %
  89. % CONDITIONS type input is for getting indicator vectors. The features
  90. % of evaluated input described above are complimented as follows:
  91. % v) - a compressed list of digits 0-9 e.g. "12121212"
  92. % ii) - a list of indicator characters e.g. "abababab"
  93. % a-z mapped to 1-26 in alphabetical order, *except* r ("rest")
  94. % which is mapped to zero (case insensitive, [A:Z,a:z] only)
  95. % ...in addition the response is checked to ensure integer condition indices.
  96. % Occasionally a specific number of conditions will be required: This
  97. % will be indicated in the prompt, which will end with (#), where # is
  98. % the number of conditions required.
  99. %
  100. % CONTRAST type input is for getting contrast weight vectors. Enter
  101. % contrasts as row-vectors. Contrast weight vectors will be padded with
  102. % zeros to the correct length, and checked for validity. (Valid
  103. % contrasts are estimable, which are those whose weights vector is in
  104. % the row-space of the design matrix.)
  105. %
  106. % Errors in string evaluation for EVALUATED & CONDITION types are
  107. % handled gracefully, the user notified, and prompted to re-enter.
  108. %
  109. % - BUTTON input -
  110. % For Button input, the prompt is displayed adjacent to a small row of
  111. % buttons. Press the approprate button. The default button (if
  112. % available) has a dark outline. Keyboard accelerators are available
  113. % (provided no graphics widget has the focus): <RETURN> or <ENTER>
  114. % selects the default button (if available). Typing the first character
  115. % of the button label (case insensitive) "presses" that button. (If
  116. % these Keys are not unique, then the integer keys 1,2,... "press" the
  117. % appropriate button.)
  118. %
  119. % The CommandLine variant presents a simple menu of buttons and prompts
  120. % for a selection. Any default response is indicated, and accepted if
  121. % an empty line is input.
  122. %
  123. %
  124. % - MENU input -
  125. % For Menu input, the prompt is displayed in a pull down menu widget.
  126. % Using the mouse, a selection is made by pulling down the widget and
  127. % releasing the mouse on the appropriate response. The default response
  128. % (if set) is marked with an asterisk. Keyboard accelerators are
  129. % available (provided no graphic widget has the focus) as follows: 'f',
  130. % 'n' or 'd' move forward to next response down; 'b', 'p' or 'u' move
  131. % backwards to the previous response up the list; the number keys jump
  132. % to the appropriate response number; <RETURN> or <ENTER> slelects the
  133. % currently displayed response. If a default is available, then
  134. % pressing <RETURN> or <ENTER> when the prompt is displayed jumps to
  135. % the default response.
  136. %
  137. % The CommandLine variant presents a simple menu and prompts for a selection.
  138. % Any default response is indicated, and accepted if an empty line is
  139. % input.
  140. %
  141. %
  142. % - Combination BUTTON/EDIT input -
  143. % In this usage, you will be presented with a set of buttons and an
  144. % editable text widget. Click one of the buttons to choose that option,
  145. % or type your response in the edit widget. Any default response will
  146. % be shown in the edit widget. The edit widget behaves in the same way
  147. % as with the STRING/EVALUATED input, and expects a single number.
  148. % Keypresses edit the text widget (rather than "press" the buttons)
  149. % (provided no other graphics widget has the focus). A default response
  150. % can be selected with the mouse by clicking the thick border of the
  151. % edit widget.
  152. %
  153. %
  154. % - Command line -
  155. % If YPos is 0 or global CMDLINE is true, then the command line is used.
  156. % Negative YPos overrides CMDLINE, ensuring the GUI is used, at
  157. % YPos=abs(YPos). Similarly relative YPos beginning with '!'
  158. % (E.g.YPos='!+1') ensures the GUI is used.
  159. %
  160. % spm_input uses the SPM 'Interactive' window, which is 'Tag'ged
  161. % 'Interactive'. If there is no such window, then the current figure is
  162. % used, or an 'Interactive' window created if no windows are open.
  163. %
  164. %-----------------------------------------------------------------------
  165. % Programers help is contained in the main body of spm_input.m
  166. %-----------------------------------------------------------------------
  167. % See : input.m (MatLab Reference Guide)
  168. % See also : spm_select.m (SPM file selector dialog)
  169. % : spm_input.m (Input wrapper function - handles batch mode)
  170. %_______________________________________________________________________
  171. % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
  172. % Andrew Holmes
  173. % $Id: spm_input.m 6510 2015-07-31 14:49:33Z guillaume $
  174. %=======================================================================
  175. % - FORMAT specifications for programers
  176. %=======================================================================
  177. % generic - [p,YPos] = spm_input(Prompt,YPos,Type,...)
  178. % string - [p,YPos] = spm_input(Prompt,YPos,'s',DefStr)
  179. % string+ - [p,YPos] = spm_input(Prompt,YPos,'s+',DefStr)
  180. % evaluated - [p,YPos] = spm_input(Prompt,YPos,'e',DefStr,n)
  181. % - natural - [p,YPos] = spm_input(Prompt,YPos,'n',DefStr,n,mx)
  182. % - whole - [p,YPos] = spm_input(Prompt,YPos,'w',DefStr,n,mx)
  183. % - integer - [p,YPos] = spm_input(Prompt,YPos,'i',DefStr,n)
  184. % - real - [p,YPos] = spm_input(Prompt,YPos,'r',DefStr,n,mm)
  185. % condition - [p,YPos] = spm_input(Prompt,YPos,'c',DefStr,n,m)
  186. % contrast - [p,YPos] = spm_input(Prompt,YPos,'x',DefStr,n,X)
  187. % permutation- [p,YPos] = spm_input(Prompt,YPos,'p',DefStr,P,n)
  188. % button - [p,YPos] = spm_input(Prompt,YPos,'b',Labels,Values,DefItem)
  189. % button/edit combo's (edit for string or typed scalar evaluated input)
  190. % [p,YPos] = spm_input(Prompt,YPos,'b?1',Labels,Values,DefStr,mx)
  191. % ...where ? in b?1 specifies edit widget type as with string & eval'd input
  192. % - [p,YPos] = spm_input(Prompt,YPos,'n1',DefStr,mx)
  193. % - [p,YPos] = spm_input(Prompt,YPos,'w1',DefStr,mx)
  194. % button dialog
  195. % - [p,YPos] = spm_input(Prompt,YPos,'bd',...
  196. % Labels,Values,DefItem,Title)
  197. % menu - [p,YPos] = spm_input(Prompt,YPos,'m',Labels,Values,DefItem)
  198. % display - spm_input(Message,YPos,'d',Label)
  199. % display - (GUI only) spm_input(Alert,YPos,'d!',Label)
  200. %
  201. % yes/no - [p,YPos] = spm_input(Prompt,YPos,'y/n',Values,DefItem)
  202. % buttons (shortcut) where Labels is a bar delimited string
  203. % - [p,YPos] = spm_input(Prompt,YPos,Labels,Values,DefItem)
  204. %
  205. % NB: Natural numbers are [1:Inf), Whole numbers are [0:Inf)
  206. %
  207. % -- Parameters (input) --
  208. %
  209. % Prompt - prompt string
  210. % - Defaults (missing or empty) to 'Enter an expression'
  211. %
  212. % YPos - (numeric) vertical position {1 - 12}
  213. % - overriden by global CMDLINE
  214. % - 0 for command line
  215. % - negative to force GUI
  216. % - (string) relative vertical position E.g. '+1'
  217. % - relative to last position used
  218. % - overriden by global CMDLINE
  219. % - YPos(1)=='!' forces GUI E.g. '!+1'
  220. % - '_' is a shortcut for the lowest GUI position
  221. % - Defaults (missing or empty) to '+1'
  222. %
  223. % Type - type of interrogation
  224. % - 's'tring
  225. % - 's+' multi-line string
  226. % - p returned as cellstr (nx1 cell array of strings)
  227. % - DefStr can be a cellstr or string matrix
  228. % - 'e'valuated string
  229. % - 'n'atural numbers
  230. % - 'w'hole numbers
  231. % - 'i'ntegers
  232. % - 'r'eals
  233. % - 'c'ondition indicator vector
  234. % - 'x' - contrast entry
  235. % - If n(2) or design matrix X is specified, then
  236. % contrast matrices are padded with zeros to have
  237. % correct length.
  238. % - if design matrix X is specified, then contrasts are
  239. % checked for validity (i.e. in the row-space of X)
  240. % (checking handled by spm_SpUtil)
  241. % - 'b'uttons
  242. % - 'bd' - button dialog: Uses MatLab's questdlg
  243. % - For up to three buttons
  244. % - Prompt can be a cellstr with a long multiline message
  245. % - CmdLine support as with 'b' type
  246. % - button/edit combo's: 'be1','bn1','bw1','bi1','br1'
  247. % - second letter of b?1 specifies type for edit widget
  248. % - 'n1' - single natural number (buttons 1,2,... & edit)
  249. % - 'w1' - single whole number (buttons 0,1,... & edit)
  250. % - 'm'enu pulldown
  251. % - 'y/n' : Yes or No buttons
  252. % (See shortcuts below)
  253. % - bar delimited string : buttons with these labels
  254. % (See shortcuts below)
  255. % - Defaults (missing or empty) to 'e'
  256. %
  257. % DefStr - Default string to be placed in entry widget for string and
  258. % evaluated types
  259. % - Defaults to ''
  260. %
  261. % n ('e', 'c' & 'p' types)
  262. % - Size of matrix requred
  263. % - NaN for 'e' type implies no checking - returns input as evaluated
  264. % - length of n(:) specifies dimension - elements specify size
  265. % - Inf implies no restriction
  266. % - Scalar n expanded to [n,1] (i.e. a column vector)
  267. % (except 'x' contrast type when it's [n,np] for np
  268. % - E.g: [n,1] & [1,n] (scalar n) prompt for an n-vector,
  269. % returned as column or row vector respectively
  270. % [1,Inf] & [Inf,1] prompt for a single vector,
  271. % returned as column or row vector respectively
  272. % [n,Inf] & [Inf,n] prompts for any number of n-vectors,
  273. % returned with row/column dimension n respectively.
  274. % [a,b] prompts for an 2D matrix with row dimension a and
  275. % column dimension b
  276. % [a,Inf,b] prompt for a 3D matrix with row dimension a,
  277. % page dimension b, and any column dimension.
  278. % - 'c' type can only deal with single vectors
  279. % - NaN for 'c' type treated as Inf
  280. % - Defaults (missing or empty) to NaN
  281. %
  282. % n ('x'type)
  283. % - Number of contrasts required by 'x' type (n(1))
  284. % ( n(2) can be used specify length of contrast vectors if )
  285. % ( a design matrix isn't passed )
  286. % - Defaults (missing or empty) to 1 - vector contrast
  287. %
  288. % mx ('n', 'w', 'n1', 'w1', 'bn1' & 'bw1' types)
  289. % - Maximum value (inclusive)
  290. %
  291. % mm ('r' type)
  292. % - Maximum and minimum values (inclusive)
  293. %
  294. % m - Number of unique conditions required by 'c' type
  295. % - Inf implies no restriction
  296. % - Defaults (missing or empty) to Inf - no restriction
  297. %
  298. % P - set (vector) of numbers of which a permutation is required
  299. %
  300. % X - Design matrix for contrast checking in 'x' type
  301. % - Can be either a straight matrix or a space structure (see spm_sp)
  302. % - Column dimension of design matrix specifies length of contrast
  303. % vectors (overriding n(2) is specified).
  304. %
  305. % Title - Title for questdlg in 'bd' type
  306. %
  307. % Labels - Labels for button and menu types.
  308. % - string matrix, one label per row
  309. % - bar delimited string
  310. % E.g. 'AnCova|Scaling|None'
  311. %
  312. % Values - Return values corresponding to Labels for button and menu types
  313. % - j-th row is returned if button / menu item j is selected
  314. % (row vectors are transposed)
  315. % - Defaults (missing or empty) to - (button) Labels
  316. % - ( menu ) menu item numbers
  317. %
  318. % DefItem - Default item number, for button and menu types.
  319. %
  320. % -- Parameters (output) --
  321. % p - results
  322. % YPos - Optional second output argument returns GUI position just used
  323. %
  324. %-----------------------------------------------------------------------
  325. % WINDOWS:
  326. %
  327. % spm_input uses the SPM 'Interactive' 'Tag'ged window. If this isn't
  328. % available and no figures are open, an 'Interactive' SPM window is
  329. % created (`spm('CreateIntWin')`). If figures are available, then the
  330. % current figure is used *unless* it is 'Tag'ged.
  331. %
  332. %-----------------------------------------------------------------------
  333. % SHORTCUTS:
  334. %
  335. % Buttons SHORTCUT - If the Type parameter is a bar delimited string, then
  336. % the Type is taken as 'b' with the specified labels, and the next parameter
  337. % (if specified) is taken for the Values.
  338. %
  339. % Yes/No question shortcut - p = spm_input(Prompt,YPos,'y/n') expands
  340. % to p = spm_input(Prompt,YPos,'b','yes|no',...), enabling easy use of
  341. % spm_input for yes/no dialogue. Values defaults to 'yn', so 'y' or 'n'
  342. % is returned as appropriate.
  343. %
  344. %-----------------------------------------------------------------------
  345. % EXAMPLES:
  346. % ( Specified YPos is overriden if global CMDLINE is )
  347. % ( true, when the command line versions are used. )
  348. %
  349. % p = spm_input
  350. % Command line input of an evaluated string, default prompt.
  351. % p = spm_input('Enter a value',1)
  352. % Evaluated string input, prompted by 'Enter a value', in
  353. % position 1 of the dialog figure.
  354. % p = spm_input(str,'+1','e',0.001)
  355. % Evaluated string input, prompted by contents of string str,
  356. % in next position of the dialog figure.
  357. % Default value of 0.001 offered.
  358. % p = spm_input(str,2,'e',[],5)
  359. % Evaluated string input, prompted by contents of string str,
  360. % in second position of the dialog figure.
  361. % Vector of length 5 required - returned as column vector
  362. % p = spm_input(str,2,'e',[],[Inf,5])
  363. % ...as above, but can enter multiple 5-vectors in a matrix,
  364. % returned with 5-vectors in rows
  365. % p = spm_input(str,0,'c','ababab')
  366. % Condition string input, prompted by contents of string str
  367. % Uses command line interface.
  368. % Default string of 'ababab' offered.
  369. % p = spm_input(str,0,'c','010101')
  370. % As above, but default string of '010101' offered.
  371. % [p,YPos] = spm_input(str,'0','s','Image')
  372. % String input, same position as last used, prompted by str,
  373. % default of 'Image' offered. YPos returns GUI position used.
  374. % p = spm_input(str,'-1','y/n')
  375. % Yes/No buttons for question with prompt str, in position one
  376. % before the last used Returns 'y' or 'n'.
  377. % p = spm_input(str,'-1','y/n',[1,0],2)
  378. % As above, but returns 1 for yes response, 0 for no,
  379. % with 'no' as the default response
  380. % p = spm_input(str,4,'AnCova|Scaling')
  381. % Presents two buttons labelled 'AnCova' & 'Scaling', with
  382. % prompt str, in position 4 of the dialog figure. Returns the
  383. % string on the depresed button, where buttons can be pressed
  384. % with the mouse or by the respective keyboard accelerators
  385. % 'a' & 's' (or 'A' & 'S').
  386. % p = spm_input(str,-4,'b','AnCova|Scaling',[],2)
  387. % As above, but makes "Scaling" the default response, and
  388. % overrides global CMDLINE
  389. % p = spm_input(str,0,'b','AnCova|Scaling|None',[1,2,3])
  390. % Prompts for [A]ncova / [S]caling / [N]one in MatLab command
  391. % window, returns 1, 2, or 3 according to the first character
  392. % of the entered string as one of 'a', 's', or 'n' (case
  393. % insensitive).
  394. % p = spm_input(str,1,'b','AnCova',1)
  395. % Since there's only one button, this just displays the response
  396. % in GUI position 1 (or on the command line if global CMDLINE
  397. % is true), and returns 1.
  398. % p = spm_input(str,'+0','br1','None|Mask',[-Inf,NaN],0.8)
  399. % Presents two buttons labelled "None" & "Mask" (which return
  400. % -Inf & NaN if clicked), together with an editable text widget
  401. % for entry of a single real number. The default of 0.8 is
  402. % initially presented in the edit window, and can be selected by
  403. % pressing return.
  404. % Uses the previous GUI position, unless global CMDLINE is true,
  405. % in which case a command-line equivalent is used.
  406. % p = spm_input(str,'+0','w1')
  407. % Prompts for a single whole number using a combination of
  408. % buttons and edit widget, using the previous GUI position,
  409. % or the command line if global CMDLINE is true.
  410. % p = spm_input(str,'!0','m','Single Subject|Multi Subject|Multi Study')
  411. % Prints the prompt str in a pull down menu containing items
  412. % 'Single Subject', 'Multi Subject' & 'Multi Study'. When OK is
  413. % clicked p is returned as the index of the choice, 1,2, or 3
  414. % respectively. Uses last used position in GUI, irrespective of
  415. % global CMDLINE
  416. % p = spm_input(str,5,'m',...
  417. % 'Single Subject|Multi Subject|Multi Study',...
  418. % ['SS';'MS';'SP'],2)
  419. % As above, but returns strings 'SS', 'MS', or 'SP' according to
  420. % the respective choice, with 'MS; as the default response.
  421. % p = spm_input(str,0,'m',...
  422. % 'Single Subject|Multi Subject|Multi Study',...
  423. % ['SS';'MS';'SP'],2)
  424. % As above, but the menu is presented in the command window
  425. % as a numbered list.
  426. % spm_input('AnCova, GrandMean scaling',0,'d')
  427. % Displays message in a box in the MatLab command window
  428. % [null,YPos]=spm_input('Session 1','+1','d!','fMRI')
  429. % Displays 'fMRI: Session 1' in next GUI position of the
  430. % 'Interactive' window. If CMDLINE is 1, then nothing is done.
  431. % Position used is returned in YPos.
  432. %
  433. %-----------------------------------------------------------------------
  434. % FORMAT h = spm_input(Prompt,YPos,'m!',Labels,cb,UD,XCB);
  435. % GUI PullDown menu utility - creates a pulldown menu in the Interactive window
  436. % FORMAT H = spm_input(Prompt,YPos,'b!',Labels,cb,UD,XCB);
  437. % GUI Buttons utility - creates GUI buttons in the Interactive window
  438. %
  439. % Prompt, YPos, Labels - as with 'm'enu/'b'utton types
  440. % cb - CallBack string
  441. % UD - UserData
  442. % XCB - Extended CallBack handling - allows different CallBack for each item,
  443. % and use of UD in CallBack strings. [Defaults to 1 for PullDown type
  444. % when multiple CallBacks specified, 0 o/w.]
  445. % H - Handle of 'PullDown' uicontrol / 'Button's
  446. %
  447. % In "normal" mode (when XCB is false), this is essentially a utility
  448. % to create a PullDown menu widget or set of buttons in the SPM
  449. % 'Interactive' figure, using positioning and Label definition
  450. % conveniences of the spm_input 'm'enu & 'b'utton types. If Prompt is
  451. % not empty, then the PullDown/Buttons appears on the right, with the
  452. % Prompt on the left, otherwise the PullDown/Buttons use the whole
  453. % width of the Interactive figure. The PopUp's CallBack string is
  454. % specified in cb, and [optional] UserData may be passed as UD.
  455. %
  456. % For buttons, a separate callback can be specified for each button, by
  457. % passing the callbacks corresponding to the Labels as rows of a
  458. % cellstr or string matrix.
  459. %
  460. % This "different CallBacks" facility can also be extended to the
  461. % PullDown type, using the "extended callback" mode (when XCB is
  462. % true). % In addition, in "extended callback", you can use UD to
  463. % refer to the UserData argument in the CallBack strings. (What happens
  464. % is this: The cb & UD are stored as fields in the PopUp's UserData
  465. % structure, and the PopUp's callback is set to spm_input('!m_cb'),
  466. % which reads UD into the functions workspace and eval's the
  467. % appropriate CallBack string. Note that this means that base
  468. % workspace variables are inaccessible (put what you need in UD), and
  469. % that any return arguments from CallBack functions are not passed back
  470. % to the base workspace).
  471. %
  472. %
  473. %-----------------------------------------------------------------------
  474. % UTILITY FUNCTIONS:
  475. %
  476. % FORMAT colour = spm_input('!Colour')
  477. % Returns colour for input widgets, as specified in COLOUR parameter at
  478. % start of code.
  479. % colour - [r,g,b] colour triple
  480. %
  481. % FORMAT [iCond,msg] = spm_input('!iCond',str,n,m)
  482. % Parser for special 'c'ondition type: Handles digit strings and
  483. % strings of indicator chars.
  484. % str - input string
  485. % n - length of condition vector required [defaut Inf - no restriction]
  486. % m - number of conditions required [default Inf - no restrictions]
  487. % iCond - Integer condition indicator vector
  488. % msg - status message
  489. %
  490. % FORMAT hM = spm_input('!InptConMen',Finter,H)
  491. % Sets a basic Input ContextMenu for the figure
  492. % Finter - figure to set menu in
  493. % H - handles of objects to delete on "crash out" option
  494. % hM - handle of UIContextMenu
  495. %
  496. % FORMAT [CmdLine,YPos] = spm_input('!CmdLine',YPos)
  497. % Sorts out whether to use CmdLine or not & canonicalises YPos
  498. % CmdLine - Binary flag
  499. % YPos - Position index
  500. %
  501. % FORMAT Finter = spm_input('!GetWin',F)
  502. % Locates (or creates) figure to work in
  503. % F - Interactive Figure, defaults to 'Interactive'
  504. % Finter - Handle of figure to use
  505. %
  506. % FORMAT [PLoc,cF] = spm_input('!PointerJump',RRec,F,XDisp)
  507. % Raise window & jump pointer over question
  508. % RRec - Response rectangle of current question
  509. % F - Interactive Figure, Defaults to 'Interactive'
  510. % XDisp - X-displacement of cursor relative to RRec
  511. % PLoc - Pointer location before jumping
  512. % cF - Current figure before making F current.
  513. %
  514. % FORMAT [PLoc,cF] = spm_input('!PointerJumpBack',PLoc,cF)
  515. % Replace pointer and reset CurrentFigure back
  516. % PLoc - Pointer location before jumping
  517. % cF - Previous current figure
  518. %
  519. % FORMAT spm_input('!PrntPrmpt',Prompt,TipStr,Title)
  520. % Print prompt for CmdLine questioning
  521. % Prompt - prompt string, callstr, or string matrix
  522. % TipStr - tip string
  523. % Title - title string
  524. %
  525. % FORMAT [Frec,QRec,PRec,RRec] = spm_input('!InputRects',YPos,rec,F)
  526. % Returns rectangles (pixels) used in GUI
  527. % YPos - Position index
  528. % rec - Rectangle specifier: String, one of 'Frec','QRec','PRec','RRec'
  529. % Defaults to '', which returns them all.
  530. % F - Interactive Figure, Defaults to spm_figure('FindWin','Interactive')
  531. % FRec - Position of interactive window
  532. % QRec - Position of entire question
  533. % PRec - Position of prompt
  534. % RRec - Position of response
  535. %
  536. % FORMAT spm_input('!DeleteInputObj',F)
  537. % Deltes input objects (only) from figure F
  538. % F - Interactive Figure, Defaults to spm_figure('FindWin','Interactive')
  539. %
  540. % FORMAT [CPos,hCPos] = spm_input('!CurrentPos',F)
  541. % Returns currently used GUI question positions & their handles
  542. % F - Interactive Figure, Defaults to spm_figure('FindWin','Interactive')
  543. % CPos - Vector of position indices
  544. % hCPos - (n x CPos) matrix of object handles
  545. %
  546. % FORMAT h = spm_input('!FindInputObj',F)
  547. % Returns handles of input GUI objects in figure F
  548. % F - Interactive Figure, Defaults to spm_figure('FindWin','Interactive')
  549. % h - vector of object handles
  550. %
  551. % FORMAT [NPos,CPos,hCPos] = spm_input('!NextPos',YPos,F,CmdLine)
  552. % Returns next position index, specified by YPos
  553. % YPos - Absolute (integer) or relative (string) position index
  554. % Defaults to '+1'
  555. % F - Interactive Figure, defaults to spm_figure('FindWin','Interactive')
  556. % CmdLine - Command line? Defaults to spm_input('!CmdLine',YPos)
  557. % NPos - Next position index
  558. % CPos & hCPos - as for !CurrentPos
  559. %
  560. % FORMAT NPos = spm_input('!SetNextPos',YPos,F,CmdLine)
  561. % Sets up for input at next position index, specified by YPos. This utility
  562. % function can be used stand-alone to implicitly set the next position
  563. % by clearing positions NPos and greater.
  564. % YPos - Absolute (integer) or relative (string) position index
  565. % Defaults to '+1'
  566. % F - Interactive Figure, defaults to spm_figure('FindWin','Interactive')
  567. % CmdLine - Command line? Defaults to spm_input('!CmdLine',YPos)
  568. % NPos - Next position index
  569. %
  570. % FORMAT MPos = spm_input('!MaxPos',F,FRec3)
  571. % Returns maximum position index for figure F
  572. % F - Interactive Figure, Defaults to spm_figure('FindWin','Interactive')
  573. % Not required if FRec3 is specified
  574. % FRec3 - Length of interactive figure in pixels
  575. %
  576. % FORMAT spm_input('!EditableKeyPressFcn',h,ch)
  577. % KeyPress callback for GUI string / eval input
  578. %
  579. % FORMAT spm_input('!ButtonKeyPressFcn',h,Keys,DefItem,ch)
  580. % KeyPress callback for GUI buttons
  581. %
  582. % FORMAT spm_input('!PullDownKeyPressFcn',h,ch,DefItem)
  583. % KeyPress callback for GUI pulldown menus
  584. %
  585. % FORMAT spm_input('!m_cb')
  586. % Extended CallBack handler for 'p' PullDown utility type
  587. %
  588. % FORMAT spm_input('!dScroll',h,str)
  589. % Scroll text string in object h
  590. % h - handle of text object
  591. % Prompt - Text to scroll (Defaults to 'UserData' of h)
  592. %
  593. %-----------------------------------------------------------------------
  594. % SUBFUNCTIONS:
  595. %
  596. % FORMAT [Keys,Labs] = sf_labkeys(Labels)
  597. % Make unique character keys for the Labels, ignoring case.
  598. % Used with 'b'utton types.
  599. %
  600. % FORMAT [p,msg] = sf_eEval(str,Type,n,m)
  601. % Common code for evaluating various input types.
  602. %
  603. % FORMAT str = sf_SzStr(n,l)
  604. % Common code to construct prompt strings for pre-specified vector/matrix sizes
  605. %
  606. % FORMAT [p,msg] = sf_SzChk(p,n,msg)
  607. % Common code to check (& canonicalise) sizes of input vectors/matrices
  608. %
  609. %_______________________________________________________________________
  610. % @(#)spm_input.m 2.8 Andrew Holmes 03/03/04
  611. %-Parameters
  612. %=======================================================================
  613. PJump = 1; %-Jumping of pointer to question?
  614. TTips = 1; %-Use ToolTipStrings? (which can be annoying!)
  615. ConCrash = 1; %-Add "crash out" option to 'Interactive'fig.ContextMenu
  616. %-Condition arguments
  617. %=======================================================================
  618. if nargin<1||isempty(varargin{1}), Prompt=''; else Prompt=varargin{1}; end
  619. if ~isempty(Prompt) && ischar(Prompt) && Prompt(1)=='!'
  620. %-Utility functions have Prompt string starting with '!'
  621. Type = Prompt;
  622. else %-Should be an input request: get Type & YPos
  623. if nargin<3||isempty(varargin{3}), Type='e'; else Type=varargin{3}; end
  624. if any(Type=='|'), Type='b|'; end
  625. if nargin<2||isempty(varargin{2}), YPos='+1'; else YPos=varargin{2}; end
  626. [CmdLine,YPos] = spm_input('!CmdLine',YPos);
  627. if ~CmdLine %-Setup for GUI use
  628. %-Locate (or create) figure to work in
  629. Finter = spm_input('!GetWin');
  630. COLOUR = get(Finter,'Color');
  631. %-Find out which Y-position to use, setup for use
  632. YPos = spm_input('!SetNextPos',YPos,Finter,CmdLine);
  633. %-Determine position of objects
  634. [FRec,QRec,PRec,RRec]=spm_input('!InputRects',YPos,'',Finter);
  635. end
  636. end
  637. switch lower(Type)
  638. case {'s','s+','e','n','w','i','r','c','x','p'} %-String and evaluated input
  639. %=======================================================================
  640. %-Condition arguments
  641. if nargin<6||isempty(varargin{6}), m=[]; else m=varargin{6}; end
  642. if nargin<5||isempty(varargin{5}), n=[]; else n=varargin{5}; end
  643. if nargin<4, DefStr=''; else DefStr=varargin{4}; end
  644. if strcmpi(Type,'s+')
  645. %-DefStr should be a cellstr for 's+' type.
  646. if isempty(DefStr), DefStr = {};
  647. else DefStr = cellstr(DefStr); end
  648. DefStr = DefStr(:);
  649. else
  650. %-DefStr needs to be a string
  651. if ~ischar(DefStr), DefStr=num2str(DefStr); end
  652. DefStr = DefStr(:)';
  653. end
  654. strM='';
  655. switch lower(Type) %-Type specific defaults/setup
  656. case 's', TTstr='enter string';
  657. case 's+',TTstr='enter string - multi-line';
  658. case 'e', TTstr='enter expression to evaluate';
  659. case 'n', TTstr='enter expression - natural number(s)';
  660. if ~isempty(m), strM=sprintf(' (in [1,%d])',m); TTstr=[TTstr,strM]; end
  661. case 'w', TTstr='enter expression - whole number(s)';
  662. if ~isempty(m), strM=sprintf(' (in [0,%d])',m); TTstr=[TTstr,strM]; end
  663. case 'i', TTstr='enter expression - integer(s)';
  664. case 'r', TTstr='enter expression - real number(s)';
  665. if ~isempty(m), TTstr=[TTstr,sprintf(' in [%g,%g]',min(m),max(m))]; end
  666. case 'c', TTstr='enter indicator vector e.g. 0101... or abab...';
  667. if ~isempty(m) && isfinite(m), strM=sprintf(' (%d)',m); end
  668. case 'x', TTstr='enter contrast matrix';
  669. case 'p',
  670. if isempty(n), error('permutation of what?'), else P=n(:)'; end
  671. if isempty(m), n = [1,length(P)]; end
  672. m = P;
  673. if isempty(setxor(m,[1:max(m)]))
  674. TTstr=['enter permutation of [1:',num2str(max(m)),']'];
  675. else
  676. TTstr=['enter permutation of [',num2str(m),']'];
  677. end
  678. otherwise
  679. TTstr='enter expression';
  680. end
  681. strN = sf_SzStr(n);
  682. if CmdLine %-Use CmdLine to get answer
  683. %-----------------------------------------------------------------------
  684. spm_input('!PrntPrmpt',[Prompt,strN,strM],TTstr)
  685. %-Do Eval Types in Base workspace, catch errors
  686. switch lower(Type), case 's'
  687. if ~isempty(DefStr)
  688. Prompt=[Prompt,' (Default: ',DefStr,' )'];
  689. end
  690. str = input([Prompt,' : '],'s');
  691. if isempty(str), str=DefStr; end
  692. while isempty(str)
  693. spm('Beep')
  694. fprintf('! %s : enter something!\n',mfilename)
  695. str = input([Prompt,' : '],'s');
  696. if isempty(str), str=DefStr; end
  697. end
  698. p = str; msg = '';
  699. case 's+'
  700. fprintf(['Multi-line input: Type ''.'' on a line',...
  701. ' of its own to terminate input.\n'])
  702. if ~isempty(DefStr)
  703. fprintf('Default : (press return to accept)\n')
  704. fprintf(' : %s\n',DefStr{:})
  705. end
  706. fprintf('\n')
  707. str = input('l001 : ','s');
  708. while (isempty(str) || strcmp(str,'.')) && isempty(DefStr)
  709. spm('Beep')
  710. fprintf('! %s : enter something!\n',mfilename)
  711. str = input('l001 : ','s');
  712. end
  713. if isempty(str)
  714. %-Accept default
  715. p = DefStr;
  716. else
  717. %-Got some input, allow entry of additional lines
  718. p = {str};
  719. str = input(sprintf('l%03u : ',length(p)+1),'s');
  720. while ~strcmp(str,'.')
  721. p = [p;{str}];
  722. str = input(sprintf('l%03u : ',length(p)+1),'s');
  723. end
  724. end
  725. msg = '';
  726. otherwise
  727. if ~isempty(DefStr)
  728. Prompt=[Prompt,' (Default: ',DefStr,' )'];
  729. end
  730. str = input([Prompt,' : '],'s');
  731. if isempty(str), str=DefStr; end
  732. [p,msg] = sf_eEval(str,Type,n,m);
  733. while ischar(p)
  734. spm('Beep'), fprintf('! %s : %s\n',mfilename,msg)
  735. str = input([Prompt,' : '],'s');
  736. if isempty(str), str=DefStr; end
  737. [p,msg] = sf_eEval(str,Type,n,m);
  738. end
  739. end
  740. if ~isempty(msg), fprintf('\t%s\n',msg), end
  741. else %-Use GUI to get answer
  742. %-----------------------------------------------------------------------
  743. %-Create text and edit control objects
  744. %---------------------------------------------------------------
  745. hPrmpt = uicontrol(Finter,'Style','Text',...
  746. 'String',[strN,Prompt,strM],...
  747. 'Tag',['GUIinput_',int2str(YPos)],...
  748. 'UserData','',...
  749. 'BackgroundColor',COLOUR,...
  750. 'HorizontalAlignment','Right',...
  751. 'Position',PRec);
  752. if TTips, set(hPrmpt,'ToolTipString',[strN,Prompt,strM]); end
  753. %-Default button surrounding edit widget (if a DefStr given)
  754. %-Callback sets hPrmpt UserData, and EditWidget string, to DefStr
  755. % (Buttons UserData holds handles [hPrmpt,hEditWidget], set later)
  756. cb = ['set(get(gcbo,''UserData'')*[1;0],''UserData'',',...
  757. 'get(gcbo,''String'')),',...
  758. 'set(get(gcbo,''UserData'')*[0;1],''String'',',...
  759. 'get(gcbo,''String''))'];
  760. if ~isempty(DefStr)
  761. if iscellstr(DefStr), str=[DefStr{1},'...'];
  762. else str=DefStr; end
  763. hDef = uicontrol(Finter,'Style','PushButton',...
  764. 'String',DefStr,...
  765. 'ToolTipString',...
  766. ['Click on border to accept default: ' str],...
  767. 'Tag',['GUIinput_',int2str(YPos)],...
  768. 'UserData',[],...
  769. 'BackgroundColor',COLOUR,...
  770. 'CallBack',cb,...
  771. 'Position',RRec+[-2,-2,+4,+4]);
  772. else
  773. hDef = [];
  774. end
  775. %-Edit widget: Callback puts string into hPrompts UserData
  776. cb = 'set(get(gcbo,''UserData''),''UserData'',get(gcbo,''String''))';
  777. h = uicontrol(Finter,'Style','Edit',...
  778. 'String',DefStr,...
  779. 'Max',strcmpi(Type,'s+')+1,...
  780. 'Tag',['GUIinput_',int2str(YPos)],...
  781. 'UserData',hPrmpt,...
  782. 'CallBack',cb,...
  783. 'Horizontalalignment','Left',...
  784. 'BackgroundColor','w',...
  785. 'Position',RRec);
  786. set(hDef,'UserData',[hPrmpt,h])
  787. uifocus(h);
  788. if TTips, set(h,'ToolTipString',TTstr), end
  789. %-Figure ContextMenu for shortcuts
  790. hM = spm_input('!InptConMen',Finter,[hPrmpt,hDef,h]);
  791. cb = [ 'set(get(gcbo,''UserData''),''String'',',...
  792. '[''spm_load('''''',spm_select(1),'''''')'']), ',...
  793. 'set(get(get(gcbo,''UserData''),''UserData''),''UserData'',',...
  794. 'get(get(gcbo,''UserData''),''String''))'];
  795. uimenu(hM,'Label','load from text file','Separator','on',...
  796. 'CallBack',cb,'UserData',h)
  797. %-Bring window to fore & jump pointer to edit widget
  798. [PLoc,cF] = spm_input('!PointerJump',RRec,Finter);
  799. %-Setup FigureKeyPressFcn for editing of entry widget without clicking
  800. set(Finter,'KeyPressFcn',[...
  801. 'spm_input(''!EditableKeyPressFcn'',',...
  802. 'findobj(gcf,''Tag'',''GUIinput_',int2str(YPos),''',',...
  803. '''Style'',''edit''),',...
  804. 'get(gcbf,''CurrentCharacter''))'])
  805. %-Wait for edit, do eval Types in Base workspace, catch errors
  806. %---------------------------------------------------------------
  807. waitfor(hPrmpt,'UserData')
  808. if ~ishandle(hPrmpt), error(['Input window cleared whilst waiting ',...
  809. 'for response: Bailing out!']), end
  810. str = get(hPrmpt,'UserData');
  811. switch lower(Type), case 's'
  812. p = str; msg = '';
  813. case 's+'
  814. p = cellstr(str); msg = '';
  815. otherwise
  816. [p,msg] = sf_eEval(str,Type,n,m);
  817. while ischar(p)
  818. set(h,'Style','Text',...
  819. 'String',msg,'HorizontalAlignment','Center',...
  820. 'ForegroundColor','r')
  821. spm('Beep'), pause(2)
  822. set(h,'Style','Edit',...
  823. 'String',str,...
  824. 'HorizontalAlignment','Left',...
  825. 'ForegroundColor','k')
  826. %set(hPrmpt,'UserData','');
  827. waitfor(hPrmpt,'UserData')
  828. if ~ishandle(hPrmpt), error(['Input window cleared ',...
  829. 'whilst waiting for response: Bailing out!']),end
  830. str = get(hPrmpt,'UserData');
  831. [p,msg] = sf_eEval(str,Type,n,m);
  832. end
  833. end
  834. %-Fix edit window, clean up, reposition pointer, set CurrentFig back
  835. delete([hM,hDef]), set(Finter,'KeyPressFcn','')
  836. set(h,'Style','Text','HorizontalAlignment','Center',...
  837. 'ToolTipString',msg,...
  838. 'BackgroundColor',COLOUR)
  839. spm_input('!PointerJumpBack',PLoc,cF)
  840. drawnow
  841. end % (if CmdLine)
  842. %-Return response
  843. %-----------------------------------------------------------------------
  844. varargout = {p,YPos};
  845. case {'b','bd','b|','y/n','be1','bn1','bw1','bi1','br1',...
  846. '-n1','n1','-w1','w1','m'} %-'b'utton & 'm'enu Types
  847. %=======================================================================
  848. %-Condition arguments
  849. switch lower(Type), case {'b','be1','bi1','br1','m'}
  850. m = []; Title = '';
  851. if nargin<6, DefItem=[]; else DefItem=varargin{6}; end
  852. if nargin<5, Values=[]; else Values =varargin{5}; end
  853. if nargin<4, Labels=''; else Labels =varargin{4}; end
  854. case 'bd'
  855. if nargin<7, Title=''; else Title =varargin{7}; end
  856. if nargin<6, DefItem=[]; else DefItem=varargin{6}; end
  857. if nargin<5, Values=[]; else Values =varargin{5}; end
  858. if nargin<4, Labels=''; else Labels =varargin{4}; end
  859. case 'y/n'
  860. Title = '';
  861. if nargin<5, DefItem=[]; else DefItem=varargin{5}; end
  862. if nargin<4, Values=[]; else Values =varargin{4}; end
  863. if isempty(Values), Values='yn'; end
  864. Labels = {'yes','no'};
  865. case 'b|'
  866. Title = '';
  867. if nargin<5, DefItem=[]; else DefItem=varargin{5}; end
  868. if nargin<4, Values=[]; else Values =varargin{4}; end
  869. Labels = varargin{3};
  870. case 'bn1'
  871. if nargin<7, m=[]; else m=varargin{7}; end
  872. if nargin<6, DefItem=[]; else DefItem=varargin{6}; end
  873. if nargin<5, Values=[]; else Values =varargin{5}; end
  874. if nargin<4, Labels=[1:5]'; Values=[1:5]; Type='-n1';
  875. else Labels=varargin{4}; end
  876. case 'bw1'
  877. if nargin<7, m=[]; else m=varargin{7}; end
  878. if nargin<6, DefItem=[]; else DefItem=varargin{6}; end
  879. if nargin<5, Values=[]; else Values =varargin{5}; end
  880. if nargin<4, Labels=[0:4]'; Values=[0:4]; Type='-w1';
  881. else Labels=varargin{4}; end
  882. case {'-n1','n1','-w1','w1'}
  883. if nargin<5, m=[]; else m=varargin{5}; end
  884. if nargin<4, DefItem=[]; else DefItem=varargin{4}; end
  885. switch lower(Type)
  886. case {'n1','-n1'}, Labels=[1:min([5,m])]'; Values=Labels'; Type='-n1';
  887. case {'w1','-w1'}, Labels=[0:min([4,m])]'; Values=Labels'; Type='-w1';
  888. end
  889. end
  890. %-Check some labels were specified
  891. if isempty(Labels), error('No Labels specified'), end
  892. if iscellstr(Labels), Labels=char(Labels); end
  893. %-Convert Labels "option" string to string matrix if required
  894. if ischar(Labels) && any(Labels(:)=='|')
  895. OptStr=Labels;
  896. BarPos=find([OptStr=='|',1]);
  897. Labels=OptStr(1:BarPos(1)-1);
  898. for Bar = 2:sum(OptStr=='|')+1
  899. Labels=strvcat(Labels,OptStr(BarPos(Bar-1)+1:BarPos(Bar)-1));
  900. end
  901. end
  902. %-Set default Values for the Labels
  903. if isempty(Values)
  904. if strcmpi(Type,'m')
  905. Values=[1:size(Labels,1)]';
  906. else
  907. Values=Labels;
  908. end
  909. else
  910. %-Make sure Values are in rows
  911. if size(Labels,1)>1 && size(Values,1)==1, Values = Values'; end
  912. %-Check numbers of Labels and Values match
  913. if (size(Labels,1)~=size(Values,1))
  914. error('Labels & Values incompatible sizes'), end
  915. end
  916. %-Numeric Labels to strings
  917. if isnumeric(Labels)
  918. tmp = Labels; Labels = cell(size(tmp,1),1);
  919. for i=1:numel(tmp), Labels{i}=num2str(tmp(i,:)); end
  920. Labels=char(Labels);
  921. end
  922. switch lower(Type), case {'b','bd','b|','y/n'} %-Process button types
  923. %=======================================================================
  924. %-Make unique character keys for the Labels, sort DefItem
  925. %---------------------------------------------------------------
  926. nLabels = size(Labels,1);
  927. [Keys,Labs] = sf_labkeys(Labels);
  928. if ~isempty(DefItem) && any(DefItem==[1:nLabels])
  929. DefKey = Keys(DefItem);
  930. else
  931. DefItem = 0;
  932. DefKey = '';
  933. end
  934. if CmdLine
  935. %-Display question prompt
  936. spm_input('!PrntPrmpt',Prompt,'',Title)
  937. %-Build prompt
  938. %-------------------------------------------------------
  939. if ~isempty(Labs)
  940. Prmpt = ['[',Keys(1),']',deblank(Labs(1,:)),' '];
  941. for i = 2:nLabels
  942. Prmpt=[Prmpt,'/ [',Keys(i),']',deblank(Labs(i,:)),' '];
  943. end
  944. else
  945. Prmpt = ['[',Keys(1),'] '];
  946. for i = 2:nLabels, Prmpt=[Prmpt,'/ [',Keys(i),'] ']; end
  947. end
  948. if DefItem
  949. Prmpt = [Prmpt,...
  950. ' (Default: ',deblank(Labels(DefItem,:)),')'];
  951. end
  952. %-Ask for user response
  953. %-------------------------------------------------------
  954. if nLabels==1
  955. %-Only one choice - auto-pick & display
  956. k = 1; fprintf('%s: %s\t(only option)',Prmpt,Labels)
  957. else
  958. str = input([Prmpt,'? '],'s');
  959. if isempty(str), str=DefKey; end
  960. while isempty(str) || ~any(lower(Keys)==lower(str(1)))
  961. if ~isempty(str),fprintf('%c\t!Out of range\n',7),end
  962. str = input([Prmpt,'? '],'s');
  963. if isempty(str), str=DefKey; end
  964. end
  965. k = find(lower(Keys)==lower(str(1)));
  966. end
  967. fprintf('\n')
  968. p = Values(k,:); if ischar(p), p=deblank(p); end
  969. elseif strcmpi(Type,'bd')
  970. if nLabels>3, error('at most 3 labels for GUI ''bd'' type'), end
  971. tmp = cellstr(Labels);
  972. if DefItem
  973. tmp = [tmp; tmp(DefItem)];
  974. Prompt = cellstr(Prompt); Prompt=Prompt(:);
  975. Prompt = [Prompt;{' '};...
  976. {['[default: ',tmp{DefItem},']']}];
  977. else
  978. tmp = [tmp; tmp(1)];
  979. end
  980. k = min(find(strcmp(tmp,...
  981. questdlg(Prompt,sprintf('%s: %s...',spm('Version'),Title),...
  982. tmp{:}))));
  983. p = Values(k,:); if ischar(p), p=deblank(p); end
  984. else
  985. Tag = ['GUIinput_',int2str(YPos)]; %-Tag for widgets
  986. %-Create text and edit control objects
  987. %-'UserData' of prompt contains answer
  988. %-------------------------------------------------------
  989. hPrmpt = uicontrol(Finter,'Style','Text',...
  990. 'String',Prompt,...
  991. 'Tag',Tag,...
  992. 'UserData',[],...
  993. 'BackgroundColor',COLOUR,...
  994. 'HorizontalAlignment','Right',...
  995. 'Position',PRec);
  996. if TTips, set(hPrmpt,'ToolTipString',Prompt); end
  997. if nLabels==1
  998. %-Only one choice - auto-pick
  999. k = 1;
  1000. else
  1001. %-Draw buttons and process response
  1002. dX = RRec(3)/nLabels;
  1003. if TTips, str = ['select with mouse or use kbd: ',...
  1004. sprintf('%c/',Keys(1:end-1)),Keys(end)];
  1005. else str=''; end
  1006. %-Store button # in buttons 'UserData' property
  1007. %-Store handle of prompt string in buttons 'Max' property
  1008. %-Button callback sets UserData of prompt string to
  1009. % number of pressed button
  1010. cb = ['set(get(gcbo,''UserData''),''UserData'',',...
  1011. 'get(gcbo,''Max''))'];
  1012. H = [];
  1013. XDisp = [];
  1014. for i=1:nLabels
  1015. if i==DefItem
  1016. %-Default button, outline it
  1017. h = uicontrol(Finter,'Style','Frame',...
  1018. 'BackGroundColor','k',...
  1019. 'ForeGroundColor','k',...
  1020. 'Tag',Tag,...
  1021. 'Position',...
  1022. [RRec(1)+(i-1)*dX ...
  1023. RRec(2)-1 dX RRec(4)+2]);
  1024. XDisp = (i-1/3)*dX;
  1025. H = [H,h];
  1026. end
  1027. h = uicontrol(Finter,'Style','Pushbutton',...
  1028. 'String',deblank(Labels(i,:)),...
  1029. 'ToolTipString',sprintf('%s\n%s',deblank(Labels(i,:)),str),...
  1030. 'Tag',Tag,...
  1031. 'Max',i,...
  1032. 'UserData',hPrmpt,...
  1033. 'BackgroundColor',COLOUR,...
  1034. 'Callback',cb,...
  1035. 'Position',[RRec(1)+(i-1)*dX+1 ...
  1036. RRec(2) dX-2 RRec(4)]);
  1037. if i == DefItem, uifocus(h); end
  1038. H = [H,h];
  1039. end
  1040. %-Figure ContextMenu for shortcuts
  1041. hM = spm_input('!InptConMen',Finter,[hPrmpt,H]);
  1042. %-Bring window to fore & jump pointer to default button
  1043. [PLoc,cF]=spm_input('!PointerJump',RRec,Finter,XDisp);
  1044. %-Callback for KeyPress, to store valid button # in
  1045. % UserData of Prompt, DefItem if (DefItem~=0)
  1046. % & return (ASCII-13) is pressed
  1047. set(Finter,'KeyPressFcn',...
  1048. ['spm_input(''!ButtonKeyPressFcn'',',...
  1049. 'findobj(gcf,''Tag'',''',Tag,''',',...
  1050. '''Style'',''text''),',...
  1051. '''',lower(Keys),''',',num2str(DefItem),',',...
  1052. 'get(gcbf,''CurrentCharacter''))'])
  1053. %-Wait for button press, process results
  1054. %-----------------------------------------------
  1055. waitfor(hPrmpt,'UserData')
  1056. if ~ishandle(hPrmpt)
  1057. error(['Input objects cleared whilst ',...
  1058. 'waiting for response: Bailing out!'])
  1059. end
  1060. k = get(hPrmpt,'UserData');
  1061. %-Clean up
  1062. delete([H,hM]), set(Finter,'KeyPressFcn','')
  1063. spm_input('!PointerJumpBack',PLoc,cF)
  1064. end
  1065. %-Display answer
  1066. uicontrol(Finter,'Style','Text',...
  1067. 'String',deblank(Labels(k,:)),...
  1068. 'Tag',Tag,...
  1069. 'Horizontalalignment','Center',...
  1070. 'BackgroundColor',COLOUR,...
  1071. 'Position',RRec);
  1072. drawnow
  1073. p = Values(k,:); if ischar(p), p=deblank(p); end
  1074. end
  1075. case {'be1','bn1','bw1','bi1','br1','-n1','-w1'}
  1076. %-Process button/entry combo types
  1077. %=======================================================================
  1078. if ischar(DefItem), DefStr=DefItem; else DefStr=num2str(DefItem); end
  1079. if isempty(m), strM=''; else strM=sprintf(' (<=%d)',m); end
  1080. if CmdLine
  1081. %-Process default item
  1082. %---------------------------------------------------------------
  1083. if ~isempty(DefItem)
  1084. [DefVal,msg] = sf_eEval(DefStr,Type(2),1);
  1085. if ischar(DefVal), error(['Invalid DefItem: ',msg]), end
  1086. Labels = strvcat(Labels,DefStr);
  1087. Values = [Values;DefVal];
  1088. DefItem = size(Labels,1);
  1089. end
  1090. %-Add option to specify...
  1091. Labels = strvcat(Labels,'specify...');
  1092. %-Process options
  1093. nLabels = size(Labels,1);
  1094. [Keys,Labs] = sf_labkeys(Labels);
  1095. if ~isempty(DefItem), DefKey = Keys(DefItem); else DefKey = ''; end
  1096. %-Print banner prompt
  1097. %---------------------------------------------------------------
  1098. spm_input('!PrntPrmpt',Prompt) %-Display question prompt
  1099. if Type(1)=='-' %-No special buttons - go straight to input
  1100. k = size(Labels,1);
  1101. else %-Offer buttons, default or "specify..."
  1102. %-Build prompt
  1103. %-------------------------------------------------------
  1104. if ~isempty(Labs)
  1105. Prmpt = ['[',Keys(1),']',deblank(Labs(1,:)),' '];
  1106. for i = 2:nLabels
  1107. Prmpt=[Prmpt,'/ [',Keys(i),']',deblank(Labs(i,:)),' '];
  1108. end
  1109. else
  1110. Prmpt = ['[',Keys(1),'] '];
  1111. for i = 2:nLabels, Prmpt=[Prmpt,'/ [',Keys(i),'] ']; end
  1112. end
  1113. if DefItem, Prmpt = [Prmpt,...
  1114. ' (Default: ',deblank(Labels(DefItem,:)),')']; end
  1115. %-Ask for user response
  1116. %-------------------------------------------------------
  1117. if nLabels==1
  1118. %-Only one choice - auto-pick & display
  1119. k = 1; fprintf('%s: %s\t(only option)',Prmpt,Labels)
  1120. else
  1121. str = input([Prmpt,'? '],'s');
  1122. if isempty(str), str=DefKey; end
  1123. while isempty(str) || ~any(lower(Keys)==lower(str(1)))
  1124. if ~isempty(str),fprintf('%c\t!Invalid response\n',7),end
  1125. str = input([Prmpt,'? '],'s');
  1126. if isempty(str), str=DefKey; end
  1127. end
  1128. k = find(lower(Keys)==lower(str(1)));
  1129. end
  1130. fprintf('\n')
  1131. end
  1132. %-Process response: prompt for value if "specify..." option chosen
  1133. %===============================================================
  1134. if k<size(Labels,1)
  1135. p = Values(k,:); if ischar(p), p=deblank(p); end
  1136. else
  1137. %-"specify option chosen: ask user to specify
  1138. %-------------------------------------------------------
  1139. switch lower(Type(2))
  1140. case 's', tstr=' string';
  1141. case 'e', tstr='n expression';
  1142. case 'n', tstr=' natural number';
  1143. case 'w', tstr=' whole number';
  1144. case 'i', tstr='n integer';
  1145. case 'r', tstr=' real number';
  1146. otherwise, tstr='';
  1147. end
  1148. Prompt = sprintf('%s (a%s%s)',Prompt,tstr,strM);
  1149. if ~isempty(DefStr)
  1150. Prompt=sprintf('%s\b, default %s)',Prompt,DefStr); end
  1151. str = input([Prompt,' : '],'s');
  1152. if isempty(str), str=DefStr; end
  1153. %-Eval in Base workspace, catch errors
  1154. [p,msg] = sf_eEval(str,Type(2),1,m);
  1155. while ischar(p)
  1156. spm('Beep'), fprintf('! %s : %s\n',mfilename,msg)
  1157. str = input([Prompt,' : '],'s');
  1158. if isempty(str), str=DefStr; end
  1159. [p,msg] = sf_eEval(str,Type(2),1,m);
  1160. end
  1161. end
  1162. else
  1163. Tag = ['GUIinput_',int2str(YPos)]; %-Tag for widgets
  1164. nLabels = size(Labels,1); %-#buttons
  1165. %-Create text and edit control objects
  1166. %-'UserData' of prompt contains answer
  1167. %---------------------------------------------------------------
  1168. hPrmpt = uicontrol(Finter,'Style','Text',...
  1169. 'String',[Prompt,strM],...
  1170. 'Tag',Tag,...
  1171. 'UserData',[],...
  1172. 'BackgroundColor',COLOUR,...
  1173. 'HorizontalAlignment','Right',...
  1174. 'Position',PRec);
  1175. if TTips, set(hPrmpt,'ToolTipString',[Prompt,strM]); end
  1176. %-Draw buttons & entry widget, & process response
  1177. dX = RRec(3)*(2/3)/nLabels;
  1178. %-Store button # in buttons 'UserData'
  1179. %-Store handle of prompt string in buttons 'Max' property
  1180. %-Callback sets UserData of prompt string to button number.
  1181. cb = ['set(get(gcbo,''UserData''),''UserData'',get(gcbo,''Max''))'];
  1182. if TTips, str=sprintf('select by mouse or enter value in text widget');
  1183. else str=''; end
  1184. H = [];
  1185. for i=1:nLabels
  1186. h = uicontrol(Finter,'Style','Pushbutton',...
  1187. 'String',deblank(Labels(i,:)),...
  1188. 'Max',i,...
  1189. 'ToolTipString',sprintf('%s\n%s',deblank(Labels(i,:)),str),...
  1190. 'Tag',Tag,...
  1191. 'UserData',hPrmpt,...
  1192. 'BackgroundColor',COLOUR,...
  1193. 'Callback',cb,...
  1194. 'Position',[RRec(1)+(i-1)*dX+1 RRec(2) dX-2 RRec(4)]);
  1195. H = [H,h];
  1196. end
  1197. %-Default button surrounding edit widget (if a DefStr given)
  1198. %-Callback sets hPrmpt UserData, and EditWidget string, to DefStr
  1199. % (Buttons UserData holds handles [hPrmpt,hEditWidget], set later)
  1200. cb = ['set(subsref(get(gcbo,''UserData''),substruct(''()'',{1})),',...
  1201. '''UserData'',get(gcbo,''String'')),',...
  1202. 'set(subsref(get(gcbo,''UserData''),substruct(''()'',{2})),',...
  1203. '''String'',get(gcbo,''String''))'];
  1204. if ~isempty(DefStr)
  1205. hDef = uicontrol(Finter,'Style','PushButton',...
  1206. 'String',DefStr,...
  1207. 'ToolTipString',['Click on border to accept ',...
  1208. 'default: ' DefStr],...
  1209. 'Tag',Tag,...
  1210. 'UserData',[],...
  1211. 'CallBack',cb,...
  1212. 'BackgroundColor',COLOUR,...
  1213. 'Position',...
  1214. [RRec(1)+RRec(3)*(2/3) RRec(2)-2 RRec(3)/3+2 RRec(4)+4]);
  1215. H = [H,hDef];
  1216. else
  1217. hDef = [];
  1218. end
  1219. %-Edit widget: Callback puts string into hPrompts UserData
  1220. cb = ['set(get(gcbo,''UserData''),''UserData'',get(gcbo,''String''))'];
  1221. h = uicontrol(Finter,'Style','Edit',...
  1222. 'String',DefStr,...
  1223. 'ToolTipString',str,...
  1224. 'Tag',Tag,...
  1225. 'UserData',hPrmpt,...
  1226. 'CallBack',cb,...
  1227. 'Horizontalalignment','Center',...
  1228. 'BackgroundColor','w',...
  1229. 'Position',...
  1230. [RRec(1)+RRec(3)*(2/3)+2 RRec(2) RRec(3)/3-2 RRec(4)]);
  1231. set(hDef,'UserData',[hPrmpt,h])
  1232. uifocus(h);
  1233. H = [H,h];
  1234. %-Figure ContextMenu for shortcuts
  1235. hM = spm_input('!InptConMen',Finter,[hPrmpt,H]);
  1236. %-Bring window to fore & jump pointer to default button
  1237. [PLoc,cF] = spm_input('!PointerJump',RRec,Finter,RRec(3)*0.95);
  1238. %-Setup FigureKeyPressFcn for editing of entry widget without clicking
  1239. set(Finter,'KeyPressFcn',[...
  1240. 'spm_input(''!EditableKeyPressFcn'',',...
  1241. 'findobj(gcf,''Tag'',''GUIinput_',int2str(YPos),''',',...
  1242. '''Style'',''edit''),',...
  1243. 'get(gcbf,''CurrentCharacter''))'])
  1244. %-Wait for button press, process results
  1245. %---------------------------------------------------------------
  1246. waitfor(hPrmpt,'UserData')
  1247. if ~ishandle(hPrmpt), error(['Input objects cleared whilst waiting ',...
  1248. 'for response: Bailing out!']), end
  1249. p = get(hPrmpt,'UserData');
  1250. if ~ischar(p)
  1251. k = p;
  1252. p = Values(k,:); if ischar(p), p=deblank(p); end
  1253. else
  1254. Labels = strvcat(Labels,'specify...');
  1255. k = size(Labels,1);
  1256. [p,msg] = sf_eEval(p,Type(2),1,m);
  1257. while ischar(p)
  1258. set(H,'Visible','off')
  1259. h = uicontrol('Style','Text','String',msg,...
  1260. 'Horizontalalignment','Center',...
  1261. 'ForegroundColor','r',...
  1262. 'BackgroundColor',COLOUR,...
  1263. 'Tag',Tag,'Position',RRec);
  1264. spm('Beep')
  1265. pause(2), delete(h), set(H,'Visible','on')
  1266. set(hPrmpt,'UserData','')
  1267. waitfor(hPrmpt,'UserData')
  1268. if ~ishandle(hPrmpt), error(['Input objects cleared ',...
  1269. 'whilst waiting for response: Bailing out!']),end
  1270. p = get(hPrmpt,'UserData');
  1271. if ischar(p), [p,msg] = sf_eEval(p,Type(2),1,m); end
  1272. end
  1273. end
  1274. %-Clean up
  1275. delete([H,hM]), set(Finter,'KeyPressFcn','')
  1276. spm_input('!PointerJumpBack',PLoc,cF)
  1277. %-Display answer
  1278. uicontrol(Finter,'Style','Text',...
  1279. 'String',num2str(p),...
  1280. 'Tag',Tag,...
  1281. 'Horizontalalignment','Center',...
  1282. 'BackgroundColor',COLOUR,...
  1283. 'Position',RRec);
  1284. drawnow
  1285. end % (if CmdLine)
  1286. case 'm' %-Process menu type
  1287. %=======================================================================
  1288. nLabels = size(Labels,1);
  1289. if ~isempty(DefItem) && ~any(DefItem==[1:nLabels]), DefItem=[]; end
  1290. %-Process pull down menu type
  1291. if CmdLine
  1292. spm_input('!PrntPrmpt',Prompt)
  1293. nLabels = size(Labels,1);
  1294. for i = 1:nLabels, fprintf('\t%2d : %s\n',i,Labels(i,:)), end
  1295. Prmpt = ['Menu choice (1-',int2str(nLabels),')'];
  1296. if ~isempty(DefItem)
  1297. Prmpt=[Prmpt,' (Default: ',num2str(DefItem),')'];
  1298. end
  1299. %-Ask for user response
  1300. %-------------------------------------------------------
  1301. if nLabels==1
  1302. %-Only one choice - auto-pick & display
  1303. k = 1;
  1304. fprintf('Menu choice: 1 - %s\t(only option)',Labels)
  1305. else
  1306. k = input([Prmpt,' ? ']);
  1307. if ~isempty(DefItem) && isempty(k), k=DefItem; end
  1308. while isempty(k) || ~any([1:nLabels]==k)
  1309. if ~isempty(k),fprintf('%c\t!Out of range\n',7),end
  1310. k = input([Prmpt,' ? ']);
  1311. if ~isempty(DefItem) && isempty(k), k=DefItem; end
  1312. end
  1313. end
  1314. fprintf('\n')
  1315. else
  1316. Tag = ['GUIinput_',int2str(YPos)]; %-Tag for widgets
  1317. if nLabels==1
  1318. %-Only one choice - auto-pick
  1319. k = 1;
  1320. else
  1321. Labs=[repmat(' ',nLabels,2),Labels];
  1322. if ~isempty(DefItem)
  1323. Labs(DefItem,1)='*';
  1324. H = uicontrol(Finter,'Style','Frame',...
  1325. 'BackGroundColor','k',...
  1326. 'ForeGroundColor','k',...
  1327. 'Position',QRec+[-1,-1,+2,+2]);
  1328. else
  1329. H = [];
  1330. end
  1331. cb = ['if (get(gcbo,''Value'')>1),',...
  1332. 'set(gcbo,''UserData'',''Selected''), end'];
  1333. hPopUp = uicontrol(Finter,'Style','popupmenu',...
  1334. 'HorizontalAlignment','Left',...
  1335. 'ForegroundColor','k',...
  1336. 'BackgroundColor',COLOUR,...
  1337. 'String',strvcat([Prompt,'...'],Labs),...
  1338. 'Tag',Tag,...
  1339. 'UserData',DefItem,...
  1340. 'CallBack',cb,...
  1341. 'Position',QRec);
  1342. if TTips
  1343. cLabs = cellstr(Labels);
  1344. cInd = num2cell(1:nLabels);
  1345. scLabs = [cInd; cLabs'];
  1346. scLabs = sprintf('%d: %s\n',scLabs{:});
  1347. set(hPopUp,'ToolTipString',sprintf(['select with ',...
  1348. 'mouse or type option number (1-',...
  1349. num2str(nLabels),') & press return\n%s'],scLabs));
  1350. end
  1351. %-Figure ContextMenu for shortcuts
  1352. hM = spm_input('!InptConMen',Finter,[hPopUp,H]);
  1353. %-Bring window to fore & jump pointer to menu widget
  1354. [PLoc,cF] = spm_input('!PointerJump',RRec,Finter);
  1355. %-Callback for KeyPresses
  1356. cb=['spm_input(''!PullDownKeyPressFcn'',',...
  1357. 'findobj(gcf,''Tag'',''',Tag,'''),',...
  1358. 'get(gcf,''CurrentCharacter''))'];
  1359. set(Finter,'KeyPressFcn',cb)
  1360. %-Wait for menu selection
  1361. %-----------------------------------------------
  1362. waitfor(hPopUp,'UserData')
  1363. if ~ishandle(hPopUp), error(['Input object cleared ',...
  1364. 'whilst waiting for response: Bailing out!']),end
  1365. k = get(hPopUp,'Value')-1;
  1366. %-Clean up
  1367. delete([H,hM]), set(Finter,'KeyPressFcn','')
  1368. set(hPopUp,'Style','Text',...
  1369. 'Horizontalalignment','Center',...
  1370. 'String',deblank(Labels(k,:)),...
  1371. 'BackgroundColor',COLOUR)
  1372. spm_input('!PointerJumpBack',PLoc,cF)
  1373. end
  1374. %-Display answer
  1375. uicontrol(Finter,'Style','Text',...
  1376. 'String',deblank(Labels(k,:)),...
  1377. 'Tag',Tag,...
  1378. 'Horizontalalignment','Center',...
  1379. 'BackgroundColor',COLOUR,...
  1380. 'Position',QRec);
  1381. drawnow
  1382. end
  1383. p = Values(k,:); if ischar(p), p=deblank(p); end
  1384. otherwise, error('unrecognised type')
  1385. end % (switch lower(Type) within case {'b','b|','y/n'})
  1386. %-Return response
  1387. %-----------------------------------------------------------------------
  1388. varargout = {p,YPos};
  1389. case {'m!','b!'} %-GUI PullDown/Buttons utility
  1390. %=======================================================================
  1391. % H = spm_input(Prompt,YPos,'p',Labels,cb,UD,XCB)
  1392. %-Condition arguments
  1393. if nargin<7, XCB = 0; else XCB = varargin{7}; end
  1394. if nargin<6, UD = []; else UD = varargin{6}; end
  1395. if nargin<5, cb = ''; else cb = varargin{5}; end
  1396. if nargin<4, Labels = []; else Labels = varargin{4}; end
  1397. if CmdLine, error('Can''t do CmdLine GUI utilities!'), end
  1398. if isempty(cb), cb = 'disp(''(CallBack not set)'')'; end
  1399. if ischar(cb), cb = cellstr(cb); end
  1400. if length(cb)>1 && strcmpi(Type,'m!'), XCB=1; end
  1401. if iscellstr(Labels), Labels=char(Labels); end
  1402. %-Convert Labels "option" string to string matrix if required
  1403. if any(Labels=='|')
  1404. OptStr=Labels;
  1405. BarPos=find([OptStr=='|',1]);
  1406. Labels=OptStr(1:BarPos(1)-1);
  1407. for Bar = 2:sum(OptStr=='|')+1
  1408. Labels=strvcat(Labels,OptStr(BarPos(Bar-1)+1:BarPos(Bar)-1));
  1409. end
  1410. end
  1411. %-Check #CallBacks
  1412. if ~( length(cb)==1 || (length(cb)==size(Labels,1)) )
  1413. error('Labels & Callbacks size mismatch'), end
  1414. %-Draw Prompt
  1415. %-----------------------------------------------------------------------
  1416. Tag = ['GUIinput_',int2str(YPos)]; %-Tag for widgets
  1417. if ~isempty(Prompt)
  1418. uicontrol(Finter,'Style','Text',...
  1419. 'String',Prompt,...
  1420. 'Tag',Tag,...
  1421. 'HorizontalAlignment','Right',...
  1422. 'BackgroundColor',COLOUR,...
  1423. 'Position',PRec)
  1424. Rec = RRec;
  1425. else
  1426. Rec = QRec;
  1427. end
  1428. %-Sort out UserData for extended callbacks (handled by spm_input('!m_cb')
  1429. %-----------------------------------------------------------------------
  1430. if XCB, if iscell(UD), UD={UD}; end, UD = struct('UD',UD,'cb',{cb}); end
  1431. %-Draw PullDown or Buttons
  1432. %-----------------------------------------------------------------------
  1433. switch lower(Type), case 'm!'
  1434. if XCB, UD.cb=cb; cb = {'spm_input(''!m_cb'')'}; end
  1435. H = uicontrol(Finter,'Style','popupmenu',...
  1436. 'HorizontalAlignment','Left',...
  1437. 'ForegroundColor','k',...
  1438. 'BackgroundColor',COLOUR,...
  1439. 'String',Labels,...
  1440. 'Tag',Tag,...
  1441. 'UserData',UD,...
  1442. 'CallBack',char(cb),...
  1443. 'Position',Rec);
  1444. case 'b!'
  1445. nLabels = size(Labels,1);
  1446. dX = Rec(3)/nLabels;
  1447. H = [];
  1448. for i=1:nLabels
  1449. if length(cb)>1, tcb=cb(i); else tcb=cb; end
  1450. if XCB, UD.cb=tcb; tcb = {'spm_input(''!m_cb'')'}; end
  1451. h = uicontrol(Finter,'Style','Pushbutton',...
  1452. 'String',deblank(Labels(i,:)),...
  1453. 'ToolTipString','',...
  1454. 'Tag',Tag,...
  1455. 'UserData',UD,...
  1456. 'BackgroundColor',COLOUR,...
  1457. 'Callback',char(tcb),...
  1458. 'Position',[Rec(1)+(i-1)*dX+1 ...
  1459. Rec(2) dX-2 Rec(4)]);
  1460. H = [H,h];
  1461. end
  1462. end
  1463. %-Bring window to fore & jump pointer to menu widget
  1464. [PLoc,cF] = spm_input('!PointerJump',RRec,Finter);
  1465. varargout = {H};
  1466. case {'d','d!'} %-Display message
  1467. %=======================================================================
  1468. %-Condition arguments
  1469. if nargin<4, Label=''; else Label=varargin{4}; end
  1470. if CmdLine && strcmpi(Type,'d')
  1471. fprintf('\n +-%s%s+',Label,repmat('-',1,57-length(Label)))
  1472. Prompt = [Prompt,' '];
  1473. while ~isempty(Prompt)
  1474. tmp = length(Prompt);
  1475. if tmp>56, tmp=min([max(find(Prompt(1:56)==' ')),56]); end
  1476. fprintf('\n | %s%s |',Prompt(1:tmp),repmat(' ',1,56-tmp))
  1477. Prompt(1:tmp)=[];
  1478. end
  1479. fprintf('\n +-%s+\n',repmat('-',1,57))
  1480. elseif ~CmdLine
  1481. if ~isempty(Label), Prompt = [Label,': ',Prompt]; end
  1482. figure(Finter)
  1483. %-Create text axes and edit control objects
  1484. %---------------------------------------------------------------
  1485. h = uicontrol(Finter,'Style','Text',...
  1486. 'String',Prompt(1:min(length(Prompt),56)),...
  1487. 'FontWeight','bold',...
  1488. 'Tag',['GUIinput_',int2str(YPos)],...
  1489. 'HorizontalAlignment','Left',...
  1490. 'ForegroundColor','k',...
  1491. 'BackgroundColor',COLOUR,...
  1492. 'UserData',Prompt,...
  1493. 'Position',QRec);
  1494. if length(Prompt)>56
  1495. pause(1)
  1496. set(h,'ToolTipString',Prompt)
  1497. spm_input('!dScroll',h)
  1498. uicontrol(Finter,'Style','PushButton','String','>',...
  1499. 'ToolTipString','press to scroll message',...
  1500. 'Tag',['GUIinput_',int2str(YPos)],...
  1501. 'UserData',h,...
  1502. 'CallBack',[...
  1503. 'set(gcbo,''Visible'',''off''),',...
  1504. 'spm_input(''!dScroll'',get(gcbo,''UserData'')),',...
  1505. 'set(gcbo,''Visible'',''on'')'],...
  1506. 'BackgroundColor',COLOUR,...
  1507. 'Position',[QRec(1)+QRec(3)-10,QRec(2),15,QRec(4)]);
  1508. end
  1509. end
  1510. if nargout>0, varargout={[],YPos}; end
  1511. %=======================================================================
  1512. % U T I L I T Y F U N C T I O N S
  1513. %=======================================================================
  1514. case '!colour'
  1515. %=======================================================================
  1516. % colour = spm_input('!Colour')
  1517. varargout = {COLOUR};
  1518. case '!icond'
  1519. %=======================================================================
  1520. % [iCond,msg] = spm_input('!iCond',str,n,m)
  1521. % Parse condition indicator spec strings:
  1522. % '2 3 2 3', '0 1 0 1', '2323', '0101', 'abab', 'R A R A'
  1523. if nargin<4, m=Inf; else m=varargin{4}; end
  1524. if nargin<3, n=NaN; else n=varargin{3}; end
  1525. if any(isnan(n(:)))
  1526. n=Inf;
  1527. elseif (length(n(:))==2 && ~any(n==1)) || length(n(:))>2
  1528. error('condition input can only do vectors')
  1529. end
  1530. if nargin<2, i=''; else i=varargin{2}; end
  1531. if isempty(i), varargout={[],'empty input'}; return, end
  1532. msg = ''; i=i(:)';
  1533. if ischar(i)
  1534. if i(1)=='0' && all(ismember(unique(i(:)),char(abs('0'):abs('9'))))
  1535. %-Leading zeros in a digit list
  1536. msg = sprintf('%s expanded',i);
  1537. z = min(find([diff(i=='0'),1]));
  1538. i = [zeros(1,z), spm_input('!iCond',i(z+1:end))'];
  1539. else
  1540. %-Try an eval, for functions & string #s
  1541. i = evalin('base',['[',i,']'],'i');
  1542. end
  1543. end
  1544. if ischar(i)
  1545. %-Evaluation error from above: see if it's an 'abab' or 'a b a b' type:
  1546. [c,null,i] = unique(lower(i(~isspace(i))));
  1547. if all(ismember(c,char(abs('a'):abs('z'))))
  1548. %-Map characters a-z to 1-26, but let 'r' be zero (rest)
  1549. tmp = c-'a'+1; tmp(tmp=='r'-'a'+1)=0;
  1550. i = tmp(i);
  1551. msg = [sprintf('[%s] mapped to [',c),...
  1552. sprintf('%d,',tmp(1:end-1)),...
  1553. sprintf('%d',tmp(end)),']'];
  1554. else
  1555. i = '!'; msg = 'evaluation error';
  1556. end
  1557. elseif ~all(floor(i(:))==i(:))
  1558. i = '!'; msg = 'must be integers';
  1559. elseif length(i)==1 && prod(n)>1
  1560. msg = sprintf('%d expanded',i);
  1561. i = floor(i./10.^[floor(log10(i)+eps):-1:0]);
  1562. i = i-[0,10*i(1:end-1)];
  1563. end
  1564. %-Check size of i & #conditions
  1565. if ~ischar(i), [i,msg] = sf_SzChk(i,n,msg); end
  1566. if ~ischar(i) && isfinite(m) && length(unique(i))~=m
  1567. i = '!'; msg = sprintf('%d conditions required',m);
  1568. end
  1569. varargout = {i,msg};
  1570. case '!inptconmen'
  1571. %=======================================================================
  1572. % hM = spm_input('!InptConMen',Finter,H)
  1573. if nargin<3, H=[]; else H=varargin{3}; end
  1574. if nargin<2, varargout={[]}; else Finter=varargin{2}; end
  1575. hM = uicontextmenu('Parent',Finter);
  1576. if ConCrash
  1577. uimenu(hM,'Label','crash out','Separator','on',...
  1578. 'CallBack','delete(get(gcbo,''UserData''))',...
  1579. 'UserData',[hM,H])
  1580. end
  1581. set(Finter,'UIContextMenu',hM)
  1582. varargout={hM};
  1583. case '!cmdline'
  1584. %=======================================================================
  1585. % [CmdLine,YPos] = spm_input('!CmdLine',YPos)
  1586. %-Sorts out whether to use CmdLine or not & canonicalises YPos
  1587. if nargin<2, YPos=''; else YPos=varargin{2}; end
  1588. if isempty(YPos), YPos='+1'; end
  1589. CmdLine = [];
  1590. %-Special YPos specifications
  1591. if ischar(YPos)
  1592. if(YPos(1)=='!'), CmdLine=0; YPos(1)=[]; end
  1593. elseif YPos==0
  1594. CmdLine=1;
  1595. elseif YPos<0
  1596. CmdLine=0;
  1597. YPos=-YPos;
  1598. end
  1599. CmdLine = spm('CmdLine',CmdLine);
  1600. if CmdLine, YPos=0; end
  1601. varargout = {CmdLine,YPos};
  1602. case '!getwin'
  1603. %=======================================================================
  1604. % Finter = spm_input('!GetWin',F)
  1605. %-Locate (or create) figure to work in (Don't use 'Tag'ged figs)
  1606. if nargin<2, F='Interactive'; else F=varargin{2}; end
  1607. Finter = spm_figure('FindWin',F);
  1608. if isempty(Finter)
  1609. if ~isempty(get(0,'Children'))
  1610. if isempty(get(gcf,'Tag')), Finter = gcf;
  1611. else Finter = spm('CreateIntWin'); end
  1612. else
  1613. Finter = spm('CreateIntWin');
  1614. end
  1615. end
  1616. varargout = {Finter};
  1617. case '!pointerjump'
  1618. %=======================================================================
  1619. % [PLoc,cF] = spm_input('!PointerJump',RRec,F,XDisp)
  1620. %-Raise window & jump pointer over question
  1621. if nargin<4, XDisp=[]; else XDisp=varargin{4}; end
  1622. if nargin<3, F='Interactive'; else F=varargin{3}; end
  1623. if nargin<2, error('Insufficient arguments'), else RRec=varargin{2}; end
  1624. F = spm_figure('FindWin',F);
  1625. PLoc = get(0,'PointerLocation');
  1626. cF = get(0,'CurrentFigure');
  1627. if ~isempty(F)
  1628. figure(F)
  1629. FRec = get(F,'Position');
  1630. if isempty(XDisp), XDisp=RRec(3)*4/5; end
  1631. if PJump, set(0,'PointerLocation',...
  1632. floor([(FRec(1)+RRec(1)+XDisp), (FRec(2)+RRec(2)+RRec(4)/3)]));
  1633. end
  1634. end
  1635. varargout = {PLoc,cF};
  1636. case '!pointerjumpback'
  1637. %=======================================================================
  1638. % spm_input('!PointerJumpBack',PLoc,cF)
  1639. %-Replace pointer and reset CurrentFigure back
  1640. if nargin<4, cF=[]; else F=varargin{3}; end
  1641. if nargin<2, error('Insufficient arguments'), else PLoc=varargin{2}; end
  1642. if PJump, set(0,'PointerLocation',PLoc), end
  1643. cF = spm_figure('FindWin',cF);
  1644. if ~isempty(cF), set(0,'CurrentFigure',cF); end
  1645. case '!prntprmpt'
  1646. %=======================================================================
  1647. % spm_input('!PrntPrmpt',Prompt,TipStr,Title)
  1648. %-Print prompt for CmdLine questioning
  1649. if nargin<4, Title = ''; else Title = varargin{4}; end
  1650. if nargin<3, TipStr = ''; else TipStr = varargin{3}; end
  1651. if nargin<2, Prompt = ''; else Prompt = varargin{2}; end
  1652. if isempty(Prompt), Prompt='Enter an expression'; end
  1653. Prompt = cellstr(Prompt);
  1654. if ~isempty(TipStr)
  1655. tmp = 8 + length(Prompt{end}) + length(TipStr);
  1656. if tmp < 62
  1657. TipStr = sprintf('%s(%s)',repmat(' ',1,70-tmp),TipStr);
  1658. else
  1659. TipStr = sprintf('\n%s(%s)',repmat(' ',1,max(0,70-length(TipStr))),TipStr);
  1660. end
  1661. end
  1662. if isempty(Title)
  1663. fprintf('\n%s\n',repmat('~',1,72))
  1664. else
  1665. fprintf('\n= %s %s\n',Title,repmat('~',1,72-length(Title)-3))
  1666. end
  1667. fprintf('\t%s',Prompt{1})
  1668. for i=2:numel(Prompt), fprintf('\n\t%s',Prompt{i}), end
  1669. fprintf('%s\n%s\n',TipStr,repmat('~',1,72))
  1670. case '!inputrects'
  1671. %=======================================================================
  1672. % [Frec,QRec,PRec,RRec,Sz,Se] = spm_input('!InputRects',YPos,rec,F)
  1673. if nargin<4, F='Interactive'; else F=varargin{4}; end
  1674. if nargin<3, rec=''; else rec=varargin{3}; end
  1675. if nargin<2, YPos=1; else YPos=varargin{2}; end
  1676. F = spm_figure('FindWin',F);
  1677. if isempty(F), error('Figure not found'), end
  1678. Units = get(F,'Units');
  1679. set(F,'Units','pixels')
  1680. FRec = get(F,'Position');
  1681. set(F,'Units',Units);
  1682. Xdim = FRec(3); Ydim = FRec(4);
  1683. WS = spm('WinScale');
  1684. Sz = round(22*min(WS)); %-Height
  1685. Pd = Sz/2; %-Pad
  1686. Se = 2*round(25*min(WS)/2); %-Seperation
  1687. Yo = round(2*min(WS)); %-Y offset for responses
  1688. a = 5.5/10;
  1689. y = Ydim - Se*YPos;
  1690. QRec = [Pd y Xdim-2*Pd Sz]; %-Question
  1691. PRec = [Pd y floor(a*Xdim)-2*Pd Sz]; %-Prompt
  1692. RRec = [ceil(a*Xdim) y+Yo floor((1-a)*Xdim)-Pd Sz]; %-Response
  1693. % MRec = [010 y Xdim-50 Sz]; %-Menu PullDown
  1694. % BRec = MRec + [Xdim-50+1, 0+1, 50-Xdim+30, 0]; %-Menu PullDown OK butt
  1695. if ~isempty(rec)
  1696. varargout = {eval(rec)};
  1697. else
  1698. varargout = {FRec,QRec,PRec,RRec,Sz,Se};
  1699. end
  1700. case '!deleteinputobj'
  1701. %=======================================================================
  1702. % spm_input('!DeleteInputObj',F)
  1703. if nargin<2, F='Interactive'; else F=varargin{2}; end
  1704. h = spm_input('!FindInputObj',F);
  1705. delete(h(h>0))
  1706. case {'!currentpos','!findinputobj'}
  1707. %=======================================================================
  1708. % [CPos,hCPos] = spm_input('!CurrentPos',F)
  1709. % h = spm_input('!FindInputObj',F)
  1710. % hPos contains handles: Columns contain handles corresponding to Pos
  1711. if nargin<2, F='Interactive'; else F=varargin{2}; end
  1712. F = spm_figure('FindWin',F);
  1713. %-Find tags and YPos positions of 'GUIinput_' 'Tag'ged objects
  1714. H = [];
  1715. YPos = [];
  1716. for h = get(F,'Children')'
  1717. tmp = get(h,'Tag');
  1718. if ~isempty(tmp)
  1719. if strcmp(tmp(1:min(length(tmp),9)),'GUIinput_')
  1720. H = [H, h];
  1721. YPos = [YPos, eval(tmp(10:end))];
  1722. end
  1723. end
  1724. end
  1725. switch lower(Type), case '!findinputobj'
  1726. varargout = {H};
  1727. case '!currentpos'
  1728. if nargout<2
  1729. varargout = {max(YPos),[]};
  1730. elseif isempty(H)
  1731. varargout = {[],[]};
  1732. else
  1733. %-Sort out
  1734. tmp = sort(YPos);
  1735. CPos = tmp(find([1,diff(tmp)]));
  1736. nPos = length(CPos);
  1737. nPerPos = diff(find([1,diff(tmp),1]));
  1738. hCPos = zeros(max(nPerPos),nPos);
  1739. for i = 1:nPos
  1740. hCPos(1:nPerPos(i),i) = H(YPos==CPos(i))';
  1741. end
  1742. varargout = {CPos,hCPos};
  1743. end
  1744. end
  1745. case '!nextpos'
  1746. %=======================================================================
  1747. % [NPos,CPos,hCPos] = spm_input('!NextPos',YPos,F,CmdLine)
  1748. %-Return next position to use
  1749. if nargin<3, F='Interactive'; else F=varargin{3}; end
  1750. if nargin<2, YPos='+1'; else YPos=varargin{2}; end
  1751. if nargin<4, [CmdLine,YPos]=spm_input('!CmdLine',YPos);
  1752. else CmdLine=varargin{4}; end
  1753. F = spm_figure('FindWin',F);
  1754. %-Get current positions
  1755. if nargout<3
  1756. CPos = spm_input('!CurrentPos',F);
  1757. hCPos = [];
  1758. else
  1759. [CPos,hCPos] = spm_input('!CurrentPos',F);
  1760. end
  1761. if CmdLine
  1762. NPos = 0;
  1763. else
  1764. MPos = spm_input('!MaxPos',F);
  1765. if ischar(YPos)
  1766. %-Relative YPos
  1767. %-Strip any '!' prefix from YPos
  1768. if(YPos(1)=='!'), YPos(1)=[]; end
  1769. if strncmp(YPos,'_',1)
  1770. %-YPos='_' means bottom
  1771. YPos=eval(['MPos+',YPos(2:end)],'MPos');
  1772. else
  1773. YPos = max([0,CPos])+eval(YPos);
  1774. end
  1775. else
  1776. %-Absolute YPos
  1777. YPos=abs(YPos);
  1778. end
  1779. NPos = min(max(1,YPos),MPos);
  1780. end
  1781. varargout = {NPos,CPos,hCPos};
  1782. case '!setnextpos'
  1783. %=======================================================================
  1784. % NPos = spm_input('!SetNextPos',YPos,F,CmdLine)
  1785. %-Set next position to use
  1786. if nargin<3, F='Interactive'; else F=varargin{3}; end
  1787. if nargin<2, YPos='+1'; else YPos=varargin{2}; end
  1788. if nargin<4, [CmdLine,YPos]=spm_input('!CmdLine',YPos);
  1789. else CmdLine=varargin{4}; end
  1790. %-Find out which Y-position to use
  1791. [NPos,CPos,hCPos] = spm_input('!NextPos',YPos,F,CmdLine);
  1792. %-Delete any previous inputs using positions NPos and after
  1793. if any(CPos>=NPos), h=hCPos(:,CPos>=NPos); delete(h(h>0)), end
  1794. varargout = {NPos};
  1795. case '!maxpos'
  1796. %=======================================================================
  1797. % MPos = spm_input('!MaxPos',F,FRec3)
  1798. %
  1799. if nargin<3
  1800. if nargin<2, F='Interactive'; else F=varargin{2}; end
  1801. F = spm_figure('FindWin',F);
  1802. if isempty(F)
  1803. FRec3=spm('WinSize','Interactive')*[0;0;0;1];
  1804. else
  1805. %-Get figure size
  1806. Units = get(F,'Units');
  1807. set(F,'Units','pixels')
  1808. FRec3 = get(F,'Position')*[0;0;0;1];
  1809. set(F,'Units',Units);
  1810. end
  1811. end
  1812. Se = round(25*min(spm('WinScale')));
  1813. MPos = floor((FRec3-5)/Se);
  1814. varargout = {MPos};
  1815. case '!editablekeypressfcn'
  1816. %=======================================================================
  1817. % spm_input('!EditableKeyPressFcn',h,ch,hPrmpt)
  1818. if nargin<2, error('Insufficient arguments'), else h=varargin{2}; end
  1819. if isempty(h), set(gcbf,'KeyPressFcn','','UserData',[]), return, end
  1820. if nargin<3, ch=get(get(h,'Parent'),'CurrentCharacter'); else ch=varargin{3};end
  1821. if nargin<4, hPrmpt=get(h,'UserData'); else hPrmpt=varargin{4}; end
  1822. tmp = get(h,'String');
  1823. if isempty(tmp), tmp=''; end
  1824. if iscellstr(tmp) && length(tmp)==1; tmp=tmp{:}; end
  1825. if isempty(ch) %- shift / control / &c. pressed
  1826. return
  1827. elseif any(abs(ch)==[32:126]) %-Character
  1828. if iscellstr(tmp), return, end
  1829. tmp = [tmp, ch];
  1830. elseif abs(ch)==21 %- ^U - kill
  1831. tmp = '';
  1832. elseif any(abs(ch)==[8,127]) %-BackSpace or Delete
  1833. if iscellstr(tmp), return, end
  1834. if ~isempty(tmp), tmp(length(tmp))=''; end
  1835. elseif abs(ch)==13 %-Return pressed
  1836. if ~isempty(tmp)
  1837. set(hPrmpt,'UserData',get(h,'String'))
  1838. end
  1839. return
  1840. else
  1841. %-Illegal character
  1842. return
  1843. end
  1844. set(h,'String',tmp)
  1845. case '!buttonkeypressfcn'
  1846. %=======================================================================
  1847. % spm_input('!ButtonKeyPressFcn',h,Keys,DefItem,ch)
  1848. %-Callback for KeyPress, to store valid button # in UserData of Prompt,
  1849. % DefItem if (DefItem~=0) & return (ASCII-13) is pressed
  1850. %-Condition arguments
  1851. if nargin<2, error('Insufficient arguments'), else h=varargin{2}; end
  1852. if isempty(h), set(gcf,'KeyPressFcn','','UserData',[]), return, end
  1853. if nargin<3, error('Insufficient arguments'); else Keys=varargin{3}; end
  1854. if nargin<4, DefItem=0; else DefItem=varargin{4}; end
  1855. if nargin<5, ch=get(gcf,'CurrentCharacter'); else ch=varargin{5}; end
  1856. if isempty(ch)
  1857. %- shift / control / &c. pressed
  1858. return
  1859. elseif (DefItem && ch==13)
  1860. But = DefItem;
  1861. else
  1862. But = find(lower(ch)==lower(Keys));
  1863. end
  1864. if ~isempty(But), set(h,'UserData',But), end
  1865. case '!pulldownkeypressfcn'
  1866. %=======================================================================
  1867. % spm_input('!PullDownKeyPressFcn',h,ch,DefItem)
  1868. if nargin<2, error('Insufficient arguments'), else h=varargin{2}; end
  1869. if isempty(h), set(gcf,'KeyPressFcn',''), return, end
  1870. if nargin<3, ch=get(get(h,'Parent'),'CurrentCharacter'); else ch=varargin{3};end
  1871. if nargin<4, DefItem=get(h,'UserData'); else ch=varargin{4}; end
  1872. Pmax = get(h,'Max');
  1873. Pval = get(h,'Value');
  1874. if Pmax==1, return, end
  1875. if isempty(ch)
  1876. %- shift / control / &c. pressed
  1877. return
  1878. elseif abs(ch)==13
  1879. if Pval==1
  1880. if DefItem, set(h,'Value',max(2,min(DefItem+1,Pmax))), end
  1881. else
  1882. set(h,'UserData','Selected')
  1883. end
  1884. elseif any(ch=='bpu')
  1885. %-Move "b"ack "u"p to "p"revious entry
  1886. set(h,'Value',max(2,Pval-1))
  1887. elseif any(ch=='fnd')
  1888. %-Move "f"orward "d"own to "n"ext entry
  1889. set(h,'Value',min(Pval+1,Pmax))
  1890. elseif any(ch=='123456789')
  1891. %-Move to entry n
  1892. set(h,'Value',max(2,min(eval(ch)+1,Pmax)))
  1893. else
  1894. %-Illegal character
  1895. end
  1896. case '!m_cb' %-CallBack handler for extended CallBack 'p'ullDown type
  1897. %=======================================================================
  1898. % spm_input('!m_cb')
  1899. %-Get PopUp handle and value
  1900. h = gcbo;
  1901. n = get(h,'Value');
  1902. %-Get PopUp's UserData, check cb and UD fields exist, extract cb & UD
  1903. tmp = get(h,'UserData');
  1904. if ~(isfield(tmp,'cb') && isfield(tmp,'UD'))
  1905. error('Invalid UserData structure for spm_input extended callback')
  1906. end
  1907. cb = tmp.cb;
  1908. UD = tmp.UD;
  1909. %-Evaluate appropriate CallBack string (ignoring any return arguments)
  1910. % NB: Using varargout={eval(cb{n})}; gives an error if the CallBack
  1911. % has no return arguments!
  1912. if length(cb)==1, eval(char(cb)); else eval(cb{n}); end
  1913. case '!dscroll'
  1914. %=======================================================================
  1915. % spm_input('!dScroll',h,Prompt)
  1916. %-Scroll text in object h
  1917. if nargin<2, return, else h=varargin{2}; end
  1918. if nargin<3, Prompt = get(h,'UserData'); else Prompt=varargin{3}; end
  1919. tmp = Prompt;
  1920. if length(Prompt)>56
  1921. while length(tmp)>56
  1922. tic, while(toc<0.1), pause(0.05), end
  1923. tmp(1)=[];
  1924. set(h,'String',tmp(1:min(length(tmp),56)))
  1925. end
  1926. pause(1)
  1927. set(h,'String',Prompt(1:min(length(Prompt),56)))
  1928. end
  1929. otherwise
  1930. %=======================================================================
  1931. error(['Invalid type/action: ',Type])
  1932. %=======================================================================
  1933. end % (case lower(Type))
  1934. %=======================================================================
  1935. %- S U B - F U N C T I O N S
  1936. %=======================================================================
  1937. function [Keys,Labs] = sf_labkeys(Labels)
  1938. %=======================================================================
  1939. %-Make unique character keys for the Labels, ignoring case
  1940. if nargin<1, error('insufficient arguments'), end
  1941. if iscellstr(Labels), Labels = char(Labels); end
  1942. if isempty(Labels), Keys=''; Labs=''; return, end
  1943. Keys=Labels(:,1)';
  1944. nLabels = size(Labels,1);
  1945. if any(~diff(abs(sort(lower(Keys)))))
  1946. if nLabels<10
  1947. Keys = sprintf('%d',[1:nLabels]);
  1948. elseif nLabels<=26
  1949. Keys = sprintf('%c',abs('a')+[0:nLabels-1]);
  1950. else
  1951. error('Too many buttons!')
  1952. end
  1953. Labs = Labels;
  1954. else
  1955. Labs = Labels(:,2:end);
  1956. end
  1957. function [p,msg] = sf_eEval(str,Type,n,m)
  1958. %=======================================================================
  1959. %-Evaluation and error trapping of typed input
  1960. if nargin<4, m=[]; end
  1961. if nargin<3, n=[]; end
  1962. if nargin<2, Type='e'; end
  1963. if nargin<1, str=''; end
  1964. if isempty(str), p='!'; msg='empty input'; return, end
  1965. switch lower(Type)
  1966. case 's'
  1967. p = str; msg = '';
  1968. case 'e'
  1969. p = evalin('base',['[',str,']'],'''!''');
  1970. if ischar(p)
  1971. msg = 'evaluation error';
  1972. else
  1973. [p,msg] = sf_SzChk(p,n);
  1974. end
  1975. case 'n'
  1976. p = evalin('base',['[',str,']'],'''!''');
  1977. if ischar(p)
  1978. msg = 'evaluation error';
  1979. elseif any(floor(p(:))~=p(:)|p(:)<1)||~isreal(p)
  1980. p='!'; msg='natural number(s) required';
  1981. elseif ~isempty(m) && any(p(:)>m)
  1982. p='!'; msg=['max value is ',num2str(m)];
  1983. else
  1984. [p,msg] = sf_SzChk(p,n);
  1985. end
  1986. case 'w'
  1987. p = evalin('base',['[',str,']'],'''!''');
  1988. if ischar(p)
  1989. msg = 'evaluation error';
  1990. elseif any(floor(p(:))~=p(:)|p(:)<0)||~isreal(p)
  1991. p='!'; msg='whole number(s) required';
  1992. elseif ~isempty(m) && any(p(:)>m)
  1993. p='!'; msg=['max value is ',num2str(m)];
  1994. else
  1995. [p,msg] = sf_SzChk(p,n);
  1996. end
  1997. case 'i'
  1998. p = evalin('base',['[',str,']'],'''!''');
  1999. if ischar(p)
  2000. msg = 'evaluation error';
  2001. elseif any(floor(p(:))~=p(:))||~isreal(p)
  2002. p='!'; msg='integer(s) required';
  2003. else
  2004. [p,msg] = sf_SzChk(p,n);
  2005. end
  2006. case 'p'
  2007. p = evalin('base',['[',str,']'],'''!''');
  2008. if ischar(p)
  2009. msg = 'evaluation error';
  2010. elseif ~isempty(setxor(p(:)',m))
  2011. p='!'; msg='invalid permutation';
  2012. else
  2013. [p,msg] = sf_SzChk(p,n);
  2014. end
  2015. case 'r'
  2016. p = evalin('base',['[',str,']'],'''!''');
  2017. if ischar(p)
  2018. msg = 'evaluation error';
  2019. elseif ~isreal(p)
  2020. p='!'; msg='real number(s) required';
  2021. elseif ~isempty(m) && ( max(p)>max(m) || min(p)<min(m) )
  2022. p='!'; msg=sprintf('real(s) in [%g,%g] required',min(m),max(m));
  2023. else
  2024. [p,msg] = sf_SzChk(p,n);
  2025. end
  2026. case 'c'
  2027. if isempty(m), m=Inf; end
  2028. [p,msg] = spm_input('!iCond',str,n,m);
  2029. case 'x'
  2030. X = m; %-Design matrix/space-structure
  2031. if isempty(n), n=1; end
  2032. %-Sort out contrast matrix dimensions (contrast vectors in rows)
  2033. if length(n)==1, n=[n,Inf]; else n=reshape(n(1:2),1,2); end
  2034. if ~isempty(X) % - override n(2) w/ design column dimension
  2035. n(2) = spm_SpUtil('size',X,2);
  2036. end
  2037. p = evalin('base',['[',str,']'],'''!''');
  2038. if ischar(p)
  2039. msg = 'evaluation error';
  2040. else
  2041. if isfinite(n(2)) && size(p,2)<n(2)
  2042. tmp = n(2) -size(p,2);
  2043. p = [p, zeros(size(p,1),tmp)];
  2044. if size(p,1)>1, str=' columns'; else str='s'; end
  2045. msg = sprintf('right padded with %d zero%s',tmp,str);
  2046. else
  2047. msg = '';
  2048. end
  2049. if size(p,2)>n(2)
  2050. p='!'; msg=sprintf('too long - only %d prams',n(2));
  2051. elseif isfinite(n(1)) && size(p,1)~=n(1)
  2052. p='!';
  2053. if n(1)==1, msg='vector required';
  2054. else msg=sprintf('%d contrasts required',n(1)); end
  2055. elseif ~isempty(X) && ~spm_SpUtil('allCon',X,p')
  2056. p='!'; msg='invalid contrast';
  2057. end
  2058. end
  2059. otherwise
  2060. error('unrecognised type');
  2061. end
  2062. function str = sf_SzStr(n,l)
  2063. %=======================================================================
  2064. %-Size info string construction
  2065. if nargin<2, l=0; else l=1; end
  2066. if nargin<1, error('insufficient arguments'), end
  2067. if isempty(n), n=NaN; end
  2068. n=n(:); if length(n)==1, n=[n,1]; end, dn=length(n);
  2069. if any(isnan(n)) || (prod(n)==1 && dn<=2) || (dn==2 && min(n)==1 && isinf(max(n)))
  2070. str = ''; lstr = '';
  2071. elseif dn==2 && min(n)==1
  2072. str = sprintf('[%d]',max(n)); lstr = [str,'-vector'];
  2073. elseif dn==2 && sum(isinf(n))==1
  2074. str = sprintf('[%d]',min(n)); lstr = [str,'-vector(s)'];
  2075. else
  2076. str='';
  2077. for i = 1:dn
  2078. if isfinite(n(i)), str = sprintf('%s,%d',str,n(i));
  2079. else str = sprintf('%s,*',str); end
  2080. end
  2081. str = ['[',str(2:end),']']; lstr = [str,'-matrix'];
  2082. end
  2083. if l, str=sprintf('\t%s',lstr); else str=[str,' ']; end
  2084. function [p,msg] = sf_SzChk(p,n,msg)
  2085. %=======================================================================
  2086. %-Size checking
  2087. if nargin<3, msg=''; end
  2088. if nargin<2, n=[]; end, if isempty(n), n=NaN; else n=n(:)'; end
  2089. if nargin<1, error('insufficient arguments'), end
  2090. if ischar(p) || any(isnan(n(:))), return, end
  2091. if length(n)==1, n=[n,1]; end
  2092. dn = length(n);
  2093. sp = size(p);
  2094. dp = ndims(p);
  2095. if dn==2 && min(n)==1
  2096. %-[1,1], [1,n], [n,1], [1,Inf], [Inf,1] - vector - allow transpose
  2097. %---------------------------------------------------------------
  2098. i = min(find(n==max(n)));
  2099. if n(i)==1 && max(sp)>1
  2100. p='!'; msg='scalar required';
  2101. elseif ndims(p)~=2 || ~any(sp==1) || ( isfinite(n(i)) && max(sp)~=n(i) )
  2102. %-error: Not2D | not vector | not right length
  2103. if isfinite(n(i)), str=sprintf('%d-',n(i)); else str=''; end
  2104. p='!'; msg=[str,'vector required'];
  2105. elseif sp(i)==1 && n(i)~=1
  2106. p=p'; msg=[msg,' (input transposed)'];
  2107. end
  2108. elseif dn==2 && sum(isinf(n))==1
  2109. %-[n,Inf], [Inf,n] - n vector(s) required - allow transposing
  2110. %---------------------------------------------------------------
  2111. i = find(isfinite(n));
  2112. if ndims(p)~=2 || ~any(sp==n(i))
  2113. p='!'; msg=sprintf('%d-vector(s) required',min(n));
  2114. elseif sp(i)~=n
  2115. p=p'; msg=[msg,' (input transposed)'];
  2116. end
  2117. else
  2118. %-multi-dimensional matrix required - check dimensions
  2119. %---------------------------------------------------------------
  2120. if ndims(p)~=dn || ~all( size(p)==n | isinf(n) )
  2121. p = '!'; msg='';
  2122. for i = 1:dn
  2123. if isfinite(n(i)), msg = sprintf('%s,%d',msg,n(i));
  2124. else msg = sprintf('%s,*',msg); end
  2125. end
  2126. msg = ['[',msg(2:end),']-matrix required'];
  2127. end
  2128. end
  2129. %==========================================================================
  2130. function uifocus(h)
  2131. try
  2132. if strcmpi(get(h, 'Style'), 'PushButton') == 1
  2133. uicontrol(gcbo);
  2134. else
  2135. uicontrol(h);
  2136. end
  2137. end