1
0

IDE.st 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331
  1. Widget subclass: #TabManager
  2. instanceVariableNames: 'selectedTab tabs opened ul input'
  3. category: 'IDE'!
  4. !TabManager methodsFor: 'accessing'!
  5. tabs
  6. ^tabs ifNil: [tabs := Array new]
  7. !
  8. labelFor: aWidget
  9. | label maxSize |
  10. maxSize := 15.
  11. label := aWidget label copyFrom: 0 to: (aWidget label size min: maxSize).
  12. aWidget label size > maxSize ifTrue: [
  13. label := label, '...'].
  14. ^label
  15. ! !
  16. !TabManager methodsFor: 'actions'!
  17. updateBodyMargin
  18. self setBodyMargin: '#jtalk' asJQuery height
  19. !
  20. updatePosition
  21. <jQuery('#jtalk').css('top', '').css('bottom', '0px')>
  22. !
  23. removeBodyMargin
  24. self setBodyMargin: 0
  25. !
  26. setBodyMargin: anInteger
  27. '.jtalkBody' asJQuery css: 'margin-bottom' put: anInteger asString, 'px'
  28. !
  29. onResize: aBlock
  30. <jQuery('#jtalk').resizable({
  31. handles: 'n',
  32. resize: aBlock,
  33. minHeight: 230
  34. })>
  35. !
  36. onWindowResize: aBlock
  37. <jQuery(window).resize(aBlock)>
  38. !
  39. open
  40. opened ifFalse: [
  41. 'body' asJQuery addClass: 'jtalkBody'.
  42. '#jtalk' asJQuery show.
  43. ul asJQuery show.
  44. self updateBodyMargin.
  45. selectedTab show.
  46. opened := true]
  47. !
  48. close
  49. opened ifTrue: [
  50. '#jtalk' asJQuery hide.
  51. ul asJQuery hide.
  52. selectedTab hide.
  53. self removeBodyMargin.
  54. 'body' asJQuery removeClass: 'jtalkBody'.
  55. opened := false]
  56. !
  57. newBrowserTab
  58. Browser open
  59. !
  60. selectTab: aWidget
  61. self open.
  62. selectedTab := aWidget.
  63. self tabs do: [:each |
  64. each hide].
  65. aWidget show.
  66. self update
  67. !
  68. closeTab: aWidget
  69. self removeTab: aWidget.
  70. self selectTab: self tabs last.
  71. aWidget remove.
  72. self update
  73. !
  74. search: aString
  75. | searchedClass |
  76. searchedClass := Smalltalk current at: aString.
  77. searchedClass isClass
  78. ifTrue: [Browser openOn: searchedClass]
  79. ifFalse: [ReferencesBrowser search: aString]
  80. ! !
  81. !TabManager methodsFor: 'adding/Removing'!
  82. addTab: aWidget
  83. self tabs add: aWidget.
  84. aWidget appendToJQuery: '#jtalk' asJQuery.
  85. aWidget hide
  86. !
  87. removeTab: aWidget
  88. self tabs remove: aWidget.
  89. self update
  90. ! !
  91. !TabManager methodsFor: 'initialization'!
  92. initialize
  93. super initialize.
  94. opened := true.
  95. [:html | html div id: 'jtalk'] appendToJQuery: 'body' asJQuery.
  96. 'body' asJQuery
  97. addClass: 'jtalkBody'.
  98. self appendToJQuery: '#jtalk' asJQuery.
  99. self
  100. addTab: IDETranscript current;
  101. addTab: Workspace new;
  102. addTab: TestRunner new.
  103. self selectTab: self tabs last.
  104. self
  105. onResize: [self updateBodyMargin; updatePosition];
  106. onWindowResize: [self updatePosition]
  107. ! !
  108. !TabManager methodsFor: 'rendering'!
  109. renderOn: html
  110. html div id: 'logo'.
  111. self renderToolbarOn: html.
  112. ul := html ul
  113. id: 'jtalkTabs';
  114. yourself.
  115. self renderTabs
  116. !
  117. renderTabFor: aWidget on: html
  118. | li |
  119. li := html li.
  120. selectedTab = aWidget ifTrue: [
  121. li class: 'selected'].
  122. li with: [
  123. html span class: 'ltab'.
  124. html span
  125. class: 'mtab';
  126. with: [
  127. aWidget canBeClosed ifTrue: [
  128. html span
  129. class: 'close';
  130. with: 'x';
  131. onClick: [self closeTab: aWidget]].
  132. html span with: (self labelFor: aWidget)].
  133. html span class: 'rtab'];
  134. onClick: [self selectTab: aWidget]
  135. !
  136. renderTabs
  137. ul contents: [:html |
  138. self tabs do: [:each |
  139. self renderTabFor: each on: html].
  140. html li
  141. class: 'newtab';
  142. with: [
  143. html span class: 'ltab'.
  144. html span class: 'mtab'; with: ' + '.
  145. html span class: 'rtab'];
  146. onClick: [self newBrowserTab]]
  147. !
  148. renderToolbarOn: html
  149. html div
  150. id: 'jt_toolbar';
  151. with: [
  152. input := html input
  153. class: 'implementors';
  154. yourself.
  155. input onKeyPress: [:event |
  156. event keyCode = 13 ifTrue: [
  157. self search: input asJQuery val]].
  158. html div id: 'jt_close'; onClick: [self close]]
  159. ! !
  160. !TabManager methodsFor: 'updating'!
  161. update
  162. self renderTabs
  163. ! !
  164. TabManager class instanceVariableNames: 'current'!
  165. !TabManager class methodsFor: 'instance creation'!
  166. current
  167. ^current ifNil: [current := super new]
  168. !
  169. new
  170. self shouldNotImplement
  171. ! !
  172. Widget subclass: #TabWidget
  173. instanceVariableNames: 'div'
  174. category: 'IDE'!
  175. !TabWidget methodsFor: 'accessing'!
  176. label
  177. self subclassResponsibility
  178. ! !
  179. !TabWidget methodsFor: 'actions'!
  180. open
  181. TabManager current addTab: self.
  182. TabManager current selectTab: self
  183. !
  184. show
  185. div asJQuery show
  186. !
  187. hide
  188. div asJQuery hide
  189. !
  190. remove
  191. div asJQuery remove
  192. !
  193. close
  194. TabManager current closeTab: self
  195. ! !
  196. !TabWidget methodsFor: 'rendering'!
  197. renderOn: html
  198. div := html div
  199. class: 'jtalkTool';
  200. yourself.
  201. self renderTab
  202. !
  203. renderBoxOn: html
  204. !
  205. renderButtonsOn: html
  206. !
  207. update
  208. self renderTab
  209. !
  210. renderTab
  211. div contents: [:html |
  212. html div
  213. class: 'jt_box';
  214. with: [self renderBoxOn: html].
  215. html div
  216. class: 'jt_buttons';
  217. with: [self renderButtonsOn: html]]
  218. ! !
  219. !TabWidget methodsFor: 'testing'!
  220. canBeClosed
  221. ^false
  222. ! !
  223. !TabWidget class methodsFor: 'instance creation'!
  224. open
  225. ^self new open
  226. ! !
  227. TabWidget subclass: #Workspace
  228. instanceVariableNames: 'sourceArea'
  229. category: 'IDE'!
  230. !Workspace methodsFor: 'accessing'!
  231. label
  232. ^'Workspace'
  233. ! !
  234. !Workspace methodsFor: 'actions'!
  235. clearWorkspace
  236. sourceArea clear
  237. !
  238. doIt
  239. sourceArea doIt
  240. !
  241. printIt
  242. sourceArea printIt
  243. !
  244. inspectIt
  245. sourceArea inspectIt
  246. !
  247. fileIn
  248. sourceArea fileIn
  249. ! !
  250. !Workspace methodsFor: 'rendering'!
  251. renderBoxOn: html
  252. sourceArea := SourceArea new.
  253. sourceArea renderOn: html
  254. !
  255. renderButtonsOn: html
  256. html button
  257. with: 'DoIt';
  258. title: 'ctrl+d';
  259. onClick: [self doIt].
  260. html button
  261. with: 'PrintIt';
  262. title: 'ctrl+p';
  263. onClick: [self printIt].
  264. html button
  265. with: 'InspectIt';
  266. title: 'ctrl+i';
  267. onClick: [self inspectIt].
  268. html button
  269. with: 'FileIn';
  270. title: 'ctrl+f';
  271. onClick: [self fileIn].
  272. html button
  273. with: 'Clear workspace';
  274. onClick: [self clearWorkspace]
  275. ! !
  276. TabWidget subclass: #Browser
  277. instanceVariableNames: 'selectedPackage selectedClass selectedProtocol selectedMethod commitButton packagesList classesList protocolsList methodsList sourceArea tabsList selectedTab saveButton classButtons methodButtons unsavedChanges renameButton deleteButton commitLocalButton'
  278. category: 'IDE'!
  279. !Browser methodsFor: 'accessing'!
  280. label
  281. ^selectedClass
  282. ifNil: ['Browser (nil)']
  283. ifNotNil: ['Browser: ', selectedClass name]
  284. !
  285. packages
  286. | packages |
  287. packages := Array new.
  288. Smalltalk current classes do: [:each |
  289. (packages includes: each category) ifFalse: [
  290. packages add: each category]].
  291. ^packages sort
  292. !
  293. classes
  294. ^(Smalltalk current classes
  295. select: [:each | each category = selectedPackage])
  296. sort: [:a :b | a name < b name]
  297. !
  298. protocols
  299. | klass |
  300. selectedClass ifNotNil: [
  301. selectedTab = #comment ifTrue: [^#()].
  302. klass := selectedTab = #instance
  303. ifTrue: [selectedClass]
  304. ifFalse: [selectedClass class].
  305. klass methodDictionary isEmpty ifTrue: [
  306. ^Array with: 'not yet classified'].
  307. ^klass protocols].
  308. ^Array new
  309. !
  310. methods
  311. | klass |
  312. selectedTab = #comment ifTrue: [^#()].
  313. selectedClass ifNotNil: [
  314. klass := selectedTab = #instance
  315. ifTrue: [selectedClass]
  316. ifFalse: [selectedClass class]].
  317. ^(selectedProtocol
  318. ifNil: [
  319. klass
  320. ifNil: [#()]
  321. ifNotNil: [klass methodDictionary values]]
  322. ifNotNil: [
  323. klass methodDictionary values select: [:each |
  324. each category = selectedProtocol]]) sort: [:a :b | a selector < b selector]
  325. !
  326. source
  327. selectedTab = #comment ifFalse: [
  328. ^(selectedProtocol notNil or: [selectedMethod notNil])
  329. ifFalse: [self declarationSource]
  330. ifTrue: [self methodSource]].
  331. ^selectedClass
  332. ifNil: ['']
  333. ifNotNil: [self classCommentSource]
  334. !
  335. methodSource
  336. ^selectedMethod
  337. ifNil: [self dummyMethodSource]
  338. ifNotNil: [selectedMethod source]
  339. !
  340. dummyMethodSource
  341. ^'messageSelectorAndArgumentNames
  342. "comment stating purpose of message"
  343. | temporary variable names |
  344. statements'
  345. !
  346. declarationSource
  347. ^selectedTab = #instance
  348. ifTrue: [self classDeclarationSource]
  349. ifFalse: [self metaclassDeclarationSource]
  350. !
  351. classDeclarationSource
  352. | stream |
  353. stream := '' writeStream.
  354. selectedClass ifNil: [^self classDeclarationTemplate].
  355. stream
  356. nextPutAll: selectedClass superclass asString;
  357. nextPutAll: ' subclass: #';
  358. nextPutAll: selectedClass name;
  359. nextPutAll: String lf, String tab;
  360. nextPutAll: 'instanceVariableNames: '''.
  361. selectedClass instanceVariableNames
  362. do: [:each | stream nextPutAll: each]
  363. separatedBy: [stream nextPutAll: ' '].
  364. stream
  365. nextPutAll: '''', String lf, String tab;
  366. nextPutAll: 'package: ''';
  367. nextPutAll: selectedClass category;
  368. nextPutAll: ''''.
  369. ^stream contents
  370. !
  371. metaclassDeclarationSource
  372. | stream |
  373. stream := '' writeStream.
  374. selectedClass ifNotNil: [
  375. stream
  376. nextPutAll: selectedClass asString;
  377. nextPutAll: ' class ';
  378. nextPutAll: 'instanceVariableNames: '''.
  379. selectedClass class instanceVariableNames
  380. do: [:each | stream nextPutAll: each]
  381. separatedBy: [stream nextPutAll: ' '].
  382. stream nextPutAll: ''''].
  383. ^stream contents
  384. !
  385. classCommentSource
  386. ^selectedClass comment
  387. !
  388. selectedClass
  389. ^selectedClass
  390. !
  391. classDeclarationTemplate
  392. ^'Object subclass: #nameOfSubclass
  393. instanceVariableNames: ''
  394. package: ''', self selectedPackage, ''''
  395. !
  396. selectedPackage
  397. ^selectedPackage
  398. ! !
  399. !Browser methodsFor: 'actions'!
  400. disableSaveButton
  401. saveButton ifNotNil: [
  402. saveButton at: 'disabled' put: true].
  403. unsavedChanges := false
  404. !
  405. hideClassButtons
  406. classButtons asJQuery hide
  407. !
  408. showClassButtons
  409. classButtons asJQuery show
  410. !
  411. hideMethodButtons
  412. methodButtons asJQuery hide
  413. !
  414. showMethodButtons
  415. methodButtons asJQuery show
  416. !
  417. compile
  418. self disableSaveButton.
  419. selectedTab = #comment
  420. ifTrue: [
  421. selectedClass ifNotNil: [
  422. self compileClassComment]]
  423. ifFalse: [
  424. (selectedProtocol notNil or: [selectedMethod notNil])
  425. ifFalse: [self compileDefinition]
  426. ifTrue: [self compileMethodDefinition]]
  427. !
  428. compileClassComment
  429. selectedClass comment: sourceArea val
  430. !
  431. compileMethodDefinition
  432. selectedTab = #instance
  433. ifTrue: [self compileMethodDefinitionFor: selectedClass]
  434. ifFalse: [self compileMethodDefinitionFor: selectedClass class]
  435. !
  436. compileMethodDefinitionFor: aClass
  437. | compiler method source node |
  438. source := sourceArea val.
  439. selectedProtocol ifNil: [selectedProtocol := selectedMethod category].
  440. compiler := Compiler new.
  441. compiler source: source.
  442. node := compiler parse: source.
  443. node isParseFailure ifTrue: [
  444. ^self alert: 'PARSE ERROR: ', node reason, ', position: ', node position asString].
  445. compiler currentClass: aClass.
  446. method := compiler eval: (compiler compileNode: node).
  447. method category: selectedProtocol.
  448. compiler unknownVariables do: [:each |
  449. "Do not try to redeclare javascript's objects"
  450. (window at: each) ifNil: [
  451. (self confirm: 'Declare ''', each, ''' as instance variable?') ifTrue: [
  452. self addInstanceVariableNamed: each toClass: aClass.
  453. ^self compileMethodDefinitionFor: aClass]]].
  454. aClass addCompiledMethod: method.
  455. compiler setupClass: aClass.
  456. self updateMethodsList.
  457. self selectMethod: method
  458. !
  459. compileDefinition
  460. | newClass |
  461. newClass := Compiler new loadExpression: sourceArea val.
  462. self
  463. resetClassesList;
  464. updateCategoriesList;
  465. updateClassesList
  466. !
  467. cancelChanges
  468. ^unsavedChanges
  469. ifTrue: [self confirm: 'Cancel changes?']
  470. ifFalse: [true]
  471. !
  472. removeClass
  473. (self confirm: 'Do you really want to remove ', selectedClass name, '?')
  474. ifTrue: [
  475. Smalltalk current removeClass: selectedClass.
  476. self resetClassesList.
  477. self selectClass: nil]
  478. !
  479. removeMethod
  480. self cancelChanges ifTrue: [
  481. (self confirm: 'Do you really want to remove #', selectedMethod selector, '?')
  482. ifTrue: [
  483. selectedTab = #instance
  484. ifTrue: [selectedClass removeCompiledMethod: selectedMethod]
  485. ifFalse: [selectedClass class removeCompiledMethod: selectedMethod].
  486. self selectMethod: nil]]
  487. !
  488. setMethodProtocol: aString
  489. self cancelChanges ifTrue: [
  490. (self protocols includes: aString)
  491. ifFalse: [self addNewProtocol]
  492. ifTrue: [
  493. selectedMethod category: aString.
  494. selectedProtocol := aString.
  495. selectedMethod := selectedMethod.
  496. self
  497. updateProtocolsList;
  498. updateMethodsList;
  499. updateSourceAndButtons]]
  500. !
  501. addNewProtocol
  502. | newProtocol |
  503. newProtocol := self prompt: 'New method protocol'.
  504. (newProtocol notNil and: [newProtocol notEmpty]) ifTrue: [
  505. selectedMethod category: newProtocol.
  506. self setMethodProtocol: newProtocol]
  507. !
  508. selectCategory: aCategory
  509. self cancelChanges ifTrue: [
  510. selectedPackage := aCategory.
  511. selectedClass := selectedProtocol := selectedMethod := nil.
  512. self resetClassesList.
  513. self
  514. updateCategoriesList;
  515. updateClassesList;
  516. updateProtocolsList;
  517. updateMethodsList;
  518. updateSourceAndButtons]
  519. !
  520. selectClass: aClass
  521. self cancelChanges ifTrue: [
  522. selectedClass := aClass.
  523. selectedProtocol := selectedMethod := nil.
  524. self
  525. updateClassesList;
  526. updateProtocolsList;
  527. updateMethodsList;
  528. updateSourceAndButtons]
  529. !
  530. selectProtocol: aString
  531. self cancelChanges ifTrue: [
  532. selectedProtocol := aString.
  533. selectedMethod := nil.
  534. self
  535. updateProtocolsList;
  536. updateMethodsList;
  537. updateSourceAndButtons]
  538. !
  539. selectMethod: aMethod
  540. self cancelChanges ifTrue: [
  541. selectedMethod := aMethod.
  542. self
  543. updateProtocolsList;
  544. updateMethodsList;
  545. updateSourceAndButtons]
  546. !
  547. selectTab: aString
  548. self cancelChanges ifTrue: [
  549. selectedTab := aString.
  550. self selectProtocol: nil.
  551. self updateTabsList]
  552. !
  553. renameClass
  554. | newName |
  555. newName := self prompt: 'Rename class ', selectedClass name.
  556. newName notEmpty ifTrue: [
  557. selectedClass rename: newName.
  558. self
  559. updateClassesList;
  560. updateSourceAndButtons]
  561. !
  562. addInstanceVariableNamed: aString toClass: aClass
  563. ClassBuilder new
  564. addSubclassOf: aClass superclass
  565. named: aClass name
  566. instanceVariableNames: (aClass instanceVariableNames copy add: aString; yourself)
  567. package: aClass package name
  568. !
  569. searchReferencesOf: aString
  570. ReferencesBrowser search: aString
  571. !
  572. searchClassReferences
  573. ReferencesBrowser search: selectedClass name
  574. !
  575. search: aString
  576. self cancelChanges ifTrue: [| searchedClass |
  577. searchedClass := Smalltalk current at: aString.
  578. searchedClass isClass
  579. ifTrue: [self class openOn: searchedClass]
  580. ifFalse: [self searchReferencesOf: aString]]
  581. !
  582. handleSourceAreaKeyDown: anEvent
  583. <if(anEvent.ctrlKey) {
  584. if(anEvent.keyCode === 83) { //ctrl+s
  585. self._compile();
  586. anEvent.preventDefault();
  587. return false;
  588. }
  589. }
  590. >
  591. !
  592. commitPackage
  593. selectedPackage ifNotNil: [
  594. jQuery
  595. ajax: self class commitPathJs, '/', selectedPackage, '.js'
  596. options: #{
  597. 'type' -> 'PUT'.
  598. 'data' -> (Exporter new exportPackage: selectedPackage).
  599. 'error' -> [self alert: 'Commit failed!!']
  600. }.
  601. jQuery
  602. ajax: self class commitPathJs, '/', selectedPackage, '.deploy.js'
  603. options: #{
  604. 'type' -> 'PUT'.
  605. 'data' -> (StrippedExporter new exportPackage: selectedPackage).
  606. 'error' -> [self alert: 'Commit failed!!']
  607. }.
  608. jQuery
  609. ajax: self class commitPathSt, '/', selectedPackage, '.st'
  610. options: #{
  611. 'type' -> 'PUT'.
  612. 'data' -> (ChunkExporter new exportPackage: selectedPackage).
  613. 'error' -> [self alert: 'Commit failed!!']
  614. }]
  615. !
  616. renamePackage
  617. | newName |
  618. newName := self prompt: 'Rename package ', selectedPackage.
  619. newName ifNotNil: [
  620. newName notEmpty ifTrue: [
  621. Smalltalk current renamePackage: selectedPackage to: newName.
  622. self updateCategoriesList]]
  623. !
  624. removePackage
  625. (self confirm: 'Do you really want to remove the whole package ', selectedPackage, ' with all its classes?')
  626. ifTrue: [
  627. Smalltalk current removePackage: selectedPackage.
  628. self updateCategoriesList]
  629. !
  630. commitPackageToLocalStorage
  631. | key sourceCode |
  632. selectedPackage ifNotNil: [
  633. key := 'smalltalk.packages.' , selectedPackage.
  634. sourceCode := (Exporter new exportPackage: selectedPackage).
  635. <localStorage[key] = sourceCode>]
  636. ! !
  637. !Browser methodsFor: 'initialization'!
  638. initialize
  639. super initialize.
  640. selectedTab := #instance.
  641. selectedPackage := self packages first.
  642. unsavedChanges := false
  643. ! !
  644. !Browser methodsFor: 'rendering'!
  645. renderBoxOn: html
  646. self
  647. renderTopPanelOn: html;
  648. renderTabsOn: html;
  649. renderBottomPanelOn: html
  650. !
  651. renderTopPanelOn: html
  652. html div
  653. class: 'top';
  654. with: [
  655. packagesList := html ul class: 'jt_column browser packages'.
  656. commitButton := html button
  657. class: 'jt_commit';
  658. title: 'Commit classes in this package to disk';
  659. onClick: [self commitPackage];
  660. with: 'Commit'.
  661. commitLocalButton := html button
  662. class: 'jt_commit_local';
  663. title: 'Commit classes in this package to local storage';
  664. onClick: [self commitPackageToLocalStorage];
  665. with: 'Local'.
  666. renameButton := html button
  667. class: 'jt_rename';
  668. title: 'Rename package';
  669. onClick: [self renamePackage];
  670. with: 'Rename'.
  671. deleteButton := html button
  672. class: 'jt_delete';
  673. title: 'Remove this package from the system';
  674. onClick: [self removePackage];
  675. with: 'Remove'.
  676. classesList := ClassesList on: self.
  677. classesList renderOn: html.
  678. protocolsList := html ul class: 'jt_column browser protocols'.
  679. methodsList := html ul class: 'jt_column browser methods'.
  680. self
  681. updateCategoriesList;
  682. updateClassesList;
  683. updateProtocolsList;
  684. updateMethodsList.
  685. html div class: 'jt_clear']
  686. !
  687. renderTabsOn: html
  688. tabsList := html ul class: 'jt_tabs jt_browser'.
  689. self updateTabsList.
  690. !
  691. renderBottomPanelOn: html
  692. html div
  693. class: 'jt_sourceCode';
  694. with: [
  695. sourceArea := SourceArea new.
  696. sourceArea renderOn: html.
  697. sourceArea onKeyDown: [:e |
  698. self handleSourceAreaKeyDown: e].
  699. sourceArea onKeyUp: [self updateStatus]]
  700. !
  701. renderButtonsOn: html
  702. saveButton := html button.
  703. saveButton
  704. with: 'Save';
  705. onClick: [self compile].
  706. methodButtons := html span.
  707. classButtons := html span.
  708. html div
  709. class: 'right';
  710. with: [
  711. html button
  712. with: 'DoIt';
  713. onClick: [sourceArea doIt].
  714. html button
  715. with: 'PrintIt';
  716. onClick: [sourceArea printIt].
  717. html button with: 'InspectIt';
  718. onClick: [sourceArea inspectIt]].
  719. self updateSourceAndButtons
  720. ! !
  721. !Browser methodsFor: 'testing'!
  722. canBeClosed
  723. ^true
  724. ! !
  725. !Browser methodsFor: 'updating'!
  726. updateCategoriesList
  727. packagesList contents: [:html |
  728. self packages do: [:each || li label |
  729. each isEmpty
  730. ifTrue: [label := 'Unclassified']
  731. ifFalse: [label := each].
  732. li := html li.
  733. selectedPackage = each ifTrue: [
  734. li class: 'selected'].
  735. li
  736. with: label;
  737. onClick: [self selectCategory: each]]]
  738. !
  739. updateClassesList
  740. TabManager current update.
  741. classesList updateNodes.
  742. "classesList contents: [:html |
  743. self classes do: [:each || li |
  744. li := html li.
  745. selectedClass = each ifTrue: [
  746. li class: 'selected'].
  747. li
  748. with: each name;
  749. onClick: [self selectClass: each]]]"
  750. !
  751. updateProtocolsList
  752. protocolsList contents: [:html |
  753. self protocols do: [:each || li |
  754. li := html li.
  755. selectedProtocol = each ifTrue: [
  756. li class: 'selected'].
  757. li
  758. with: each;
  759. onClick: [self selectProtocol: each]]]
  760. !
  761. updateMethodsList
  762. methodsList contents: [:html |
  763. self methods do: [:each || li |
  764. li := html li.
  765. selectedMethod = each ifTrue: [
  766. li class: 'selected'].
  767. li
  768. with: each selector;
  769. onClick: [self selectMethod: each]]]
  770. !
  771. updateTabsList
  772. tabsList contents: [:html || li |
  773. li := html li.
  774. selectedTab = #instance ifTrue: [li class: 'selected'].
  775. li
  776. with: [
  777. html span class: 'ltab'.
  778. html span class: 'mtab'; with: 'Instance'.
  779. html span class: 'rtab'];
  780. onClick: [self selectTab: #instance].
  781. li := html li.
  782. selectedTab = #class ifTrue: [li class: 'selected'].
  783. li
  784. with: [
  785. html span class: 'ltab'.
  786. html span class: 'mtab'; with: 'Class'.
  787. html span class: 'rtab'];
  788. onClick: [self selectTab: #class].
  789. li := html li.
  790. selectedTab = #comment ifTrue: [li class: 'selected'].
  791. li
  792. with: [
  793. html span class: 'ltab'.
  794. html span class: 'mtab'; with: 'Comment'.
  795. html span class: 'rtab'];
  796. onClick: [self selectTab: #comment]]
  797. !
  798. updateSourceAndButtons
  799. self disableSaveButton.
  800. classButtons contents: [:html |
  801. html button
  802. with: 'Rename class';
  803. onClick: [self renameClass].
  804. html button
  805. with: 'Remove class';
  806. onClick: [self removeClass].
  807. html button
  808. with: 'References';
  809. onClick: [self searchClassReferences]].
  810. methodButtons contents: [:html | | protocolSelect referencesSelect |
  811. html button
  812. with: 'Remove method';
  813. onClick: [self removeMethod].
  814. protocolSelect := html select.
  815. protocolSelect
  816. onChange: [ self setMethodProtocol: protocolSelect asJQuery val];
  817. with: [
  818. html option
  819. with: 'Method protocol';
  820. at: 'disabled' put: 'disabled'.
  821. html option
  822. class: 'important';
  823. with: 'New...'.
  824. self protocols do: [:each |
  825. html option with: each]].
  826. selectedMethod isNil ifFalse: [
  827. referencesSelect := html select.
  828. referencesSelect
  829. onChange: [self searchReferencesOf: referencesSelect asJQuery val];
  830. with: [
  831. html option
  832. with: 'References';
  833. at: 'disabled' put: 'disabled'.
  834. html option
  835. class: 'important';
  836. with: selectedMethod selector.
  837. selectedMethod messageSends sorted do: [:each |
  838. html option with: each]]]].
  839. selectedMethod isNil
  840. ifTrue: [
  841. self hideMethodButtons.
  842. (selectedClass isNil or: [selectedProtocol notNil])
  843. ifTrue: [self hideClassButtons]
  844. ifFalse: [self showClassButtons]]
  845. ifFalse: [
  846. self hideClassButtons.
  847. self showMethodButtons].
  848. sourceArea val: self source
  849. !
  850. updateStatus
  851. sourceArea val = self source
  852. ifTrue: [
  853. saveButton ifNotNil: [
  854. saveButton at: 'disabled' put: true].
  855. unsavedChanges := false]
  856. ifFalse: [
  857. saveButton ifNotNil: [
  858. saveButton removeAt: 'disabled'].
  859. unsavedChanges := true]
  860. !
  861. resetClassesList
  862. classesList resetNodes
  863. ! !
  864. !Browser class methodsFor: 'accessing'!
  865. commitPathJs
  866. ^'js'
  867. !
  868. commitPathSt
  869. ^'st'
  870. ! !
  871. !Browser class methodsFor: 'convenience'!
  872. openOn: aClass
  873. ^self new
  874. open;
  875. selectCategory: aClass category;
  876. selectClass: aClass
  877. !
  878. open
  879. self new open
  880. ! !
  881. TabWidget subclass: #Inspector
  882. instanceVariableNames: 'label variables object selectedVariable variablesList valueTextarea diveButton sourceArea'
  883. category: 'IDE'!
  884. !Inspector methodsFor: 'accessing'!
  885. label
  886. ^label ifNil: ['Inspector (nil)']
  887. !
  888. variables
  889. ^variables
  890. !
  891. setVariables: aCollection
  892. variables := aCollection
  893. !
  894. setLabel: aString
  895. label := aString
  896. !
  897. selectedVariable
  898. ^selectedVariable
  899. !
  900. selectedVariable: aString
  901. selectedVariable := aString
  902. !
  903. sourceArea
  904. ^sourceArea
  905. ! !
  906. !Inspector methodsFor: 'actions'!
  907. inspect: anObject
  908. object := anObject.
  909. variables := #().
  910. object inspectOn: self
  911. !
  912. dive
  913. (self variables at: self selectedVariable) inspect
  914. !
  915. refresh
  916. self
  917. inspect: object;
  918. updateVariablesList;
  919. updateValueTextarea
  920. ! !
  921. !Inspector methodsFor: 'rendering'!
  922. renderBoxOn: html
  923. self
  924. renderTopPanelOn: html;
  925. renderBottomPanelOn: html
  926. !
  927. renderTopPanelOn: html
  928. html div
  929. class: 'top';
  930. with: [
  931. variablesList := html ul class: 'jt_column variables'.
  932. valueTextarea := html textarea class: 'jt_column value'; at: 'readonly' put: 'readonly'.
  933. html div class: 'jt_tabs inspector'; with: [
  934. html button
  935. class: 'jt_button inspector refresh';
  936. with: 'Refresh';
  937. onClick: [self refresh].
  938. diveButton := html button
  939. class: 'jt_button inspector dive';
  940. with: 'Dive';
  941. onClick: [self dive]].
  942. html div class: 'jt_clear'].
  943. self
  944. updateVariablesList;
  945. updateValueTextarea.
  946. !
  947. renderBottomPanelOn: html
  948. html div
  949. class: 'jt_sourceCode';
  950. with: [
  951. sourceArea := SourceArea new
  952. receiver: object;
  953. onDoIt: [self refresh];
  954. yourself.
  955. sourceArea renderOn: html]
  956. !
  957. renderButtonsOn: html
  958. html button
  959. with: 'DoIt';
  960. onClick: [self sourceArea doIt].
  961. html button
  962. with: 'PrintIt';
  963. onClick: [self sourceArea printIt].
  964. html button
  965. with: 'InspectIt';
  966. onClick: [self sourceArea inspectIt].
  967. self updateButtons
  968. ! !
  969. !Inspector methodsFor: 'testing'!
  970. canBeClosed
  971. ^true
  972. ! !
  973. !Inspector methodsFor: 'updating'!
  974. updateVariablesList
  975. variablesList contents: [:html |
  976. self variables keys do: [:each || li |
  977. li := html li.
  978. li
  979. with: each;
  980. onClick: [self selectVariable: each].
  981. self selectedVariable = each ifTrue: [
  982. li class: 'selected']]]
  983. !
  984. selectVariable: aString
  985. self selectedVariable: aString.
  986. self
  987. updateVariablesList;
  988. updateValueTextarea;
  989. updateButtons
  990. !
  991. updateValueTextarea
  992. valueTextarea asJQuery val: (self selectedVariable isNil
  993. ifTrue: ['']
  994. ifFalse: [(self variables at: self selectedVariable) printString])
  995. !
  996. updateButtons
  997. (self selectedVariable notNil and: [(self variables at: self selectedVariable) notNil])
  998. ifFalse: [diveButton at: 'disabled' put: true]
  999. ifTrue: [diveButton removeAt: 'disabled']
  1000. ! !
  1001. !Inspector class methodsFor: 'instance creation'!
  1002. on: anObject
  1003. ^self new
  1004. inspect: anObject;
  1005. yourself
  1006. ! !
  1007. TabWidget subclass: #ReferencesBrowser
  1008. instanceVariableNames: 'implementors senders implementorsList input timer selector sendersList referencedClasses referencedClassesList'
  1009. category: 'IDE'!
  1010. !ReferencesBrowser methodsFor: 'accessing'!
  1011. implementors
  1012. ^implementors ifNil: [implementors := Array new]
  1013. !
  1014. label
  1015. ^'[References]'
  1016. !
  1017. selector
  1018. ^selector
  1019. !
  1020. senders
  1021. ^senders ifNil: [senders := Array new]
  1022. !
  1023. classesAndMetaclasses
  1024. ^Smalltalk current classes, (Smalltalk current classes collect: [:each | each class])
  1025. !
  1026. referencedClasses
  1027. ^referencedClasses ifNil: [referencedClasses := Array new]
  1028. ! !
  1029. !ReferencesBrowser methodsFor: 'actions'!
  1030. openBrowserOn: aMethod
  1031. | browser |
  1032. browser := Browser openOn: (aMethod methodClass isMetaclass
  1033. ifTrue: [aMethod methodClass instanceClass] ifFalse: [aMethod methodClass]).
  1034. aMethod methodClass isMetaclass ifTrue: [browser selectTab: #class].
  1035. browser
  1036. selectProtocol: aMethod category;
  1037. selectMethod: aMethod
  1038. !
  1039. searchReferencesFor: aString
  1040. selector := aString.
  1041. implementors := Array new.
  1042. senders := Array new.
  1043. referencedClasses := Array new.
  1044. (selector match: '^[A-Z]')
  1045. ifFalse: [self searchSelectorReferencesFor: selector]
  1046. ifTrue: [self searchReferencedClassesFor: selector]
  1047. !
  1048. search: aString
  1049. self
  1050. searchReferencesFor: aString;
  1051. updateImplementorsList;
  1052. updateSendersList;
  1053. updateReferencedClassesList
  1054. !
  1055. searchReferencedClassesFor: aString
  1056. self classesAndMetaclasses do: [:each |
  1057. each methodDictionary values do: [:value |
  1058. (((value referencedClasses select: [:each | each notNil])collect: [:each | each name]) includes: selector) ifTrue: [
  1059. self referencedClasses add: value]]]
  1060. !
  1061. searchSelectorReferencesFor: aString
  1062. self classesAndMetaclasses do: [:each |
  1063. each methodDictionary keysAndValuesDo: [:key :value |
  1064. key = selector ifTrue: [self implementors add: value]].
  1065. each methodDictionary keysAndValuesDo: [:key :value |
  1066. (value messageSends includes: selector) ifTrue: [
  1067. self senders add: value]]]
  1068. ! !
  1069. !ReferencesBrowser methodsFor: 'initialization'!
  1070. initialize
  1071. super initialize.
  1072. selector := ''
  1073. ! !
  1074. !ReferencesBrowser methodsFor: 'private'!
  1075. setInputEvents
  1076. input
  1077. onKeyUp: [timer := [self search: input asJQuery val] valueWithTimeout: 100];
  1078. onKeyDown: [timer ifNotNil: [timer clearTimeout]]
  1079. ! !
  1080. !ReferencesBrowser methodsFor: 'rendering'!
  1081. renderBoxOn: html
  1082. self
  1083. renderInputOn: html;
  1084. renderImplementorsOn: html;
  1085. renderSendersOn: html;
  1086. renderReferencedClassesOn: html
  1087. !
  1088. renderInputOn: html
  1089. input := html input
  1090. class: 'implementors';
  1091. yourself.
  1092. input asJQuery val: selector.
  1093. self setInputEvents
  1094. !
  1095. renderImplementorsOn: html
  1096. implementorsList := html ul class: 'jt_column implementors'.
  1097. self updateImplementorsList
  1098. !
  1099. renderSendersOn: html
  1100. sendersList := html ul class: 'jt_column senders'.
  1101. self updateSendersList
  1102. !
  1103. renderReferencedClassesOn: html
  1104. referencedClassesList := html ul class: 'jt_column referenced_classes'.
  1105. self updateReferencedClassesList
  1106. ! !
  1107. !ReferencesBrowser methodsFor: 'testing'!
  1108. canBeClosed
  1109. ^true
  1110. ! !
  1111. !ReferencesBrowser methodsFor: 'updating'!
  1112. updateImplementorsList
  1113. implementorsList contents: [:html |
  1114. html li
  1115. class: 'column_label';
  1116. with: 'Implementors (', self implementors size asString, ')';
  1117. style: 'font-weight: bold'.
  1118. self implementors do: [:each || li |
  1119. li := html li.
  1120. li
  1121. with: (each methodClass asString, ' >> ', self selector);
  1122. onClick: [self openBrowserOn: each]]]
  1123. !
  1124. updateSendersList
  1125. sendersList contents: [:html |
  1126. html li
  1127. class: 'column_label';
  1128. with: 'Senders (', self senders size asString, ')';
  1129. style: 'font-weight: bold'.
  1130. self senders do: [:each |
  1131. html li
  1132. with: (each methodClass asString, ' >> ', each selector);
  1133. onClick: [self openBrowserOn: each]]]
  1134. !
  1135. updateReferencedClassesList
  1136. referencedClassesList contents: [:html |
  1137. html li
  1138. class: 'column_label';
  1139. with: 'Class references (', self referencedClasses size asString, ')';
  1140. style: 'font-weight: bold'.
  1141. self referencedClasses do: [:each |
  1142. html li
  1143. with: (each methodClass asString, ' >> ', each selector);
  1144. onClick: [self openBrowserOn: each]]]
  1145. ! !
  1146. !ReferencesBrowser class methodsFor: 'instance creation'!
  1147. search: aString
  1148. ^self new
  1149. searchReferencesFor: aString;
  1150. open
  1151. ! !
  1152. Widget subclass: #SourceArea
  1153. instanceVariableNames: 'editor div receiver onDoIt'
  1154. category: 'IDE'!
  1155. !SourceArea methodsFor: 'accessing'!
  1156. val
  1157. ^editor getValue
  1158. !
  1159. val: aString
  1160. editor setValue: aString
  1161. !
  1162. currentLine
  1163. ^editor getLine: (editor getCursor line)
  1164. !
  1165. selection
  1166. ^editor getSelection
  1167. !
  1168. selectionEnd
  1169. ^textarea element selectionEnd
  1170. !
  1171. selectionStart
  1172. ^textarea element selectionStart
  1173. !
  1174. selectionStart: anInteger
  1175. textarea element selectionStart: anInteger
  1176. !
  1177. selectionEnd: anInteger
  1178. textarea element selectionEnd: anInteger
  1179. !
  1180. setEditorOn: aTextarea
  1181. <self['@editor'] = CodeMirror.fromTextArea(aTextarea, {
  1182. theme: 'jtalk',
  1183. lineNumbers: true,
  1184. enterMode: 'classic',
  1185. matchBrackets: true,
  1186. electricChars: false
  1187. })>
  1188. !
  1189. editor
  1190. ^editor
  1191. !
  1192. receiver
  1193. ^receiver ifNil: [DoIt new]
  1194. !
  1195. receiver: anObject
  1196. receiver := anObject
  1197. !
  1198. onDoIt: aBlock
  1199. onDoIt := aBlock
  1200. !
  1201. onDoIt
  1202. ^onDoIt
  1203. !
  1204. currentLineOrSelection
  1205. ^editor somethingSelected
  1206. ifFalse: [self currentLine]
  1207. ifTrue: [self selection]
  1208. ! !
  1209. !SourceArea methodsFor: 'actions'!
  1210. clear
  1211. self val: ''
  1212. !
  1213. doIt
  1214. | result |
  1215. result := self eval: self currentLineOrSelection.
  1216. self onDoIt ifNotNil: [self onDoIt value].
  1217. ^result
  1218. !
  1219. eval: aString
  1220. | compiler |
  1221. compiler := Compiler new.
  1222. [compiler parseExpression: aString] on: Error do: [:ex |
  1223. ^self alert: ex messageText].
  1224. ^(compiler load: 'doIt ^[', aString, '] value' forClass: DoIt) fn applyTo: self receiver arguments: #()
  1225. !
  1226. handleKeyDown: anEvent
  1227. <if(anEvent.ctrlKey) {
  1228. if(anEvent.keyCode === 80) { //ctrl+p
  1229. self._printIt();
  1230. anEvent.preventDefault();
  1231. return false;
  1232. }
  1233. if(anEvent.keyCode === 68) { //ctrl+d
  1234. self._doIt();
  1235. anEvent.preventDefault();
  1236. return false;
  1237. }
  1238. if(anEvent.keyCode === 73) { //ctrl+i
  1239. self._inspectIt();
  1240. anEvent.preventDefault();
  1241. return false;
  1242. }
  1243. }>
  1244. !
  1245. inspectIt
  1246. self doIt inspect
  1247. !
  1248. print: aString
  1249. | start stop |
  1250. start := Dictionary new.
  1251. stop := Dictionary new.
  1252. start at: 'line' put: (editor getCursor: false) line.
  1253. start at: 'ch' put: (editor getCursor: false) ch.
  1254. stop at: 'line' put: (start at: 'line').
  1255. stop at: 'ch' put: ((start at: 'ch') + aString size + 2).
  1256. editor replaceSelection: (editor getSelection, ' ', aString, ' ').
  1257. editor setCursor: (editor getCursor: true).
  1258. editor setSelection: stop end: start
  1259. !
  1260. printIt
  1261. self print: self doIt printString
  1262. !
  1263. fileIn
  1264. Importer new import: self currentLineOrSelection readStream
  1265. ! !
  1266. !SourceArea methodsFor: 'events'!
  1267. onKeyUp: aBlock
  1268. div onKeyUp: aBlock
  1269. !
  1270. onKeyDown: aBlock
  1271. div onKeyDown: aBlock
  1272. ! !
  1273. !SourceArea methodsFor: 'rendering'!
  1274. renderOn: html
  1275. | textarea |
  1276. div := html div class: 'source'.
  1277. div with: [textarea := html textarea].
  1278. self setEditorOn: textarea element.
  1279. div onKeyDown: [:e | self handleKeyDown: e]
  1280. ! !
  1281. Widget subclass: #ClassesList
  1282. instanceVariableNames: 'browser ul nodes'
  1283. category: 'IDE'!
  1284. !ClassesList methodsFor: 'accessing'!
  1285. category
  1286. ^self browser selectedPackage
  1287. !
  1288. nodes
  1289. nodes ifNil: [nodes := self getNodes].
  1290. ^nodes
  1291. !
  1292. browser
  1293. ^browser
  1294. !
  1295. browser: aBrowser
  1296. browser := aBrowser
  1297. !
  1298. getNodes
  1299. | classes children others |
  1300. classes := self browser classes.
  1301. children := #().
  1302. others := #().
  1303. classes do: [:each |
  1304. (classes includes: each superclass)
  1305. ifFalse: [children add: each]
  1306. ifTrue: [others add: each]].
  1307. ^children collect: [:each |
  1308. ClassesListNode on: each browser: self browser classes: others level: 0]
  1309. !
  1310. resetNodes
  1311. nodes := nil
  1312. ! !
  1313. !ClassesList methodsFor: 'rendering'!
  1314. renderOn: html
  1315. ul := html ul
  1316. class: 'jt_column browser classes';
  1317. yourself.
  1318. self updateNodes
  1319. !
  1320. updateNodes
  1321. ul contents: [:html |
  1322. self nodes do: [:each |
  1323. each renderOn: html]]
  1324. ! !
  1325. !ClassesList class methodsFor: 'instance creation'!
  1326. on: aBrowser
  1327. ^self new
  1328. browser: aBrowser;
  1329. yourself
  1330. ! !
  1331. Widget subclass: #ClassesListNode
  1332. instanceVariableNames: 'browser theClass level nodes'
  1333. category: 'IDE'!
  1334. !ClassesListNode methodsFor: ''!
  1335. renderOn: html
  1336. | li cssClass |
  1337. cssClass := ''.
  1338. li := html li
  1339. onClick: [self browser selectClass: self theClass].
  1340. li asJQuery html: self label.
  1341. self browser selectedClass = self theClass ifTrue: [
  1342. cssClass := cssClass, ' selected'].
  1343. self theClass comment isEmpty ifFalse: [
  1344. cssClass := cssClass, ' commented'].
  1345. li class: cssClass.
  1346. self nodes do: [:each |
  1347. each renderOn: html]
  1348. ! !
  1349. !ClassesListNode methodsFor: 'accessing'!
  1350. nodes
  1351. ^nodes
  1352. !
  1353. theClass
  1354. ^theClass
  1355. !
  1356. theClass: aClass
  1357. theClass := aClass
  1358. !
  1359. browser
  1360. ^browser
  1361. !
  1362. browser: aBrowser
  1363. browser := aBrowser
  1364. !
  1365. level
  1366. ^level
  1367. !
  1368. level: anInteger
  1369. level := anInteger
  1370. !
  1371. label
  1372. | str |
  1373. str := String new writeStream.
  1374. self level timesRepeat: [
  1375. str nextPutAll: '&nbsp;&nbsp;&nbsp;&nbsp;'].
  1376. str nextPutAll: self theClass name.
  1377. ^str contents
  1378. !
  1379. getNodesFrom: aCollection
  1380. | children others |
  1381. children := #().
  1382. others := #().
  1383. aCollection do: [:each |
  1384. (each superclass = self theClass)
  1385. ifTrue: [children add: each]
  1386. ifFalse: [others add: each]].
  1387. nodes:= children collect: [:each |
  1388. ClassesListNode on: each browser: self browser classes: others level: self level + 1]
  1389. ! !
  1390. !ClassesListNode class methodsFor: 'instance creation'!
  1391. on: aClass browser: aBrowser classes: aCollection level: anInteger
  1392. ^self new
  1393. theClass: aClass;
  1394. browser: aBrowser;
  1395. level: anInteger;
  1396. getNodesFrom: aCollection;
  1397. yourself
  1398. ! !
  1399. TabWidget subclass: #Debugger
  1400. instanceVariableNames: 'error selectedContext sourceArea ul ul2 inspector saveButton unsavedChanges selectedVariable selectedVariableName inspectButton'
  1401. category: 'IDE'!
  1402. !Debugger methodsFor: 'accessing'!
  1403. error
  1404. ^error
  1405. !
  1406. error: anError
  1407. error := anError
  1408. !
  1409. label
  1410. ^'[Debugger]'
  1411. !
  1412. source
  1413. ^self method
  1414. ifNil: ['Method doesn''t exist!!']
  1415. ifNotNil: [self method source]
  1416. !
  1417. method
  1418. ^selectedContext receiver class methodAt: selectedContext selector
  1419. !
  1420. arguments
  1421. ^self method
  1422. ifNil: [selectedContext temps collect: [:each | nil]]
  1423. ifNotNil: [self method arguments]
  1424. !
  1425. receiver
  1426. ^selectedContext receiver
  1427. ! !
  1428. !Debugger methodsFor: 'actions'!
  1429. selectContext: aContext
  1430. selectedContext := aContext.
  1431. selectedVariable := nil.
  1432. selectedVariableName := nil.
  1433. self
  1434. updateContextsList;
  1435. updateSourceArea;
  1436. updateInspector;
  1437. updateVariablesList;
  1438. updateStatus
  1439. !
  1440. proceed
  1441. self close.
  1442. selectedContext receiver perform: selectedContext selector withArguments: selectedContext temps
  1443. !
  1444. save
  1445. | protocol |
  1446. protocol := (selectedContext receiver class methodDictionary at: selectedContext selector) category.
  1447. selectedContext receiver class compile: sourceArea val category: protocol.
  1448. self updateStatus
  1449. !
  1450. selectVariable: anObject named: aString
  1451. selectedVariable := anObject.
  1452. selectedVariableName := aString.
  1453. inspector contents: [:html | html with: anObject printString].
  1454. self updateVariablesList
  1455. !
  1456. inspectSelectedVariable
  1457. selectedVariable inspect
  1458. ! !
  1459. !Debugger methodsFor: 'initialization'!
  1460. initialize
  1461. super initialize.
  1462. unsavedChanges = false
  1463. ! !
  1464. !Debugger methodsFor: 'rendering'!
  1465. renderTopPanelOn: html
  1466. selectedContext := self error context.
  1467. html div
  1468. class: 'top';
  1469. with: [
  1470. html div
  1471. class: 'label';
  1472. with: self error messageText.
  1473. ul := html ul
  1474. class: 'jt_column debugger contexts';
  1475. with: [self renderContext: self error context on: html]]
  1476. !
  1477. renderContext: aContext on: html
  1478. | li |
  1479. li := html li.
  1480. selectedContext = aContext ifTrue: [
  1481. li class: 'selected'].
  1482. li
  1483. with: aContext asString;
  1484. onClick: [self selectContext: aContext].
  1485. aContext home ifNotNil: [self renderContext: aContext home on: html]
  1486. !
  1487. renderBottomPanelOn: html
  1488. html div
  1489. class: 'jt_sourceCode debugger';
  1490. with: [
  1491. sourceArea := SourceArea new.
  1492. sourceArea renderOn: html].
  1493. ul2 := html ul class: 'jt_column debugger variables'.
  1494. inspector := html div class: 'jt_column debugger inspector'.
  1495. sourceArea
  1496. onKeyUp: [self updateStatus]
  1497. !
  1498. renderButtonsOn: html
  1499. saveButton := html button
  1500. with: 'Save';
  1501. onClick: [self save].
  1502. html button
  1503. with: 'DoIt';
  1504. onClick: [sourceArea doIt].
  1505. html button
  1506. with: 'PrintIt';
  1507. onClick: [sourceArea printIt].
  1508. html button
  1509. with: 'InspectIt';
  1510. onClick: [sourceArea inspectIt].
  1511. html button
  1512. with: 'Proceed';
  1513. onClick: [self proceed].
  1514. html button
  1515. with: 'Abandon';
  1516. onClick: [self close].
  1517. inspectButton := html button
  1518. class: 'jt_button debugger inspect';
  1519. with: 'Inspect';
  1520. onClick: [self inspectSelectedVariable].
  1521. self
  1522. updateSourceArea;
  1523. updateStatus;
  1524. updateVariablesList;
  1525. updateInspector
  1526. !
  1527. renderBoxOn: html
  1528. self
  1529. renderTopPanelOn: html;
  1530. renderBottomPanelOn: html
  1531. ! !
  1532. !Debugger methodsFor: 'testing'!
  1533. canBeClosed
  1534. ^true
  1535. ! !
  1536. !Debugger methodsFor: 'updating'!
  1537. updateContextsList
  1538. ul contents: [:html |
  1539. self renderContext: self error context on: html]
  1540. !
  1541. updateSourceArea
  1542. sourceArea val: self source
  1543. !
  1544. updateStatus
  1545. sourceArea val = self source
  1546. ifTrue: [
  1547. saveButton ifNotNil: [
  1548. saveButton at: 'disabled' put: true].
  1549. unsavedChanges := false]
  1550. ifFalse: [
  1551. saveButton ifNotNil: [
  1552. saveButton removeAt: 'disabled'].
  1553. unsavedChanges := true]
  1554. !
  1555. updateInspector
  1556. inspector contents: [:html |]
  1557. !
  1558. updateVariablesList
  1559. ul2 contents: [:html | | li |
  1560. li := html li
  1561. with: 'self';
  1562. onClick: [self selectVariable: self receiver named: 'self'].
  1563. selectedVariableName = 'self' ifTrue: [
  1564. li class: 'selected'].
  1565. self arguments withIndexDo: [:each :index | | param |
  1566. param := selectedContext temps at: index.
  1567. li := html li
  1568. with: each;
  1569. onClick: [self selectVariable: param named: each].
  1570. selectedVariableName = each ifTrue: [
  1571. li class: 'selected']].
  1572. self receiver class allInstanceVariableNames do: [:each | | ivar |
  1573. ivar := self receiver instVarAt: each.
  1574. li := html li
  1575. with: each;
  1576. onClick: [self selectVariable: ivar named: each].
  1577. selectedVariableName = each ifTrue: [
  1578. li class: 'selected']]].
  1579. selectedVariable ifNil: [inspectButton at: 'disabled' put: true] ifNotNil: [inspectButton removeAt: 'disabled']
  1580. ! !
  1581. ErrorHandler subclass: #DebugErrorHandler
  1582. instanceVariableNames: ''
  1583. category: 'IDE'!
  1584. !DebugErrorHandler methodsFor: 'error handling'!
  1585. handleError: anError
  1586. [Debugger new
  1587. error: anError;
  1588. open] on: Error do: [:error |
  1589. ErrorHandler new handleError: error]
  1590. ! !
  1591. !DebugErrorHandler class methodsFor: 'initialization'!
  1592. initialize
  1593. self register
  1594. ! !
  1595. TabWidget subclass: #ProgressBar
  1596. instanceVariableNames: 'percent progressDiv div'
  1597. category: 'IDE'!
  1598. !ProgressBar methodsFor: 'accessing'!
  1599. percent
  1600. ^percent ifNil: [0]
  1601. !
  1602. percent: aNumber
  1603. percent := aNumber
  1604. ! !
  1605. !ProgressBar methodsFor: 'rendering'!
  1606. renderOn: html
  1607. div := html div
  1608. class: 'progress_bar';
  1609. yourself.
  1610. self renderProgressBar
  1611. !
  1612. renderProgressBar
  1613. div contents: [:html |
  1614. html div
  1615. class: 'progress';
  1616. style: 'width:', self percent asString, '%']
  1617. ! !
  1618. !ProgressBar methodsFor: 'updating'!
  1619. updatePercent: aNumber
  1620. self percent: aNumber.
  1621. self renderProgressBar
  1622. ! !
  1623. TabWidget subclass: #TestRunner
  1624. instanceVariableNames: 'selectedCategories packagesList selectedClasses classesList selectedMethods progressBar methodsList result statusDiv'
  1625. category: 'IDE'!
  1626. !TestRunner methodsFor: 'accessing'!
  1627. label
  1628. ^'SUnit'
  1629. !
  1630. packages
  1631. | packages |
  1632. packages := Array new.
  1633. self allClasses do: [:each |
  1634. (packages includes: each category) ifFalse: [
  1635. packages add: each category]].
  1636. ^packages sort
  1637. !
  1638. classes
  1639. ^(self allClasses
  1640. select: [:each | self selectedCategories includes: each category])
  1641. sort: [:a :b | a name > b name]
  1642. !
  1643. selectedCategories
  1644. ^selectedCategories ifNil: [selectedCategories := Array new]
  1645. !
  1646. allClasses
  1647. ^TestCase allSubclasses
  1648. !
  1649. selectedClasses
  1650. ^selectedClasses ifNil: [selectedClasses := Array new]
  1651. !
  1652. progressBar
  1653. ^progressBar ifNil: [progressBar := ProgressBar new]
  1654. !
  1655. statusInfo
  1656. ^self printTotal, self printPasses, self printErrors, self printFailures
  1657. !
  1658. result
  1659. ^result
  1660. !
  1661. testCases
  1662. | testCases |
  1663. testCases := #().
  1664. self selectedClasses do: [:each | testCases addAll: each buildSuite].
  1665. ^testCases
  1666. ! !
  1667. !TestRunner methodsFor: 'actions'!
  1668. selectAllCategories
  1669. self packages do: [:each |
  1670. (selectedCategories includes: each) ifFalse: [
  1671. self selectedCategories add: each]].
  1672. self
  1673. updateCategoriesList;
  1674. updateClassesList
  1675. !
  1676. toggleCategory: aCategory
  1677. (self isSelectedCategory: aCategory)
  1678. ifFalse: [selectedCategories add: aCategory]
  1679. ifTrue: [selectedCategories remove: aCategory].
  1680. self
  1681. updateCategoriesList;
  1682. updateClassesList
  1683. !
  1684. toggleClass: aClass
  1685. (self isSelectedClass: aClass)
  1686. ifFalse: [selectedClasses add: aClass]
  1687. ifTrue: [selectedClasses remove: aClass].
  1688. self
  1689. updateClassesList
  1690. !
  1691. selectAllClasses
  1692. self classes do: [:each |
  1693. (selectedClasses includes: each) ifFalse: [
  1694. self selectedClasses add: each]].
  1695. self
  1696. updateCategoriesList;
  1697. updateClassesList
  1698. !
  1699. run: aCollection
  1700. result := TestResult new.
  1701. self
  1702. updateStatusDiv;
  1703. updateMethodsList.
  1704. self progressBar updatePercent: 0.
  1705. result total: aCollection size.
  1706. aCollection do: [:each |
  1707. [each runCaseFor: result.
  1708. self progressBar updatePercent: result runs / result total * 100.
  1709. self updateStatusDiv.
  1710. self updateMethodsList] valueWithTimeout: 100].
  1711. !
  1712. performFailure: aTestCase
  1713. aTestCase perform: aTestCase selector
  1714. ! !
  1715. !TestRunner methodsFor: 'initialization'!
  1716. initialize
  1717. super initialize.
  1718. result := TestResult new
  1719. ! !
  1720. !TestRunner methodsFor: 'printing'!
  1721. printErrors
  1722. ^self result errors size asString , ' errors, '
  1723. !
  1724. printFailures
  1725. ^self result failures size asString, ' failures'
  1726. !
  1727. printPasses
  1728. ^(self result total - self result errors size - self result failures size) asString , ' passes, '
  1729. !
  1730. printTotal
  1731. ^self result total asString, ' runs, '
  1732. ! !
  1733. !TestRunner methodsFor: 'rendering'!
  1734. renderBoxOn: html
  1735. self
  1736. renderCategoriesOn: html;
  1737. renderClassesOn: html;
  1738. renderResultsOn: html
  1739. !
  1740. renderButtonsOn: html
  1741. html button
  1742. with: 'Run selected';
  1743. onClick: [self run: self testCases]
  1744. !
  1745. renderCategoriesOn: html
  1746. packagesList := html ul class: 'jt_column sunit packages'.
  1747. self updateCategoriesList
  1748. !
  1749. renderClassesOn: html
  1750. classesList := html ul class: 'jt_column sunit classes'.
  1751. self updateClassesList
  1752. !
  1753. renderResultsOn: html
  1754. statusDiv := html div.
  1755. html with: self progressBar.
  1756. methodsList := html ul class: 'jt_column sunit results'.
  1757. self updateMethodsList.
  1758. self updateStatusDiv
  1759. !
  1760. renderFailuresOn: html
  1761. self result failures do: [:each |
  1762. html li
  1763. class: 'failures';
  1764. with: each class name, ' >> ', each selector;
  1765. onClick: [self performFailure: each]]
  1766. !
  1767. renderErrorsOn: html
  1768. self result errors do: [:each |
  1769. html li
  1770. class: 'errors';
  1771. with: each class name, ' >> ', each selector;
  1772. onClick: [self performFailure: each]]
  1773. ! !
  1774. !TestRunner methodsFor: 'testing'!
  1775. isSelectedClass: aClass
  1776. ^(self selectedClasses includes: aClass)
  1777. !
  1778. isSelectedCategory: aCategory
  1779. ^(self selectedCategories includes: aCategory)
  1780. ! !
  1781. !TestRunner methodsFor: 'updating'!
  1782. updateCategoriesList
  1783. packagesList contents: [:html |
  1784. html li
  1785. class: 'all';
  1786. with: 'All';
  1787. onClick: [self selectAllCategories].
  1788. self packages do: [:each || li |
  1789. li := html li.
  1790. (self selectedCategories includes: each) ifTrue: [
  1791. li class: 'selected'].
  1792. li
  1793. with: each;
  1794. onClick: [self toggleCategory: each]]]
  1795. !
  1796. updateClassesList
  1797. classesList contents: [:html |
  1798. (self selectedCategories isEmpty) ifFalse: [
  1799. html li
  1800. class: 'all';
  1801. with: 'All';
  1802. onClick: [self selectAllClasses]].
  1803. self classes do: [:each || li |
  1804. li := html li.
  1805. (self selectedClasses includes: each) ifTrue: [
  1806. li class: 'selected'].
  1807. li
  1808. with: each name;
  1809. onClick: [self toggleClass: each]]]
  1810. !
  1811. updateMethodsList
  1812. methodsList contents: [:html |
  1813. self renderErrorsOn: html.
  1814. self renderFailuresOn: html]
  1815. !
  1816. updateStatusDiv
  1817. statusDiv class: 'sunit status ', result status.
  1818. statusDiv contents: [:html |
  1819. html span with: self statusInfo]
  1820. ! !
  1821. TabWidget subclass: #IDETranscript
  1822. instanceVariableNames: 'textarea'
  1823. category: 'IDE'!
  1824. !IDETranscript methodsFor: 'accessing'!
  1825. label
  1826. ^'Transcript'
  1827. ! !
  1828. !IDETranscript methodsFor: 'actions'!
  1829. clear
  1830. textarea asJQuery val: ''
  1831. !
  1832. cr
  1833. textarea asJQuery val: textarea asJQuery val, String cr.
  1834. !
  1835. show: anObject
  1836. textarea asJQuery val: textarea asJQuery val, anObject asString.
  1837. !
  1838. open
  1839. TabManager current
  1840. open;
  1841. selectTab: self
  1842. ! !
  1843. !IDETranscript methodsFor: 'rendering'!
  1844. renderBoxOn: html
  1845. textarea := html textarea.
  1846. textarea
  1847. class: 'jt_transcript';
  1848. at: 'spellcheck' put: 'false'
  1849. !
  1850. renderButtonsOn: html
  1851. html button
  1852. with: 'Clear transcript';
  1853. onClick: [self clear]
  1854. ! !
  1855. IDETranscript class instanceVariableNames: 'current'!
  1856. !IDETranscript class methodsFor: 'initialization'!
  1857. initialize
  1858. Transcript register: self current
  1859. ! !
  1860. !IDETranscript class methodsFor: 'instance creation'!
  1861. new
  1862. self shouldNotImplement
  1863. !
  1864. open
  1865. TabManager current
  1866. open;
  1867. selectTab: self current
  1868. !
  1869. current
  1870. ^current ifNil: [current := super new]
  1871. ! !
  1872. !Object methodsFor: '*IDE'!
  1873. inspect
  1874. Inspector new
  1875. inspect: self;
  1876. open
  1877. !
  1878. inspectOn: anInspector
  1879. | variables |
  1880. variables := Dictionary new.
  1881. variables at: '#self' put: self.
  1882. self class allInstanceVariableNames do: [:each |
  1883. variables at: each put: (self instVarAt: each)].
  1884. anInspector
  1885. setLabel: self printString;
  1886. setVariables: variables
  1887. ! !
  1888. !Date methodsFor: '*IDE'!
  1889. inspectOn: anInspector
  1890. | variables |
  1891. variables := Dictionary new.
  1892. variables at: '#self' put: self.
  1893. variables at: '#year' put: self year.
  1894. variables at: '#month' put: self month.
  1895. variables at: '#day' put: self day.
  1896. variables at: '#hours' put: self hours.
  1897. variables at: '#minutes' put: self minutes.
  1898. variables at: '#seconds' put: self seconds.
  1899. variables at: '#milliseconds' put: self milliseconds.
  1900. anInspector
  1901. setLabel: self printString;
  1902. setVariables: variables
  1903. ! !
  1904. !Collection methodsFor: '*IDE'!
  1905. inspectOn: anInspector
  1906. | variables |
  1907. variables := Dictionary new.
  1908. variables at: '#self' put: self.
  1909. self withIndexDo: [:each :i |
  1910. variables at: i put: each].
  1911. anInspector
  1912. setLabel: self printString;
  1913. setVariables: variables
  1914. ! !
  1915. !String methodsFor: '*IDE'!
  1916. inspectOn: anInspector
  1917. | label |
  1918. super inspectOn: anInspector.
  1919. self printString size > 30
  1920. ifTrue: [label := (self printString copyFrom: 1 to: 30), '...''']
  1921. ifFalse: [label := self printString].
  1922. anInspector setLabel: label
  1923. ! !
  1924. !MethodContext methodsFor: '*IDE'!
  1925. inspectOn: anInspector
  1926. | variables |
  1927. variables := Dictionary new.
  1928. variables at: '#self' put: self.
  1929. variables at: '#home' put: self home.
  1930. variables at: '#receiver' put: self receiver.
  1931. variables at: '#selector' put: self selector.
  1932. variables at: '#temps' put: self temps.
  1933. self class instanceVariableNames do: [:each |
  1934. variables at: each put: (self instVarAt: each)].
  1935. anInspector
  1936. setLabel: self printString;
  1937. setVariables: variables
  1938. ! !
  1939. !Dictionary methodsFor: '*IDE'!
  1940. inspectOn: anInspector
  1941. | variables |
  1942. variables := Dictionary new.
  1943. variables at: '#self' put: self.
  1944. variables at: '#keys' put: self keys.
  1945. self keysAndValuesDo: [:key :value |
  1946. variables at: key put: value].
  1947. anInspector
  1948. setLabel: self printString;
  1949. setVariables: variables
  1950. ! !