Helios-Core.st 39 KB

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