Helios-Core.st 37 KB

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