1
0

Helios-Core.st 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838
  1. Smalltalk current createPackage: 'Helios-Core'!
  2. HLError subclass: #HLListItemNotFound
  3. instanceVariableNames: ''
  4. package: 'Helios-Core'!
  5. InterfacingObject subclass: #HLModel
  6. instanceVariableNames: 'announcer environment'
  7. package: 'Helios-Core'!
  8. !HLModel commentStamp!
  9. I am the abstract superclass of all models of Helios.
  10. I am the "Model" part of the MVC pattern implementation in Helios.
  11. I provide access to an `Environment` object and both a local (model-specific) and global (system-specific) announcer.
  12. The `#withChangesDo:` method is handy for performing model changes ensuring that all widgets are aware of the change and can prevent it from happening.
  13. Modifications of the system should be done via commands (see `HLCommand` and subclasses).!
  14. !HLModel methodsFor: 'accessing'!
  15. announcer
  16. ^ announcer ifNil: [ announcer := Announcer new ]
  17. !
  18. environment
  19. ^ environment ifNil: [ self manager environment ]
  20. !
  21. environment: anEnvironment
  22. environment := anEnvironment
  23. !
  24. manager
  25. ^ HLManager current
  26. !
  27. systemAnnouncer
  28. ^ self environment systemAnnouncer
  29. ! !
  30. !HLModel methodsFor: 'error handling'!
  31. withChangesDo: aBlock
  32. [
  33. self announcer announce: (HLAboutToChange new
  34. actionBlock: aBlock).
  35. aBlock value.
  36. ]
  37. on: HLChangeForbidden
  38. do: [ :ex | ]
  39. ! !
  40. !HLModel methodsFor: 'testing'!
  41. isBrowserModel
  42. ^ false
  43. !
  44. isReferencesModel
  45. ^ false
  46. !
  47. isToolModel
  48. ^ false
  49. ! !
  50. HLModel subclass: #HLToolModel
  51. instanceVariableNames: 'selectedClass selectedPackage selectedProtocol selectedSelector'
  52. package: 'Helios-Core'!
  53. !HLToolModel commentStamp!
  54. I am a model specific to package and class manipulation. All browsers should either use me or a subclass as their model.
  55. I provide methods for package, class, protocol and method manipulation and access, forwarding to my environment.
  56. I also handle compilation of classes and methods as well as compilation and parsing errors.!
  57. !HLToolModel methodsFor: 'accessing'!
  58. allSelectors
  59. ^ self environment allSelectors
  60. !
  61. availableClassNames
  62. ^ self environment availableClassNames
  63. !
  64. availablePackageNames
  65. ^ self environment availablePackageNames
  66. !
  67. availablePackages
  68. ^ self environment availablePackageNames
  69. !
  70. availableProtocols
  71. ^ self environment availableProtocolsFor: self selectedClass
  72. !
  73. packages
  74. ^ self environment packages
  75. !
  76. selectedClass
  77. ^ selectedClass
  78. !
  79. selectedClass: aClass
  80. (self selectedClass = aClass and: [ aClass isNil ])
  81. ifTrue: [ ^ self ].
  82. self withChangesDo: [
  83. selectedClass = aClass ifTrue: [
  84. self selectedProtocol: nil ].
  85. aClass
  86. ifNil: [ selectedClass := nil ]
  87. ifNotNil: [
  88. self selectedPackage: aClass theNonMetaClass package.
  89. self showInstance
  90. ifTrue: [ selectedClass := aClass theNonMetaClass ]
  91. ifFalse: [ selectedClass := aClass theMetaClass ] ].
  92. self selectedProtocol: nil.
  93. self announcer announce: (HLClassSelected on: self selectedClass) ]
  94. !
  95. selectedMethod
  96. ^ self selectedClass ifNotNil: [
  97. self selectedClass methodDictionary
  98. at: selectedSelector
  99. ifAbsent: [ nil ] ]
  100. !
  101. selectedMethod: aCompiledMethod
  102. selectedSelector = aCompiledMethod ifTrue: [ ^ self ].
  103. self withChangesDo: [
  104. aCompiledMethod
  105. ifNil: [ selectedSelector := nil ]
  106. ifNotNil: [
  107. selectedClass := aCompiledMethod methodClass.
  108. selectedPackage := selectedClass theNonMetaClass package.
  109. selectedSelector := aCompiledMethod selector ].
  110. self announcer announce: (HLMethodSelected on: aCompiledMethod) ]
  111. !
  112. selectedPackage
  113. ^ selectedPackage
  114. !
  115. selectedPackage: aPackage
  116. selectedPackage = aPackage ifTrue: [ ^ self ].
  117. self withChangesDo: [
  118. selectedPackage := aPackage.
  119. self selectedClass: nil.
  120. self announcer announce: (HLPackageSelected on: aPackage) ]
  121. !
  122. selectedProtocol
  123. ^ selectedProtocol
  124. !
  125. selectedProtocol: aString
  126. selectedProtocol = aString ifTrue: [ ^ self ].
  127. self withChangesDo: [
  128. selectedProtocol := aString.
  129. self selectedMethod: nil.
  130. self announcer announce: (HLProtocolSelected on: aString) ]
  131. ! !
  132. !HLToolModel methodsFor: 'actions'!
  133. addInstVarNamed: aString
  134. self environment addInstVarNamed: aString to: self selectedClass.
  135. self announcer announce: (HLInstVarAdded new
  136. theClass: self selectedClass;
  137. variableName: aString;
  138. yourself)
  139. !
  140. save: aString
  141. self announcer announce: HLSourceCodeSaved new.
  142. (self shouldCompileClassDefinition: aString)
  143. ifTrue: [ self compileClassDefinition: aString ]
  144. ifFalse: [ self compileMethod: aString ]
  145. !
  146. saveSourceCode
  147. self announcer announce: HLSaveSourceCode new
  148. ! !
  149. !HLToolModel methodsFor: 'commands actions'!
  150. commitPackage
  151. self environment commitPackage: self selectedPackage
  152. !
  153. copyClassTo: aClassName
  154. self withChangesDo: [
  155. self environment
  156. copyClass: self selectedClass theNonMetaClass
  157. to: aClassName ]
  158. !
  159. moveClassToPackage: aPackageName
  160. self withChangesDo: [
  161. self environment
  162. moveClass: self selectedClass theNonMetaClass
  163. toPackage: aPackageName ]
  164. !
  165. moveMethodToClass: aClassName
  166. self withChangesDo: [
  167. self environment
  168. moveMethod: self selectedMethod
  169. toClass: aClassName ]
  170. !
  171. moveMethodToProtocol: aProtocol
  172. self withChangesDo: [
  173. self environment
  174. moveMethod: self selectedMethod
  175. toProtocol: aProtocol ]
  176. !
  177. openClassNamed: aString
  178. | class |
  179. self withChangesDo: [
  180. class := self environment classNamed: aString.
  181. self selectedPackage: class package.
  182. self selectedClass: class ]
  183. !
  184. removeClass
  185. self withChangesDo: [
  186. self manager
  187. confirm: 'Do you REALLY want to remove class ', self selectedClass name
  188. ifTrue: [ self environment removeClass: self selectedClass ] ]
  189. !
  190. removeMethod
  191. self withChangesDo: [
  192. self manager
  193. confirm: 'Do you REALLY want to remove method ', self selectedMethod methodClass name,' >> #', self selectedMethod selector
  194. ifTrue: [ self environment removeMethod: self selectedMethod ] ]
  195. !
  196. removeProtocol
  197. self withChangesDo: [
  198. self manager
  199. confirm: 'Do you REALLY want to remove protocol ', self selectedProtocol
  200. ifTrue: [ self environment
  201. removeProtocol: self selectedProtocol
  202. from: self selectedClass ] ]
  203. !
  204. renameClassTo: aClassName
  205. self withChangesDo: [
  206. self environment
  207. renameClass: self selectedClass theNonMetaClass
  208. to: aClassName ]
  209. !
  210. renameProtocolTo: aString
  211. self withChangesDo: [
  212. self environment
  213. renameProtocol: self selectedProtocol
  214. to: aString
  215. in: self selectedClass ]
  216. ! !
  217. !HLToolModel methodsFor: 'compiling'!
  218. compileClassComment: aString
  219. self environment
  220. compileClassComment: aString
  221. for: self selectedClass
  222. !
  223. compileClassDefinition: aString
  224. self environment compileClassDefinition: aString
  225. !
  226. compileMethod: aString
  227. | method |
  228. self withCompileErrorHandling: [
  229. method := self environment
  230. compileMethod: aString
  231. for: self selectedClass
  232. protocol: self compilationProtocol.
  233. self selectedMethod: method ]
  234. ! !
  235. !HLToolModel methodsFor: 'defaults'!
  236. allProtocol
  237. ^ '-- all --'
  238. !
  239. unclassifiedProtocol
  240. ^ 'as yet unclassified'
  241. ! !
  242. !HLToolModel methodsFor: 'error handling'!
  243. handleCompileError: anError
  244. self announcer announce: (HLCompileErrorRaised new
  245. error: anError;
  246. yourself)
  247. !
  248. handleParseError: anError
  249. | split line column messageToInsert |
  250. split := anError messageText tokenize: ' : '.
  251. messageToInsert := split second.
  252. "21 = 'Parse error on line ' size + 1"
  253. split := split first copyFrom: 21 to: split first size.
  254. split := split tokenize: ' column '.
  255. line := split first.
  256. column := split second.
  257. self announcer announce: (HLParseErrorRaised new
  258. line: line asNumber;
  259. column: column asNumber;
  260. message: messageToInsert;
  261. error: anError;
  262. yourself)
  263. !
  264. handleUnkownVariableError: anError
  265. self announcer announce: (HLUnknownVariableErrorRaised new
  266. error: anError;
  267. yourself)
  268. !
  269. withCompileErrorHandling: aBlock
  270. self environment
  271. evaluate: [
  272. self environment
  273. evaluate: [
  274. self environment
  275. evaluate: aBlock
  276. on: ParseError
  277. do: [:ex | self handleParseError: ex ] ]
  278. on: UnknownVariableError
  279. do: [ :ex | self handleUnkownVariableError: ex ] ]
  280. on: CompilerError
  281. do: [ :ex | self handleCompileError: ex ]
  282. ! !
  283. !HLToolModel methodsFor: 'private'!
  284. compilationProtocol
  285. | currentProtocol |
  286. currentProtocol := self selectedProtocol.
  287. currentProtocol ifNil: [ currentProtocol := self unclassifiedProtocol ].
  288. self selectedMethod ifNotNil: [ currentProtocol := self selectedMethod protocol ].
  289. ^ currentProtocol = self allProtocol
  290. ifTrue: [ self unclassifiedProtocol ]
  291. ifFalse: [ currentProtocol ]
  292. !
  293. withHelperLabelled: aString do: aBlock
  294. "TODO: doesn't belong here"
  295. '#helper' asJQuery remove.
  296. [ :html |
  297. html div
  298. id: 'helper';
  299. with: aString ] appendToJQuery: 'body' asJQuery.
  300. [
  301. aBlock value.
  302. '#helper' asJQuery remove
  303. ]
  304. valueWithTimeout: 10
  305. ! !
  306. !HLToolModel methodsFor: 'testing'!
  307. isToolModel
  308. ^ true
  309. !
  310. shouldCompileClassDefinition: aString
  311. ^ self selectedClass isNil or: [
  312. aString match: '^[A-Z]' ]
  313. ! !
  314. !HLToolModel class methodsFor: 'actions'!
  315. on: anEnvironment
  316. ^ self new
  317. environment: anEnvironment;
  318. yourself
  319. ! !
  320. ProgressHandler subclass: #HLProgressHandler
  321. instanceVariableNames: ''
  322. package: 'Helios-Core'!
  323. !HLProgressHandler commentStamp!
  324. I am a specific progress handler for Helios, displaying progresses in a modal window.!
  325. !HLProgressHandler methodsFor: 'progress handling'!
  326. do: aBlock on: aCollection displaying: aString
  327. HLProgressWidget default
  328. do: aBlock
  329. on: aCollection
  330. displaying: aString
  331. ! !
  332. Widget subclass: #HLTabWidget
  333. instanceVariableNames: 'widget label root'
  334. package: 'Helios-Core'!
  335. !HLTabWidget commentStamp!
  336. I am a widget specialized into building another widget as an Helios tab.
  337. I should not be used directly, `HLWidget class >> #openAsTab` should be used instead.
  338. ## Example
  339. HLWorkspace openAsTab!
  340. !HLTabWidget methodsFor: 'accessing'!
  341. activate
  342. self manager activate: self
  343. !
  344. add
  345. self manager addTab: self
  346. !
  347. cssClass
  348. ^ self widget tabClass
  349. !
  350. displayLabel
  351. ^ self label size > 20
  352. ifTrue: [ (self label first: 20), '...' ]
  353. ifFalse: [ self label ]
  354. !
  355. focus
  356. self widget canHaveFocus ifTrue: [
  357. self widget focus ]
  358. !
  359. label
  360. ^ label ifNil: [ '' ]
  361. !
  362. label: aString
  363. label := aString
  364. !
  365. manager
  366. ^ HLManager current
  367. !
  368. widget
  369. ^ widget
  370. !
  371. widget: aWidget
  372. widget := aWidget
  373. ! !
  374. !HLTabWidget methodsFor: 'actions'!
  375. hide
  376. root ifNotNil: [ root asJQuery css: 'visibility' put: 'hidden' ]
  377. !
  378. registerBindings
  379. self widget registerBindings
  380. !
  381. remove
  382. self widget unregister.
  383. root ifNotNil: [ root asJQuery remove ]
  384. !
  385. show
  386. root
  387. ifNil: [ self appendToJQuery: 'body' asJQuery ]
  388. ifNotNil: [ root asJQuery css: 'visibility' put: 'visible' ]
  389. ! !
  390. !HLTabWidget methodsFor: 'rendering'!
  391. renderOn: html
  392. root := html div
  393. class: 'tab';
  394. yourself.
  395. self renderTab
  396. !
  397. renderTab
  398. root contents: [ :html |
  399. html div
  400. class: 'amber_box';
  401. with: [ self widget renderOn: html ] ]
  402. ! !
  403. !HLTabWidget methodsFor: 'testing'!
  404. isActive
  405. ^ self manager activeTab = self
  406. ! !
  407. !HLTabWidget class methodsFor: 'instance creation'!
  408. on: aWidget labelled: aString
  409. ^ self new
  410. widget: aWidget;
  411. label: aString;
  412. yourself
  413. ! !
  414. Widget subclass: #HLWidget
  415. instanceVariableNames: 'wrapper'
  416. package: 'Helios-Core'!
  417. !HLWidget commentStamp!
  418. I am the abstract superclass of all Helios widgets.
  419. I provide common methods, additional behavior to widgets useful for Helios, like dialog creation, command execution and tab creation.
  420. ## API
  421. 1. Rendering
  422. Instead of overriding `#renderOn:` as with other Widget subclasses, my subclasses should override `#renderContentOn:`.
  423. 2. Refreshing
  424. To re-render a widget, use `#refresh`.
  425. 3. Key bindings registration and tabs
  426. When displayed as a tab, the widget has a chance to register keybindings with the `#registerBindingsOn:` hook method.
  427. 4. Unregistration
  428. When a widget has subscribed to announcements or other actions that need to be cleared when closing the tab, the hook method `#unregister` will be called by helios.
  429. 5. Tabs
  430. To enable a widget class to be open as a tab, override the class-side `#canBeOpenAsTab` method to answer `true`. `#tabClass` and `#tabPriority` can be overridden too to respectively change the css class of the tab and the order of tabs in the main menu.
  431. 6. Command execution
  432. An helios command (instance of `HLCommand` or one of its subclass) can be executed with `#execute:`.!
  433. !HLWidget methodsFor: 'accessing'!
  434. manager
  435. ^ HLManager current
  436. !
  437. tabClass
  438. ^ self class tabClass
  439. !
  440. wrapper
  441. ^ wrapper
  442. ! !
  443. !HLWidget methodsFor: 'actions'!
  444. confirm: aString ifTrue: aBlock
  445. self manager confirm: aString ifTrue: aBlock
  446. !
  447. execute: aCommand
  448. HLManager current keyBinder
  449. activate;
  450. applyBinding: aCommand asBinding
  451. !
  452. openAsTab
  453. HLManager current addTab: (HLTabWidget on: self labelled: self class tabLabel)
  454. !
  455. request: aString do: aBlock
  456. self manager request: aString do: aBlock
  457. !
  458. request: aString value: valueString do: aBlock
  459. self manager
  460. request: aString
  461. value: valueString
  462. do: aBlock
  463. !
  464. unregister
  465. "This method is called whenever the receiver is closed (as a tab).
  466. Widgets subscribing to announcements should unregister there"
  467. ! !
  468. !HLWidget methodsFor: 'keybindings'!
  469. bindKeyDown: keyDownBlock keyUp: keyUpBlock
  470. self wrapper asJQuery
  471. keydown: keyDownBlock;
  472. keyup: keyUpBlock
  473. !
  474. registerBindings
  475. self registerBindingsOn: self manager keyBinder bindings
  476. !
  477. registerBindingsOn: aBindingGroup
  478. !
  479. unbindKeyDownKeyUp
  480. self wrapper asJQuery
  481. unbind: 'keydown';
  482. unbind: 'keyup'
  483. ! !
  484. !HLWidget methodsFor: 'rendering'!
  485. renderContentOn: html
  486. !
  487. renderOn: html
  488. wrapper := html div.
  489. [ :renderer | self renderContentOn: renderer ] appendToJQuery: wrapper asJQuery
  490. ! !
  491. !HLWidget methodsFor: 'testing'!
  492. canHaveFocus
  493. ^ false
  494. ! !
  495. !HLWidget methodsFor: 'updating'!
  496. refresh
  497. self wrapper ifNil: [ ^ self ].
  498. self wrapper asJQuery empty.
  499. [ :html | self renderContentOn: html ] appendToJQuery: self wrapper asJQuery
  500. ! !
  501. !HLWidget class methodsFor: 'accessing'!
  502. openAsTab
  503. HLManager current addTab: (HLTabWidget on: self new labelled: self tabLabel)
  504. !
  505. tabClass
  506. ^ ''
  507. !
  508. tabLabel
  509. ^ 'Tab'
  510. !
  511. tabPriority
  512. ^ 500
  513. ! !
  514. !HLWidget class methodsFor: 'testing'!
  515. canBeOpenAsTab
  516. ^ false
  517. ! !
  518. HLWidget subclass: #HLFocusableWidget
  519. instanceVariableNames: ''
  520. package: 'Helios-Core'!
  521. !HLFocusableWidget commentStamp!
  522. I am a widget that can be focused.
  523. ## API
  524. Instead of overriding `#renderOn:` as with other `Widget` subclasses, my subclasses should override `#renderContentOn:`.
  525. To bring the focus to the widget, use the `#focus` method.!
  526. !HLFocusableWidget methodsFor: 'accessing'!
  527. focusClass
  528. ^ 'focused'
  529. ! !
  530. !HLFocusableWidget methodsFor: 'events'!
  531. blur
  532. self wrapper asJQuery blur
  533. !
  534. focus
  535. self wrapper asJQuery focus
  536. ! !
  537. !HLFocusableWidget methodsFor: 'rendering'!
  538. renderContentOn: html
  539. !
  540. renderOn: html
  541. wrapper := html div
  542. class: 'hl_widget';
  543. yourself.
  544. wrapper with: [ self renderContentOn: html ].
  545. wrapper
  546. at: 'tabindex' put: '0';
  547. onBlur: [ self wrapper asJQuery removeClass: self focusClass ];
  548. onFocus: [ self wrapper asJQuery addClass: self focusClass ]
  549. ! !
  550. !HLFocusableWidget methodsFor: 'testing'!
  551. canHaveFocus
  552. ^ true
  553. !
  554. hasFocus
  555. ^ self wrapper notNil and: [ self wrapper asJQuery hasClass: self focusClass ]
  556. ! !
  557. HLFocusableWidget subclass: #HLListWidget
  558. instanceVariableNames: 'items selectedItem'
  559. package: 'Helios-Core'!
  560. !HLListWidget methodsFor: 'accessing'!
  561. cssClassForItem: anObject
  562. ^ ''
  563. !
  564. items
  565. ^ items ifNil: [ items := self defaultItems ]
  566. !
  567. items: aCollection
  568. items := aCollection
  569. !
  570. listCssClassForItem: anObject
  571. ^ self selectedItem = anObject
  572. ifTrue: [ 'active' ]
  573. ifFalse: [ 'inactive' ]
  574. !
  575. positionOf: aListItem
  576. <
  577. return aListItem.parent().children().get().indexOf(aListItem.get(0)) + 1
  578. >
  579. !
  580. selectedItem
  581. ^ selectedItem
  582. !
  583. selectedItem: anObject
  584. selectedItem := anObject
  585. ! !
  586. !HLListWidget methodsFor: 'actions'!
  587. activateFirstListItem
  588. self activateListItem: ((wrapper asJQuery find: 'li.inactive') eq: 0)
  589. !
  590. activateItem: anObject
  591. | listData |
  592. listData := [self listDataKeyFor: anObject] on: HLListItemNotFound do: [^self].
  593. self activateListItem: ((wrapper asJQuery find: 'li[list-data="', listData , '"]') eq: 0)
  594. !
  595. activateListItem: aListItem
  596. | item |
  597. (aListItem get: 0) ifNil: [ ^self ].
  598. aListItem parent children removeClass: 'active'.
  599. aListItem addClass: 'active'.
  600. self ensureVisible: aListItem.
  601. "Activate the corresponding item"
  602. item := (self items at: (aListItem attr: 'list-data') asNumber).
  603. self selectedItem == item ifFalse: [
  604. self selectItem: item ]
  605. !
  606. activateNextListItem
  607. self activateListItem: (self wrapper asJQuery find: 'li.active') next.
  608. "select the first item if none is selected"
  609. (self wrapper asJQuery find: ' .active') get ifEmpty: [
  610. self activateFirstListItem ]
  611. !
  612. activatePreviousListItem
  613. self activateListItem: (self wrapper asJQuery find: 'li.active') prev
  614. !
  615. ensureVisible: aListItem
  616. "Move the scrollbar to show the active element"
  617. | parent position |
  618. position := self positionOf: aListItem.
  619. parent := aListItem parent.
  620. aListItem position top < 0 ifTrue: [
  621. (parent get: 0) scrollTop: ((parent get: 0) scrollTop + aListItem position top - 10) ].
  622. aListItem position top + aListItem height > parent height ifTrue: [
  623. (parent get: 0) scrollTop: ((parent get: 0) scrollTop + aListItem height - (parent height - aListItem position top)) +10 ]
  624. !
  625. focus
  626. super focus.
  627. self items isEmpty ifFalse: [
  628. self selectedItem ifNil: [ self activateFirstListItem ] ]
  629. !
  630. listDataKeyFor: anObject
  631. ^(self items indexOf: anObject ifAbsent: [HLListItemNotFound signal]) asString
  632. !
  633. refresh
  634. | listData |
  635. super refresh.
  636. listData := [self listDataKeyFor: self selectedItem] on: HLListItemNotFound do: [^self].
  637. self ensureVisible: ((wrapper asJQuery find: 'li[list-data="', listData , '"]') eq: 0)
  638. !
  639. selectItem: anObject
  640. self selectedItem: anObject
  641. ! !
  642. !HLListWidget methodsFor: 'defaults'!
  643. defaultItems
  644. ^ #()
  645. ! !
  646. !HLListWidget methodsFor: 'events'!
  647. setupKeyBindings
  648. (HLRepeatedKeyDownHandler on: self)
  649. whileKeyDown: 38 do: [ self activatePreviousListItem ];
  650. whileKeyDown: 40 do: [ self activateNextListItem ];
  651. rebindKeys
  652. ! !
  653. !HLListWidget methodsFor: 'rendering'!
  654. renderButtonsOn: html
  655. !
  656. renderContentOn: html
  657. html ul
  658. class: 'nav nav-pills nav-stacked';
  659. with: [ self renderListOn: html ].
  660. html div class: 'pane_actions form-actions'; with: [
  661. self renderButtonsOn: html ].
  662. self setupKeyBindings
  663. !
  664. renderItem: anObject dataKey: aString on: html
  665. | li |
  666. li := html li.
  667. li
  668. at: 'list-data' put: aString;
  669. class: (self listCssClassForItem: anObject);
  670. with: [
  671. html a
  672. with: [
  673. (html tag: 'i') class: (self cssClassForItem: anObject).
  674. self renderItemLabel: anObject on: html ];
  675. onClick: [
  676. self activateListItem: li asJQuery ] ]
  677. !
  678. renderItem: anObject on: html
  679. self renderItem: anObject dataKey: (self listDataKeyFor: anObject) on: html
  680. !
  681. renderItemLabel: anObject on: html
  682. html with: anObject asString
  683. !
  684. renderListOn: html
  685. self items withIndexDo: [ :each :index |
  686. self renderItem: each dataKey: index asString on: html ]
  687. ! !
  688. HLListWidget subclass: #HLNavigationListWidget
  689. instanceVariableNames: 'previous next'
  690. package: 'Helios-Core'!
  691. !HLNavigationListWidget methodsFor: 'accessing'!
  692. next
  693. ^ next
  694. !
  695. next: aWidget
  696. next := aWidget.
  697. aWidget previous = self ifFalse: [ aWidget previous: self ]
  698. !
  699. previous
  700. ^ previous
  701. !
  702. previous: aWidget
  703. previous := aWidget.
  704. aWidget next = self ifFalse: [ aWidget next: self ]
  705. ! !
  706. !HLNavigationListWidget methodsFor: 'actions'!
  707. nextFocus
  708. self next ifNotNil: [ self next focus ]
  709. !
  710. previousFocus
  711. self previous ifNotNil: [ self previous focus ]
  712. ! !
  713. !HLNavigationListWidget methodsFor: 'as yet unclassified'!
  714. activateItem: anObject
  715. self activateListItem: ((wrapper asJQuery find: 'li[list-data="', (self items indexOf: anObject ifAbsent: [^self]) asString, '"]') eq: 0)
  716. ! !
  717. !HLNavigationListWidget methodsFor: 'events'!
  718. setupKeyBindings
  719. super setupKeyBindings.
  720. self wrapper asJQuery keydown: [ :e |
  721. e which = 39 ifTrue: [
  722. self nextFocus ].
  723. e which = 37 ifTrue: [
  724. self previousFocus ] ]
  725. ! !
  726. HLNavigationListWidget subclass: #HLToolListWidget
  727. instanceVariableNames: 'model'
  728. package: 'Helios-Core'!
  729. !HLToolListWidget methodsFor: 'accessing'!
  730. commandCategory
  731. ^ self label
  732. !
  733. label
  734. ^ 'List'
  735. !
  736. menuCommands
  737. "Answer a collection of commands to be put in the cog menu"
  738. ^ ((HLToolCommand concreteClasses
  739. select: [ :each | each isValidFor: self model ])
  740. collect: [ :each | each for: self model ])
  741. select: [ :each |
  742. each category = self commandCategory and: [
  743. each isAction and: [ each isActive ] ] ]
  744. !
  745. model
  746. ^ model
  747. !
  748. model: aBrowserModel
  749. model := aBrowserModel.
  750. self
  751. observeSystem;
  752. observeModel
  753. !
  754. selectedItem: anItem
  755. "Selection changed, update the cog menu"
  756. super selectedItem: anItem.
  757. self updateMenu
  758. ! !
  759. !HLToolListWidget methodsFor: 'actions'!
  760. activateListItem: anItem
  761. self model withChangesDo: [ super activateListItem: anItem ]
  762. !
  763. activateNextListItem
  764. self model withChangesDo: [ super activateNextListItem ]
  765. !
  766. activatePreviousListItem
  767. self model withChangesDo: [ super activatePreviousListItem ]
  768. !
  769. observeModel
  770. !
  771. observeSystem
  772. !
  773. unregister
  774. super unregister.
  775. self model announcer unsubscribe: self.
  776. self model systemAnnouncer unsubscribe: self
  777. ! !
  778. !HLToolListWidget methodsFor: 'rendering'!
  779. renderContentOn: html
  780. self renderHeadOn: html.
  781. super renderContentOn: html
  782. !
  783. renderHeadOn: html
  784. html div
  785. class: 'list-label';
  786. with: [
  787. html with: self label.
  788. self renderMenuOn: html ]
  789. !
  790. renderMenuOn: html
  791. | commands |
  792. commands := self menuCommands.
  793. commands isEmpty ifTrue: [ ^ self ].
  794. html div
  795. class: 'btn-group cog';
  796. with: [
  797. html a
  798. class: 'btn dropdown-toggle';
  799. at: 'data-toggle' put: 'dropdown';
  800. with: [ (html tag: 'i') class: 'icon-cog' ].
  801. html ul
  802. class: 'dropdown-menu pull-right';
  803. with: [
  804. self menuCommands do: [ :each |
  805. html li with: [ html a
  806. with: each menuLabel;
  807. onClick: [ self execute: each ] ] ] ] ]
  808. ! !
  809. !HLToolListWidget methodsFor: 'updating'!
  810. updateMenu
  811. (self wrapper asJQuery find: '.cog') remove.
  812. [ :html | self renderMenuOn: html ]
  813. appendToJQuery: (self wrapper asJQuery find: '.list-label')
  814. ! !
  815. !HLToolListWidget class methodsFor: 'instance creation'!
  816. on: aModel
  817. ^ self new
  818. model: aModel;
  819. yourself
  820. ! !
  821. HLListWidget subclass: #HLTabListWidget
  822. instanceVariableNames: 'callback'
  823. package: 'Helios-Core'!
  824. !HLTabListWidget commentStamp!
  825. I am a widget used to display a list of helios tabs.
  826. When a tab is selected, `callback` is evaluated with the selected tab as argument.!
  827. !HLTabListWidget methodsFor: 'accessing'!
  828. callback
  829. ^ callback ifNil: [ [] ]
  830. !
  831. callback: aBlock
  832. callback := aBlock
  833. ! !
  834. !HLTabListWidget methodsFor: 'actions'!
  835. selectItem: aTab
  836. super selectItem: aTab.
  837. self callback value: aTab
  838. ! !
  839. !HLTabListWidget methodsFor: 'rendering'!
  840. renderItemLabel: aTab on: html
  841. html span
  842. class: aTab cssClass;
  843. with: aTab label
  844. ! !
  845. HLWidget subclass: #HLManager
  846. instanceVariableNames: 'tabs activeTab environment history'
  847. package: 'Helios-Core'!
  848. !HLManager methodsFor: 'accessing'!
  849. activeTab
  850. ^ activeTab
  851. !
  852. environment
  853. "The default environment used by all Helios objects"
  854. ^ environment ifNil: [ environment := self defaultEnvironment ]
  855. !
  856. environment: anEnvironment
  857. environment := anEnvironment
  858. !
  859. history
  860. ^ history ifNil: [ history := OrderedCollection new ]
  861. !
  862. history: aCollection
  863. history := aCollection
  864. !
  865. keyBinder
  866. ^ HLKeyBinder current
  867. !
  868. tabs
  869. ^ tabs ifNil: [ tabs := OrderedCollection new ]
  870. ! !
  871. !HLManager methodsFor: 'actions'!
  872. activate: aTab
  873. self keyBinder flushBindings.
  874. aTab registerBindings.
  875. activeTab := aTab.
  876. self
  877. refresh;
  878. addToHistory: aTab;
  879. show: aTab
  880. !
  881. addTab: aTab
  882. self tabs add: aTab.
  883. self activate: aTab
  884. !
  885. addToHistory: aTab
  886. self removeFromHistory: aTab.
  887. self history add: aTab
  888. !
  889. confirm: aString ifFalse: aBlock
  890. HLConfirmationWidget new
  891. confirmationString: aString;
  892. cancelBlock: aBlock;
  893. show
  894. !
  895. confirm: aString ifTrue: aBlock
  896. HLConfirmationWidget new
  897. confirmationString: aString;
  898. actionBlock: aBlock;
  899. show
  900. !
  901. registerErrorHandler: anErrorHandler
  902. self environment registerErrorHandler: anErrorHandler
  903. !
  904. registerInspector: anInspector
  905. self environment registerInspector: anInspector
  906. !
  907. registerProgressHandler: aProgressHandler
  908. self environment registerProgressHandler: aProgressHandler
  909. !
  910. removeActiveTab
  911. self removeTab: self activeTab
  912. !
  913. removeFromHistory: aTab
  914. self history: (self history reject: [ :each | each == aTab ])
  915. !
  916. removeTab: aTab
  917. (self tabs includes: aTab) ifFalse: [ ^ self ].
  918. self removeFromHistory: aTab.
  919. self tabs remove: aTab.
  920. self keyBinder flushBindings.
  921. aTab remove.
  922. self refresh.
  923. self history ifNotEmpty: [
  924. self history last activate ]
  925. !
  926. request: aString do: aBlock
  927. self
  928. request: aString
  929. value: ''
  930. do: aBlock
  931. !
  932. request: aString value: valueString do: aBlock
  933. HLRequestWidget new
  934. confirmationString: aString;
  935. actionBlock: aBlock;
  936. value: valueString;
  937. show
  938. ! !
  939. !HLManager methodsFor: 'defaults'!
  940. defaultEnvironment
  941. "If helios is loaded from within a frame, answer the parent window environment"
  942. | parent parentSmalltalk |
  943. parent := window opener ifNil: [ window parent ].
  944. parent ifNil: [ ^ Environment new ].
  945. parentSmalltalk := (parent at: 'requirejs') value: 'amber_vm/smalltalk'.
  946. parentSmalltalk ifNil: [ ^ Environment new ].
  947. ^ (parentSmalltalk at: 'Environment') new
  948. ! !
  949. !HLManager methodsFor: 'initialization'!
  950. initialize
  951. super initialize.
  952. HLErrorHandler register.
  953. HLProgressHandler register.
  954. self registerInspector: HLInspector.
  955. self registerErrorHandler: ErrorHandler current.
  956. self registerProgressHandler: ProgressHandler current.
  957. self keyBinder setupEvents
  958. ! !
  959. !HLManager methodsFor: 'rendering'!
  960. refresh
  961. '.navbar' asJQuery remove.
  962. self appendToJQuery: 'body' asJQuery
  963. !
  964. renderAddOn: html
  965. html li
  966. class: 'dropdown';
  967. with: [
  968. html a
  969. class: 'dropdown-toggle';
  970. at: 'data-toggle' put: 'dropdown';
  971. with: [
  972. html with: 'Open...'.
  973. (html tag: 'b') class: 'caret' ].
  974. html ul
  975. class: 'dropdown-menu';
  976. with: [
  977. ((HLWidget withAllSubclasses
  978. select: [ :each | each canBeOpenAsTab ])
  979. sorted: [ :a :b | a tabPriority < b tabPriority ])
  980. do: [ :each |
  981. html li with: [
  982. html a
  983. with: each tabLabel;
  984. onClick: [ each openAsTab ] ] ] ] ]
  985. !
  986. renderContentOn: html
  987. html div
  988. class: 'navbar navbar-fixed-top';
  989. with: [ html div
  990. class: 'navbar-inner';
  991. with: [ self renderTabsOn: html ] ]
  992. !
  993. renderTabsOn: html
  994. html ul
  995. class: 'nav';
  996. with: [
  997. self tabs do: [ :each |
  998. html li
  999. class: (each isActive ifTrue: [ 'active' ] ifFalse: [ 'inactive' ]);
  1000. with: [
  1001. html a
  1002. with: [
  1003. ((html tag: 'i') class: 'close')
  1004. onClick: [ self removeTab: each ].
  1005. html span
  1006. class: each cssClass;
  1007. with: each displayLabel ];
  1008. onClick: [ each activate ] ] ].
  1009. self renderAddOn: html ]
  1010. !
  1011. show: aTab
  1012. self tabs do: [ :each | each hide ].
  1013. aTab show; focus
  1014. ! !
  1015. HLManager class instanceVariableNames: 'current'!
  1016. !HLManager class methodsFor: 'accessing'!
  1017. current
  1018. ^ current ifNil: [ current := self basicNew initialize ]
  1019. ! !
  1020. !HLManager class methodsFor: 'initialization'!
  1021. initialize
  1022. self current appendToJQuery: 'body' asJQuery
  1023. ! !
  1024. !HLManager class methodsFor: 'instance creation'!
  1025. new
  1026. "Use current instead"
  1027. self shouldNotImplement
  1028. ! !
  1029. HLWidget subclass: #HLModalWidget
  1030. instanceVariableNames: ''
  1031. package: 'Helios-Core'!
  1032. !HLModalWidget commentStamp!
  1033. I implement an abstract modal widget.!
  1034. !HLModalWidget methodsFor: 'accessing'!
  1035. cssClass
  1036. ^ ''
  1037. ! !
  1038. !HLModalWidget methodsFor: 'actions'!
  1039. cancel
  1040. self remove
  1041. !
  1042. confirm
  1043. "Override in subclasses"
  1044. self remove
  1045. !
  1046. remove
  1047. '.dialog' asJQuery removeClass: 'active'.
  1048. [
  1049. '#overlay' asJQuery remove.
  1050. '.dialog' asJQuery remove
  1051. ] valueWithTimeout: 300
  1052. !
  1053. show
  1054. self appendToJQuery: 'body' asJQuery
  1055. ! !
  1056. !HLModalWidget methodsFor: 'rendering'!
  1057. hasButtons
  1058. ^ true
  1059. !
  1060. renderButtonsOn: html
  1061. | confirmButton |
  1062. html div
  1063. class: 'buttons';
  1064. with: [
  1065. html button
  1066. class: 'button';
  1067. with: 'Cancel';
  1068. onClick: [ self cancel ].
  1069. confirmButton := html button
  1070. class: 'button default';
  1071. with: 'Confirm';
  1072. onClick: [ self confirm ] ].
  1073. confirmButton asJQuery focus
  1074. !
  1075. renderContentOn: html
  1076. | confirmButton |
  1077. html div id: 'overlay'.
  1078. html div
  1079. class: 'dialog ', self cssClass;
  1080. with: [
  1081. self renderMainOn: html.
  1082. self hasButtons ifTrue: [
  1083. self renderButtonsOn: html ] ].
  1084. '.dialog' asJQuery addClass: 'active'.
  1085. self setupKeyBindings
  1086. !
  1087. renderMainOn: html
  1088. !
  1089. setupKeyBindings
  1090. '.dialog' asJQuery keyup: [ :e |
  1091. e keyCode = String esc asciiValue ifTrue: [ self cancel ] ]
  1092. ! !
  1093. HLModalWidget subclass: #HLConfirmationWidget
  1094. instanceVariableNames: 'confirmationString actionBlock cancelBlock'
  1095. package: 'Helios-Core'!
  1096. !HLConfirmationWidget commentStamp!
  1097. I display confirmation messages.
  1098. Instead of creating an instance directly, use `HLWidget >> #confirm:ifTrue:`.!
  1099. !HLConfirmationWidget methodsFor: 'accessing'!
  1100. actionBlock
  1101. ^ actionBlock ifNil: [ [] ]
  1102. !
  1103. actionBlock: aBlock
  1104. actionBlock := aBlock
  1105. !
  1106. cancelBlock
  1107. ^ cancelBlock ifNil: [ [] ]
  1108. !
  1109. cancelBlock: aBlock
  1110. cancelBlock := aBlock
  1111. !
  1112. confirmationString
  1113. ^ confirmationString ifNil: [ 'Confirm' ]
  1114. !
  1115. confirmationString: aString
  1116. confirmationString := aString
  1117. ! !
  1118. !HLConfirmationWidget methodsFor: 'actions'!
  1119. cancel
  1120. self cancelBlock value.
  1121. super cancel
  1122. !
  1123. confirm
  1124. super confirm.
  1125. self actionBlock value
  1126. ! !
  1127. !HLConfirmationWidget methodsFor: 'rendering'!
  1128. renderMainOn: html
  1129. html span with: self confirmationString
  1130. ! !
  1131. HLConfirmationWidget subclass: #HLRequestWidget
  1132. instanceVariableNames: 'input value'
  1133. package: 'Helios-Core'!
  1134. !HLRequestWidget commentStamp!
  1135. I display a modal window requesting user input.
  1136. Instead of creating instances manually, use `HLWidget >> #request:do:` and `#request:value:do:`.!
  1137. !HLRequestWidget methodsFor: 'accessing'!
  1138. cssClass
  1139. ^ 'large'
  1140. !
  1141. value
  1142. ^ value ifNil: [ '' ]
  1143. !
  1144. value: aString
  1145. value := aString
  1146. ! !
  1147. !HLRequestWidget methodsFor: 'actions'!
  1148. confirm
  1149. super confirm.
  1150. self actionBlock value: input asJQuery val
  1151. ! !
  1152. !HLRequestWidget methodsFor: 'rendering'!
  1153. renderMainOn: html
  1154. super renderMainOn: html.
  1155. input := html textarea.
  1156. input asJQuery val: self value
  1157. ! !
  1158. HLModalWidget subclass: #HLProgressWidget
  1159. instanceVariableNames: 'progressBars visible'
  1160. package: 'Helios-Core'!
  1161. !HLProgressWidget commentStamp!
  1162. I am a widget used to display progress modal dialogs.
  1163. My default instance is accessed with `HLProgressWidget class >> #default`.
  1164. See `HLProgressHandler` for usage.!
  1165. !HLProgressWidget methodsFor: 'accessing'!
  1166. progressBars
  1167. ^ progressBars ifNil: [ progressBars := OrderedCollection new ]
  1168. ! !
  1169. !HLProgressWidget methodsFor: 'actions'!
  1170. addProgressBar: aProgressBar
  1171. self show.
  1172. self progressBars add: aProgressBar.
  1173. aProgressBar appendToJQuery: (self wrapper asJQuery find: '.dialog')
  1174. !
  1175. do: aBlock on: aCollection displaying: aString
  1176. | progressBar |
  1177. progressBar := HLProgressBarWidget new
  1178. parent: self;
  1179. label: aString;
  1180. workBlock: aBlock;
  1181. collection: aCollection;
  1182. yourself.
  1183. self addProgressBar: progressBar.
  1184. progressBar start
  1185. !
  1186. flush
  1187. self progressBars do: [ :each |
  1188. self removeProgressBar: each ]
  1189. !
  1190. remove
  1191. self isVisible ifTrue: [
  1192. visible := false.
  1193. super remove ]
  1194. !
  1195. removeProgressBar: aProgressBar
  1196. self progressBars remove: aProgressBar ifAbsent: [].
  1197. aProgressBar wrapper asJQuery remove.
  1198. self progressBars ifEmpty: [ self remove ]
  1199. !
  1200. show
  1201. self isVisible ifFalse: [
  1202. visible := true.
  1203. super show ]
  1204. ! !
  1205. !HLProgressWidget methodsFor: 'rendering'!
  1206. renderMainOn: html
  1207. self progressBars do: [ :each |
  1208. html with: each ]
  1209. ! !
  1210. !HLProgressWidget methodsFor: 'testing'!
  1211. hasButtons
  1212. ^ false
  1213. !
  1214. isVisible
  1215. ^ visible ifNil: [ false ]
  1216. ! !
  1217. HLProgressWidget class instanceVariableNames: 'default'!
  1218. !HLProgressWidget class methodsFor: 'accessing'!
  1219. default
  1220. ^ default ifNil: [ default := self new ]
  1221. ! !
  1222. HLModalWidget subclass: #HLTabSelectionWidget
  1223. instanceVariableNames: 'tabs tabList selectedTab selectCallback cancelCallback confirmCallback'
  1224. package: 'Helios-Core'!
  1225. !HLTabSelectionWidget commentStamp!
  1226. I am a modal window used to select or create tabs.!
  1227. !HLTabSelectionWidget methodsFor: 'accessing'!
  1228. cancelCallback
  1229. ^ cancelCallback ifNil: [ [] ]
  1230. !
  1231. cancelCallback: aBlock
  1232. cancelCallback := aBlock
  1233. !
  1234. confirmCallback
  1235. ^ confirmCallback ifNil: [ [] ]
  1236. !
  1237. confirmCallback: aBlock
  1238. confirmCallback := aBlock
  1239. !
  1240. selectCallback
  1241. ^ selectCallback ifNil: [ [] ]
  1242. !
  1243. selectCallback: aBlock
  1244. selectCallback := aBlock
  1245. !
  1246. selectedTab
  1247. ^ selectedTab
  1248. !
  1249. selectedTab: aTab
  1250. selectedTab := aTab
  1251. !
  1252. tabs
  1253. ^ tabs ifNil: [ #() ]
  1254. !
  1255. tabs: aCollection
  1256. tabs := aCollection
  1257. ! !
  1258. !HLTabSelectionWidget methodsFor: 'actions'!
  1259. cancel
  1260. super cancel.
  1261. self cancelCallback value
  1262. !
  1263. confirm
  1264. super confirm.
  1265. self confirmCallback value: self selectedTab
  1266. !
  1267. selectTab: aTab
  1268. self selectedTab: aTab.
  1269. self selectCallback value: aTab
  1270. !
  1271. setupKeyBindings
  1272. super setupKeyBindings.
  1273. '.dialog' asJQuery keyup: [ :e |
  1274. e keyCode = String cr asciiValue ifTrue: [ self confirm ] ]
  1275. ! !
  1276. !HLTabSelectionWidget methodsFor: 'rendering'!
  1277. renderContentOn: html
  1278. super renderContentOn: html.
  1279. self tabList focus
  1280. !
  1281. renderMainOn: html
  1282. html div
  1283. class: 'title';
  1284. with: 'Tab selection'.
  1285. html with: self tabList
  1286. !
  1287. renderTab: aTab on: html
  1288. html
  1289. span
  1290. class: aTab cssClass;
  1291. with: aTab label
  1292. !
  1293. renderTabsOn: html
  1294. self tabs do: [ :each |
  1295. html li with: [
  1296. html a
  1297. with: [
  1298. self renderTab: each on: html ];
  1299. onClick: [ self selectTab: each ] ] ]
  1300. !
  1301. tabList
  1302. tabList ifNil: [
  1303. tabList := HLTabListWidget new.
  1304. tabList
  1305. callback: [ :tab | self selectTab: tab. tabList focus ];
  1306. selectedItem: self selectedTab;
  1307. items: self tabs ].
  1308. ^ tabList
  1309. ! !
  1310. HLWidget subclass: #HLProgressBarWidget
  1311. instanceVariableNames: 'label parent workBlock collection bar'
  1312. package: 'Helios-Core'!
  1313. !HLProgressBarWidget commentStamp!
  1314. I am a widget used to display a progress bar while iterating over a collection.!
  1315. !HLProgressBarWidget methodsFor: 'accessing'!
  1316. collection
  1317. ^ collection
  1318. !
  1319. collection: aCollection
  1320. collection := aCollection
  1321. !
  1322. label
  1323. ^ label
  1324. !
  1325. label: aString
  1326. label := aString
  1327. !
  1328. parent
  1329. ^ parent
  1330. !
  1331. parent: aProgress
  1332. parent := aProgress
  1333. !
  1334. workBlock
  1335. ^ workBlock
  1336. !
  1337. workBlock: aBlock
  1338. workBlock := aBlock
  1339. ! !
  1340. !HLProgressBarWidget methodsFor: 'actions'!
  1341. evaluateAt: anInteger
  1342. self updateProgress: (anInteger / self collection size) * 100.
  1343. anInteger <= self collection size
  1344. ifTrue: [
  1345. [
  1346. self workBlock value: (self collection at: anInteger).
  1347. self evaluateAt: anInteger + 1 ] valueWithTimeout: 10 ]
  1348. ifFalse: [ [ self remove ] valueWithTimeout: 500 ]
  1349. !
  1350. remove
  1351. self parent removeProgressBar: self
  1352. !
  1353. start
  1354. "Make sure the UI has some time to update itself between each iteration"
  1355. self evaluateAt: 1
  1356. !
  1357. updateProgress: anInteger
  1358. bar asJQuery css: 'width' put: anInteger asString, '%'
  1359. ! !
  1360. !HLProgressBarWidget methodsFor: 'rendering'!
  1361. renderContentOn: html
  1362. html span with: self label.
  1363. html div
  1364. class: 'progress';
  1365. with: [
  1366. bar := html div
  1367. class: 'bar';
  1368. style: 'width: 0%' ]
  1369. ! !
  1370. HLProgressBarWidget class instanceVariableNames: 'default'!
  1371. !HLProgressBarWidget class methodsFor: 'accessing'!
  1372. default
  1373. ^ default ifNil: [ default := self new ]
  1374. ! !
  1375. HLWidget subclass: #HLSUnit
  1376. instanceVariableNames: ''
  1377. package: 'Helios-Core'!
  1378. !HLSUnit class methodsFor: 'accessing'!
  1379. tabClass
  1380. ^ 'sunit'
  1381. !
  1382. tabLabel
  1383. ^ 'SUnit'
  1384. !
  1385. tabPriority
  1386. ^ 1000
  1387. ! !
  1388. !HLSUnit class methodsFor: 'testing'!
  1389. canBeOpenAsTab
  1390. ^ true
  1391. ! !