Browse Source

Improved the class browser

Nicolas Petton 13 years ago
parent
commit
835bec79dd
4 changed files with 543 additions and 474 deletions
  1. 26 9
      css/jtalk.css
  2. 200 356
      js/IDE.js
  3. 6 1
      js/boot.js
  4. 311 108
      st/IDE.st

+ 26 - 9
css/jtalk.css

@@ -106,9 +106,14 @@ body.jtalkBody {
 
 .jtalkTool .jt_buttons {
     position: absolute;
+    width: 98%;
     bottom: 15px;    
 }
 
+.jtalkTool .jt_buttons .right {
+    float: right;
+}
+
 .jtalkTool .important {
     font-weight: bold;
 }
@@ -123,7 +128,8 @@ body.jtalkBody {
     font-size: 12px;
 }
 
-.jtalkTool textarea {
+.jtalkTool textarea,
+.jtalkTool input {
     border: 1px solid;
     border-color: #a8a8a8;
     font-family: Arial, Helvetica, sans;
@@ -159,7 +165,7 @@ body.jtalkBody {
     border-color: #a8a8a8;
     height: 130px;
     overflow-y: scroll;
-    background: white;
+    background: #fff;
     position: absolute;
     top: 0;
 }
@@ -183,6 +189,15 @@ body.jtalkBody {
     left: 25.2%
 }
 
+.jtalkTool .jt_column.classes ul {
+    margin-left: 0;
+}
+
+.jtalkTool .jt_column.classes ul li {
+    padding-left: 10px;
+    margin-left: 0;
+}
+
 .jtalkTool .jt_column.protocols {
     left: 50.4%
 }
@@ -195,6 +210,8 @@ body.jtalkBody {
     list-style-type: none;
     padding-left: 5px;
     cursor: pointer;
+    color: #333;
+    font-weight: bold;
 }
 
 .jtalkTool .jt_column li.selected {
@@ -216,7 +233,8 @@ body.jtalkBody {
 }
 
 .jtalkTool .jt_tabs li {
-    color: #8c8c8c;
+    color: #666;
+    font-weight: bold;
     cursor: pointer;
     list-style-type: none;
     float: left;
@@ -234,11 +252,11 @@ body.jtalkBody {
     line-height: 18px;
 }
 
-.jtalkTool .jt_tabs li:hover {
-    background: #08c;
-    color: white;
-    border-color: #08c;
-}
+/* .jtalkTool .jt_tabs li:hover { */
+/*     background: #08c; */
+/*     color: white; */
+/*     border-color: #08c; */
+/* } */
 
 .jtalkTool .jt_tabs li.selected,
 .jtalkTool .jt_tabs li.selected:hover {
@@ -298,4 +316,3 @@ body.jtalkBody {
 	color: #000;
 	cursor: default
 }
-

File diff suppressed because it is too large
+ 200 - 356
js/IDE.js


+ 6 - 1
js/boot.js

@@ -323,7 +323,12 @@ function Smalltalk(){
 	if(typeof jsProperty === "function") {
 	    return jsProperty.apply(receiver, args);
 	} else if(jsProperty !== undefined) {
-	    return jsProperty
+	    if(args[0]) {
+		receiver[jsSelector] = args[0];
+		return nil;
+	    } else {
+		return jsProperty
+	    }
 	}
 	smalltalk.Error._signal_(receiver + ' is not a Jtalk object and "' + jsSelector + '" is undefined')
     };

+ 311 - 108
st/IDE.st

@@ -238,120 +238,38 @@ open
 ! !
 
 TabWidget subclass: #Workspace
-	instanceVariableNames: 'textarea'
+	instanceVariableNames: 'sourceArea'
 	category: 'IDE'!
 
 !Workspace methodsFor: 'accessing'!
 
 label
     ^'[Workspace]'
-!
-
-selection
-    <return document.selection>
-!
-
-selectionStart
-    <return jQuery('.jt_workspace')[0].selectionStart>
-!
-
-selectionEnd
-    <return jQuery('.jt_workspace')[0].selectionEnd>
-!
-
-selectionStart: anInteger
-    <jQuery('.jt_workspace')[0].selectionStart = anInteger>
-!
-
-selectionEnd: anInteger
-    <jQuery('.jt_workspace')[0].selectionEnd = anInteger>
-!
-
-currentLine
-    | lines startLine endLine|
-    lines := textarea asJQuery val tokenize: String lf.
-    startLine := endLine := 0.
-    lines do: [:each |
-	endLine := startLine + each size.
-	startLine := endLine + 1.
-	endLine >= self selectionStart ifTrue: [
-	    self selectionEnd: endLine.
-	    ^each]]
 ! !
 
 !Workspace methodsFor: 'actions'!
 
-handleKeyDown: anEvent
-    <if(anEvent.ctrlKey) {
-		if(anEvent.keyCode === 80) { //ctrl+p
-			self._printIt();
-			anEvent.preventDefault();
-			return false;
-		}
-		if(anEvent.keyCode === 68) { //ctrl+d
-			self._doIt();
-			anEvent.preventDefault();
-			return false;
-		}
-		if(anEvent.keyCode === 73) { //ctrl+i
-			self._inspectIt();
-			anEvent.preventDefault();
-			return false;
-		}
-	}>
-!
-
 clearWorkspace
-    textarea asJQuery val: ''
+    sourceArea clear
 !
 
 doIt
-    | selection |
-    textarea asJQuery focus.
-    self selectionStart = self selectionEnd
-	ifTrue: [selection := self currentLine]
-	ifFalse: [
-	    selection := textarea asJQuery val copyFrom: self selectionStart + 1 to: self selectionEnd + 1].
-    ^self eval: selection
+   sourceArea doIt
 !
 
 printIt
-    self print: self doIt printString
-!
-
-print: aString
-    | start |
-    start := self selectionEnd.
-    textarea asJQuery val: (
-	(textarea asJQuery val copyFrom: 1 to: start),
-	' ', aString, ' ',
-	(textarea asJQuery val copyFrom: start + 1 to: textarea asJQuery val size)).
-    self selectionStart: start.
-    self selectionEnd: start + aString size + 2
-!
-
-eval: aString
-    | compiler node |
-    compiler := Compiler new.
-    node := compiler parseExpression: aString.
-    node isParseFailure ifTrue: [
-	^self alert: node reason, ', position: ', node position].
-    ^compiler loadExpression: aString
+	sourceArea printIt
 !
 
 inspectIt
-    self doIt inspect
+    sourceArea inspectIt
 ! !
 
 !Workspace methodsFor: 'rendering'!
 
 renderBoxOn: html
-    textarea := html textarea.
-    textarea asJQuery call: 'tabby'.
-    textarea onKeyDown: [:e | self handleKeyDown: e].
-    textarea 
-	class: 'jt_workspace';
-	at: 'spellcheck' put: 'false'
+    sourceArea := SourceArea new.
+    sourceArea renderOn: html
 !
 
 renderButtonsOn: html
@@ -443,7 +361,7 @@ clear
 ! !
 
 TabWidget subclass: #Browser
-	instanceVariableNames: 'selectedCategory selectedClass selectedProtocol selectedMethod commitButton categoriesList classesList protocolsList methodsList sourceTextarea tabsList selectedTab saveButton classButtons methodButtons unsavedChanges input'
+	instanceVariableNames: 'selectedCategory selectedClass selectedProtocol selectedMethod commitButton categoriesList classesList protocolsList methodsList sourceArea tabsList selectedTab saveButton classButtons methodButtons unsavedChanges input'
 	category: 'IDE'!
 
 !Browser methodsFor: 'accessing'!
@@ -567,15 +485,14 @@ metaclassDeclarationSource
 
 classCommentSource
     ^selectedClass comment
+!
+
+selectedClass
+	^selectedClass
 ! !
 
 !Browser methodsFor: 'actions'!
 
-enableSaveButton
-    saveButton removeAt: 'disabled'.
-    unsavedChanges := true
-!
-
 disableSaveButton
     saveButton ifNotNil: [
 	saveButton at: 'disabled' put: true].
@@ -609,7 +526,7 @@ compile
 !
 
 compileClassComment
-    selectedClass comment: sourceTextarea asJQuery val
+    selectedClass comment: sourceArea val
 !
 
 compileMethodDefinition
@@ -620,7 +537,7 @@ compileMethodDefinition
 
 compileMethodDefinitionFor: aClass
     | compiler method source node |
-    source := sourceTextarea asJQuery val.
+    source := sourceArea val.
     selectedProtocol ifNil: [selectedProtocol := selectedMethod category].
     compiler := Compiler new.
     node := compiler parse: source.
@@ -641,8 +558,9 @@ compileMethodDefinitionFor: aClass
 
 compileDefinition
     | newClass |
-    newClass := Compiler new loadExpression: sourceTextarea asJQuery val.
+    newClass := Compiler new loadExpression: sourceArea textarea asJQuery val.
     self 
+	resetClassesList;
 	updateCategoriesList;
 	updateClassesList
 !
@@ -671,6 +589,7 @@ removeClass
     (self confirm: 'Do you really want to remove ', selectedClass name, '?')
 	ifTrue: [
 	    Smalltalk current basicDelete: selectedClass name.
+	    self resetClassesList.
 	    self selectClass: nil]
 !
 
@@ -710,6 +629,7 @@ selectCategory: aCategory
     self cancelChanges ifTrue: [
 	selectedCategory := aCategory.
 	selectedClass := selectedProtocol := selectedMethod :=  nil.
+	self resetClassesList.
 	self 
 	    updateCategoriesList;
 	    updateClassesList;
@@ -814,7 +734,8 @@ renderTopPanelOn: html
 		title: 'Commit classes in this category to disk';
 		onClick: [self commitCategory];
 		with: 'Commit category'.
-	    classesList := html ul class: 'jt_column browser classes'.
+	    classesList := ClassesList on: self.
+	    classesList renderOn: html.
 	    protocolsList := html ul class: 'jt_column browser protocols'.
 	    methodsList := html ul class: 'jt_column browser methods'.
 	    self
@@ -834,11 +755,10 @@ renderBottomPanelOn: html
     html div
 	class: 'jt_sourceCode';
 	with: [
-	    sourceTextarea := html textarea 
-		onKeyPress: [self enableSaveButton];
-		class: 'source';
-		at: 'spellcheck' put: 'false'.
-	    sourceTextarea asJQuery call: 'tabby']
+	    sourceArea := SourceArea new.
+	    sourceArea renderOn: html.
+	    sourceArea textarea
+		onKeyUp: [self updateStatus]]
 !
 
 renderButtonsOn: html
@@ -848,6 +768,17 @@ renderButtonsOn: html
 	onClick: [self compile].
     methodButtons := html span.
     classButtons := html span.
+    html div 
+	class: 'right';
+	with: [
+		html button
+			with: 'DoIt';
+			onClick: [sourceArea doIt].
+		html button
+			with: 'PrintIt';
+			onClick: [sourceArea printIt].
+		html button with: 'InspectIt';
+			onClick: [sourceArea inspectit]]. 
     self updateSourceAndButtons
 !
 
@@ -863,7 +794,7 @@ renderInputOn: html
 !Browser methodsFor: 'testing'!
 
 canBeClosed
-    ^true
+	^true
 ! !
 
 !Browser methodsFor: 'updating'!
@@ -884,14 +815,15 @@ updateCategoriesList
 
 updateClassesList
     TabManager current update.
-    classesList contents: [:html |
+    classesList updateNodes.
+    "classesList contents: [:html |
 	self classes do: [:each || li |
 	    li := html li.
 	    selectedClass = each ifTrue: [
 		li class: 'selected'].
 	    li
 		with: each name;
-		onClick: [self selectClass: each]]]
+		onClick: [self selectClass: each]]]"
 !
 
 updateProtocolsList
@@ -983,7 +915,23 @@ updateSourceAndButtons
 		ifFalse: [
 	    		self hideClassButtons.
 	    		self showMethodButtons].
-    	sourceTextarea asJQuery val: self source
+    	sourceArea val: self source
+!
+
+updateStatus
+	sourceArea textarea asJQuery val = self source
+		ifTrue: [
+			saveButton ifNotNil: [
+				saveButton at: 'disabled' put: true].
+    			unsavedChanges := false]
+		ifFalse: [
+			saveButton ifNotNil: [
+    				saveButton removeAt: 'disabled'].
+    			unsavedChanges := true]
+!
+
+resetClassesList
+	classesList resetNodes
 ! !
 
 !Browser class methodsFor: 'accessing'!
@@ -1322,6 +1270,261 @@ search: aString
 		open
 ! !
 
+Widget subclass: #SourceArea
+	instanceVariableNames: 'textarea'
+	category: 'IDE'!
+
+!SourceArea methodsFor: 'accessing'!
+
+val
+    ^textarea asJQuery val
+!
+
+val: aString
+    textarea asJQuery val: aString
+!
+
+currentLine
+    | lines startLine endLine|
+    lines := textarea asJQuery val tokenize: String lf.
+    startLine := endLine := 0.
+    lines do: [:each |
+	endLine := startLine + each size.
+	startLine := endLine + 1.
+	endLine >= self selectionStart ifTrue: [
+	    self selectionEnd: endLine.
+	    ^each]]
+!
+
+selection
+    <return document.selection>
+!
+
+selectionEnd
+   ^textarea element selectionEnd
+!
+
+selectionStart
+   ^textarea element selectionStart
+!
+
+selectionStart: anInteger
+   textarea element selectionStart: anInteger
+!
+
+selectionEnd: anInteger
+   textarea element selectionEnd: anInteger
+!
+
+textarea
+	^textarea
+! !
+
+!SourceArea methodsFor: 'actions'!
+
+clear
+    textarea asJQuery val: ''
+!
+
+doIt
+    | selection |
+    textarea asJQuery focus.
+    self selectionStart = self selectionEnd
+	ifTrue: [selection := self currentLine]
+	ifFalse: [
+	    selection := textarea asJQuery val copyFrom: self selectionStart + 1 to: self selectionEnd + 1].
+    ^self eval: selection
+!
+
+eval: aString
+    | compiler node |
+    compiler := Compiler new.
+    node := compiler parseExpression: aString.
+    node isParseFailure ifTrue: [
+	^self alert: node reason, ', position: ', node position].
+    ^compiler loadExpression: aString
+!
+
+handleKeyDown: anEvent
+    <if(anEvent.ctrlKey) {
+		if(anEvent.keyCode === 80) { //ctrl+p
+			self._printIt();
+			anEvent.preventDefault();
+			return false;
+		}
+		if(anEvent.keyCode === 68) { //ctrl+d
+			self._doIt();
+			anEvent.preventDefault();
+			return false;
+		}
+		if(anEvent.keyCode === 73) { //ctrl+i
+			self._inspectIt();
+			anEvent.preventDefault();
+			return false;
+		}
+	}>
+!
+
+inspectIt
+    self doIt inspect
+!
+
+print: aString
+    | start |
+    start := self selectionEnd.
+    textarea asJQuery val: (
+	(textarea asJQuery val copyFrom: 1 to: start),
+	' ', aString, ' ',
+	(textarea asJQuery val copyFrom: start + 1 to: textarea asJQuery val size)).
+    self selectionStart: start.
+    self selectionEnd: start + aString size + 2
+!
+
+printIt
+    self print: self doIt printString
+! !
+
+!SourceArea methodsFor: 'rendering'!
+
+renderOn: html
+    textarea := html textarea.
+    textarea asJQuery call: 'tabby'.
+    textarea onKeyDown: [:e | self handleKeyDown: e].
+    textarea 
+	class: 'jt_workspace';
+	at: 'spellcheck' put: 'false'
+! !
+
+Widget subclass: #ClassesList
+	instanceVariableNames: 'browser ul nodes'
+	category: 'IDE'!
+
+!ClassesList methodsFor: 'accessing'!
+
+category
+	^self browser selectedCategory
+!
+
+nodes
+	nodes ifNil: [nodes := self getNodes].
+	^nodes
+!
+
+browser
+	^browser
+!
+
+browser: aBrowser
+	browser := aBrowser
+!
+
+getNodes
+	^(self browser classes select: [:each |
+		(self browser classes includes: each superclass) not])
+			collect: [:each |
+				ClassesListNode on: each browser: self browser level: 0]
+!
+
+resetNodes
+	nodes := nil
+! !
+
+!ClassesList methodsFor: 'rendering'!
+
+renderOn: html
+	ul := html ul
+		class: 'jt_column browser classes';
+		yourself.
+	self updateNodes
+!
+
+updateNodes
+	ul contents: [:html |
+		self nodes do: [:each |
+			each renderOn: html]]
+! !
+
+!ClassesList class methodsFor: 'instance creation'!
+
+on: aBrowser
+	^self new 
+		browser: aBrowser; 
+		yourself
+! !
+
+Widget subclass: #ClassesListNode
+	instanceVariableNames: 'browser theClass level nodes'
+	category: 'IDE'!
+
+!ClassesListNode methodsFor: 'accessing'!
+
+nodes
+	^nodes ifNil: [nodes := self getNodes]
+!
+
+theClass
+	^theClass
+!
+
+theClass: aClass
+	theClass := aClass
+!
+
+browser
+	^browser
+!
+
+browser: aBrowser
+	browser := aBrowser
+!
+
+level
+	^level
+!
+
+level: anInteger
+	level := anInteger
+!
+
+label
+	| str |
+	str := String new writeStream.
+	self level timesRepeat: [
+		str nextPutAll: '&nbsp;&nbsp;&nbsp;&nbsp;'].
+	str nextPutAll: self theClass name.
+	^str contents
+!
+
+getNodes
+	^(self browser classes select: [:each |
+		each superclass = self theClass])
+			collect: [:each |
+				ClassesListNode on: each browser: self browser level: self level + 1]
+! !
+
+!ClassesListNode methodsFor: 'rendering'!
+
+renderOn: html
+	| li |
+	li := html li 
+		onClick: [self browser selectClass: self theClass].
+	li asJQuery contents: self label.
+	self browser selectedClass = self theClass ifTrue:  [
+		li class: 'selected'].
+	self nodes do: [:each |
+		each renderOn: html]
+! !
+
+!ClassesListNode class methodsFor: 'instance creation'!
+
+on: aClass browser: aBrowser level: anInteger
+	^self new
+		theClass: aClass;
+		browser: aBrowser;
+		level: anInteger;
+		yourself
+! !
+
 !Object methodsFor: '*IDE'!
 
 inspect

Some files were not shown because too many files changed in this diff