Helios-Core.st 35 KB

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