Helios-Core.st 38 KB

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