Browse Source

- Better layout and splitter handling
- More browser commands
- css tweaks

Nicolas Petton 11 years ago
parent
commit
adbf95b67e

+ 85 - 47
css/helios.css

@@ -1,6 +1,7 @@
 body {
     font-size: 11px;
-    background: #f1f1f1;
+    font-family: "Lucida Grande", helvetica, arial, sans;
+    background: #ddd;
 }
 
 .clearfix:after {
@@ -60,7 +61,7 @@ i {
 
 .CodeMirror pre {
     font-family: Menlo, Monaco, "Lucida Console", Courier, monospace;
-    line-height: 15px;
+    line-height: 16px;
 }
 
 .btn, .btn-group > .btn, .btn-group > .dropdown-menu {
@@ -72,14 +73,15 @@ i {
     line-height: 16px;
 }
 
-.navbar-inner {
+.navbar-fixed-top .navbar-inner {
     min-height: 22px;
     background-color: #dbdbdb;
-    border: 1px solid #666;
+    border-bottom: 1px solid #666;
     background-image: linear-gradient(top, #dbdbdb, #bababa);
     background-image: -webkit-linear-gradient(top, #dbdbdb, #bababa);
     background-image: -moz-linear-gradient(top, #dbdbdb, #bababa);
     background-image: -owebkit-linear-gradient(top, #dbdbdb, #bababa);
+    box-shadow: 0 0 0;
 }
 
 
@@ -126,6 +128,7 @@ i {
     font-size: 11px;
     font-family: Menlo, Monaco, "Lucida Console", Courier, monospace;
     color: #111;
+    white-space: nowrap;
 }
 
 [class^="icon-"], [class*=" icon-"] {
@@ -163,7 +166,7 @@ i {
 
 
 .tool_container {
-    position: fixed;
+    position: absolute;
     top: 23px;
     bottom: 0;
     left: 0;
@@ -171,17 +174,33 @@ i {
 }
 
 .tool_container .panes {
+    position: relative;
     height: 100%;
     width: 100%;
     overflow: hidden;
 }
 
 .tool_container .panes .pane {
+    position: absolute;
     overflow: auto;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background: #f1f1f1;
 }
 
-.tool_container .panes .pane {
-    overflow: auto;
+.tool_container .multi_pane {
+    position: relative;
+    height: 100%;
+    width: auto;
+    overflow-x: auto;
+}
+
+.tool_container .multi_pane .pane {
+    height: 100%;
+    max-width: 300px;
+    border-right: 1px solid #888;
 }
 
 .tool_container .panes .pane > div {
@@ -189,6 +208,56 @@ i {
     position: relative;
 }
 
+.tool_container .panes.horizontal > .pane {
+    min-height: 50px;
+}
+
+.tool_container .panes.horizontal > .pane {
+    top: 50%;
+}
+
+.tool_container .panes.horizontal > .pane:first-child {
+    top: 0;
+    bottom: 50%;
+}
+
+.tool_container .panes.vertical > .pane {
+    left: 50%;
+}
+
+.tool_container .panes.vertical > .pane:first-child {
+    left: 0;
+    right: 50%;
+}
+
+
+.tool_container .splitter {
+    position: absolute;
+    border-width: 0;
+    z-index: 10;
+}
+
+.tool_container .splitter.vertical {
+    width: 5px;
+    left: 50%;
+    margin-left: -1px;
+    border-left: 1px solid #888;
+    height: 100%;
+    float: left;
+    cursor: ew-resize;
+}
+
+.tool_container .splitter.horizontal {
+    top: 50%;
+    height: 5px;
+    margin-top: -1px;
+    width: 100%;
+    border-top: 1px solid #888;
+    cursor: ns-resize;
+}
+
+
+
 .tool_container .panes .pane .nav-pills {
     position: absolute;
     overflow-y: auto;
@@ -204,11 +273,12 @@ i {
     border-bottom: 1px solid #666;
     background-color: #e9eaf5;
     background-image: -webkit-linear-gradient(top, #e9eaf5, #bfc2d2);
-    color: #333;
+    color: #222;
     font-weight: bold;
     text-shadow: 0 0 0;
     padding-left: 4px;
     line-height: 16px;
+    text-shadow: 0 1px 0 #eee;
 }
 
 .tool_container .list-label .btn-group.cog {
@@ -262,7 +332,6 @@ i {
     line-height: 20px;
 }
 
-
 .tool_container .panes .pane .pane_actions .btn-group {
     display: inline;
     margin-left: 5px;
@@ -278,7 +347,7 @@ i {
     border-radius: 0;
     box-shadow: 0 0 0;
     vertical-align: top;
-    min-width: 50px;
+    /* min-width: 50px; */
 }
 
 .tool_container .panes .pane .pane_actions .btn:hover {
@@ -290,13 +359,13 @@ i {
 }
 
 .tool_container .panes .pane .pane_actions .btn-group .btn.active {
-    background: #999;
-    background-image: linear-gradient(left, #777 0%, #bababa 4%, #bababa 96%, #777 100%);
-    background-image: -webkit-linear-gradient(left, #777 0%, #bababa 4%, #bababa 96%, #777 100%);
-    background-image: -moz-linear-gradient(left, #777 0%, #bababa 4%, #bababa 96%, #777 100%);
-    background-image: -o-linear-gradient(left, #777 0%, #bababa 4%, #bababa 96%, #777 100%);
     text-shadow: #ddd 0px 1px 0px; 
     color: #222;
+    background: #bbb;
+    background-image: linear-gradient(left, #777 0%, #bababa 2px, transparent 2px), linear-gradient(right, #777 0%, #bababa 2px, transparent 2px);
+    background-image: -webkit-linear-gradient(left, #777 0%, #bababa 2px, transparent 2px), -webkit-linear-gradient(right, #777 0%, #bababa 2px, transparent 2px);
+    background-image: -moz-linear-gradient(left, #777 0%, #bababa 2px, transparent 2px), -moz-linear-gradient(right, #777 0%, #bababa 2px, transparent 2px);
+    background-image: -o-linear-gradient(left, #777 0%, #bababa 2px, transparent 2px), -o-linear-gradient(right, #777 0%, #bababa 2px, transparent 2px);
 }
 
 .tool_container .panes .pane .class_side .nav-pills {
@@ -304,37 +373,6 @@ i {
     background: #ffd;
 }
 
-
-.tool_container .panes.horizontal > .pane {
-    height: 50%;
-    min-height: 50px;
-}
-
-.tool_container .panes.vertical > .pane {
-    width: 50%;
-    display: inline;
-    float: left;
-    height: 100%;
-}
-
-.tool_container .splitter {
-    z-index: 10;
-    background: #888;
-}
-
-.tool_container .splitter.vertical {
-    width: 1px;
-    height: 100%;
-    float: left;
-    cursor: e-resize;
-}
-
-.tool_container .splitter.horizontal {
-    height: 1px;
-    cursor: s-resize;
-}
-
-
 .key_helper {
     z-index: 20;
     position: fixed;
@@ -398,7 +436,7 @@ i {
     padding: 2px 8px;
     background: #fff;
     border: 1px solid #a1a1a1;
-    border-radius: 8px;
+    border-radius: 12px;
     box-shadow: inset 0 0px 2px 0px #aaa;
     margin: 2px 4px;
     line-height: 1em;

+ 1 - 0
helios.html

@@ -9,6 +9,7 @@
     <script type='text/javascript' src='js/lib/jQuery/jquery-1.8.2.min.js'></script> 
     <script type='text/javascript' src='js/lib/jQuery/jquery-ui-1.8.24.custom.min.js'></script> 
     <script type='text/javascript' src='js/lib/bootstrap/js/bootstrap.js'></script> 
+    <script type='text/javascript' src='js/lib/showdown.js'></script> 
     <script type='text/javascript' src='js/amber.js'></script> 
   </head> 
   <body> 

+ 126 - 378
js/Helios-Browser.deploy.js

@@ -197,19 +197,22 @@ smalltalk.method({
 selector: "sourceWidget",
 fn: function (){
 var self=this;
-function $HLBrowserSourceWidget(){return smalltalk.HLBrowserSourceWidget||(typeof HLBrowserSourceWidget=="undefined"?nil:HLBrowserSourceWidget)}
+function $HLSourceCodeWidget(){return smalltalk.HLSourceCodeWidget||(typeof HLSourceCodeWidget=="undefined"?nil:HLSourceCodeWidget)}
 return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
+var $2,$3,$4,$1;
 $2=self["@sourceWidget"];
 if(($receiver = $2) == nil || $receiver == undefined){
-self["@sourceWidget"]=_st($HLBrowserSourceWidget())._on_(_st(self)._model());
+$3=_st($HLSourceCodeWidget())._new();
+_st($3)._browserModel_(_st(self)._model());
+$4=_st($3)._yourself();
+self["@sourceWidget"]=$4;
 $1=self["@sourceWidget"];
 } else {
 $1=$2;
 };
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"sourceWidget",{},smalltalk.HLBrowser)})},
-messageSends: ["ifNil:", "on:", "model"]}),
+messageSends: ["ifNil:", "browserModel:", "model", "new", "yourself"]}),
 smalltalk.HLBrowser);
 
 
@@ -725,7 +728,7 @@ fn: function (html){
 var self=this;
 function $String(){return smalltalk.String||(typeof String=="undefined"?nil:String)}
 return smalltalk.withContext(function($ctx1) { 
-var $1,$3,$4,$5,$6,$7,$8,$2;
+var $1,$3,$4,$5,$6,$7,$8,$9,$10,$11,$2;
 $1=_st(html)._div();
 _st($1)._class_("btn-group");
 _st($1)._at_put_("data-toggle","buttons-radio");
@@ -750,20 +753,35 @@ $6=_st(html)._button();
 _st($6)._class_(_st($String())._streamContents_((function(str){
 return smalltalk.withContext(function($ctx3) {
 _st(str)._nextPutAll_("btn");
-$7=_st(_st(self)._model())._showInstance();
-if(! smalltalk.assert($7)){
+$7=_st(self)._showClass();
+if(smalltalk.assert($7)){
 return _st(str)._nextPutAll_(" active");
 };
 }, function($ctx3) {$ctx3.fillBlock({str:str},$ctx1)})})));
 _st($6)._with_("Class");
 $8=_st($6)._onClick_((function(){
 return smalltalk.withContext(function($ctx3) {
-return _st(_st(self)._model())._showInstance_(false);
+return _st(self)._showInstance_(false);
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
-return $8;
+$8;
+$9=_st(html)._button();
+_st($9)._class_(_st($String())._streamContents_((function(str){
+return smalltalk.withContext(function($ctx3) {
+_st(str)._nextPutAll_("btn");
+$10=_st(self)._showComment();
+if(smalltalk.assert($10)){
+return _st(str)._nextPutAll_(" active");
+};
+}, function($ctx3) {$ctx3.fillBlock({str:str},$ctx1)})})));
+_st($9)._with_("Doc");
+$11=_st($9)._onClick_((function(){
+return smalltalk.withContext(function($ctx3) {
+return _st(self)._showComment_(true);
+}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
+return $11;
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"renderButtonsOn:",{html:html},smalltalk.HLClassesListWidget)})},
-messageSends: ["class:", "div", "at:put:", "with:", "streamContents:", "nextPutAll:", "ifTrue:", "showInstance", "button", "onClick:", "showInstance:", "ifFalse:", "model"]}),
+messageSends: ["class:", "div", "at:put:", "with:", "streamContents:", "nextPutAll:", "ifTrue:", "showInstance", "button", "onClick:", "showInstance:", "showClass", "showComment", "showComment:"]}),
 smalltalk.HLClassesListWidget);
 
 smalltalk.addMethod(
@@ -907,6 +925,46 @@ return self}, function($ctx1) {$ctx1.fill(self,"setItemsForSelectedPackage",{},s
 messageSends: ["setItemsForPackage:", "selectedPackage", "model"]}),
 smalltalk.HLClassesListWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "showClass",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(_st(_st(self)._model())._showInstance())._not())._and_((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(_st(_st(self)._model())._showComment())._not();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"showClass",{},smalltalk.HLClassesListWidget)})},
+messageSends: ["and:", "not", "showComment", "model", "showInstance"]}),
+smalltalk.HLClassesListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "showComment",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(self)._model())._showComment();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"showComment",{},smalltalk.HLClassesListWidget)})},
+messageSends: ["showComment", "model"]}),
+smalltalk.HLClassesListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "showComment:",
+fn: function (aBoolean){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._model())._showComment_(aBoolean);
+return self}, function($ctx1) {$ctx1.fill(self,"showComment:",{aBoolean:aBoolean},smalltalk.HLClassesListWidget)})},
+messageSends: ["showComment:", "model"]}),
+smalltalk.HLClassesListWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "showInstance",
@@ -914,10 +972,13 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=_st(_st(self)._model())._showInstance();
+$1=_st(_st(_st(self)._model())._showInstance())._and_((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(_st(_st(self)._model())._showComment())._not();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"showInstance",{},smalltalk.HLClassesListWidget)})},
-messageSends: ["showInstance", "model"]}),
+messageSends: ["and:", "not", "showComment", "model", "showInstance"]}),
 smalltalk.HLClassesListWidget);
 
 smalltalk.addMethod(
@@ -1922,6 +1983,32 @@ return $1;
 messageSends: ["availableClassNames", "environment"]}),
 smalltalk.HLBrowserModel);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "availablePackageNames",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(self)._environment())._availablePackageNames();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"availablePackageNames",{},smalltalk.HLBrowserModel)})},
+messageSends: ["availablePackageNames", "environment"]}),
+smalltalk.HLBrowserModel);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "availablePackages",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(self)._environment())._availablePackageNames();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"availablePackages",{},smalltalk.HLBrowserModel)})},
+messageSends: ["availablePackageNames", "environment"]}),
+smalltalk.HLBrowserModel);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "availableProtocols",
@@ -2181,6 +2268,17 @@ return $1;
 messageSends: ["current"]}),
 smalltalk.HLBrowserModel);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "moveClassToPackage:",
+fn: function (aPackageName){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._environment())._moveClass_toPackage_(_st(_st(self)._selectedClass())._theNonMetaClass(),aPackageName);
+return self}, function($ctx1) {$ctx1.fill(self,"moveClassToPackage:",{aPackageName:aPackageName},smalltalk.HLBrowserModel)})},
+messageSends: ["moveClass:toPackage:", "theNonMetaClass", "selectedClass", "environment"]}),
+smalltalk.HLBrowserModel);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "moveMethodToClass:",
@@ -2230,6 +2328,21 @@ return $1;
 messageSends: ["packages", "environment"]}),
 smalltalk.HLBrowserModel);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "removeClass",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(self)._manager())._confirm_(_st("Do you REALLY want to remove class ").__comma(_st(_st(self)._selectedClass())._name()));
+if(smalltalk.assert($1)){
+_st(_st(self)._environment())._removeClass_(_st(self)._selectedClass());
+};
+return self}, function($ctx1) {$ctx1.fill(self,"removeClass",{},smalltalk.HLBrowserModel)})},
+messageSends: ["ifTrue:", "removeClass:", "selectedClass", "environment", "confirm:", ",", "name", "manager"]}),
+smalltalk.HLBrowserModel);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "removeMethod",
@@ -2518,6 +2631,7 @@ function $HLShowInstanceToggled(){return smalltalk.HLShowInstanceToggled||(typeo
 return smalltalk.withContext(function($ctx1) { 
 var $1,$2,$4,$3;
 self["@showInstance"]=aBoolean;
+self["@showComment"]=false;
 $1=_st(self)._selectedClass();
 if(($receiver = $1) == nil || $receiver == undefined){
 $1;
@@ -2631,372 +2745,6 @@ messageSends: ["environment:", "new", "yourself"]}),
 smalltalk.HLBrowserModel.klass);
 
 
-smalltalk.addClass('HLBrowserSourceWidget', smalltalk.HLWidget, ['model', 'methodContents', 'codeWidget'], 'Helios-Browser');
-smalltalk.addMethod(
-smalltalk.method({
-selector: "codeWidget",
-fn: function (){
-var self=this;
-function $HLSourceCodeWidget(){return smalltalk.HLSourceCodeWidget||(typeof HLSourceCodeWidget=="undefined"?nil:HLSourceCodeWidget)}
-return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
-$2=self["@codeWidget"];
-if(($receiver = $2) == nil || $receiver == undefined){
-self["@codeWidget"]=_st($HLSourceCodeWidget())._on_(_st(self)._model());
-$1=self["@codeWidget"];
-} else {
-$1=$2;
-};
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"codeWidget",{},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["ifNil:", "on:", "model"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "contents",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st(_st(self)._codeWidget())._contents();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"contents",{},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["contents", "codeWidget"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "contents:",
-fn: function (aString){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-_st(self)._methodContents_(aString);
-_st(_st(self)._codeWidget())._contents_(aString);
-return self}, function($ctx1) {$ctx1.fill(self,"contents:",{aString:aString},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["methodContents:", "contents:", "codeWidget"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "focus",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-_st(_st(self)._codeWidget())._focus();
-return self}, function($ctx1) {$ctx1.fill(self,"focus",{},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["focus", "codeWidget"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "hasFocus",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st(_st(self)._codeWidget())._hasFocus();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"hasFocus",{},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["hasFocus", "codeWidget"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "hasModification",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st(_st(_st(self)._methodContents()).__eq(_st(self)._contents()))._not();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"hasModification",{},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["not", "=", "contents", "methodContents"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "initialize",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-smalltalk.HLWidget.fn.prototype._initialize.apply(_st(self), []);
-_st(self)._observeSystem();
-return self}, function($ctx1) {$ctx1.fill(self,"initialize",{},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["initialize", "observeSystem"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "methodContents",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
-$2=self["@methodContents"];
-if(($receiver = $2) == nil || $receiver == undefined){
-self["@methodContents"]="";
-$1=self["@methodContents"];
-} else {
-$1=$2;
-};
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"methodContents",{},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["ifNil:"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "methodContents:",
-fn: function (aString){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self["@methodContents"]=aString;
-return self}, function($ctx1) {$ctx1.fill(self,"methodContents:",{aString:aString},smalltalk.HLBrowserSourceWidget)})},
-messageSends: []}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "model",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=self["@model"];
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"model",{},smalltalk.HLBrowserSourceWidget)})},
-messageSends: []}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "model:",
-fn: function (aBrowserModel){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self["@model"]=aBrowserModel;
-_st(self)._observeModel();
-return self}, function($ctx1) {$ctx1.fill(self,"model:",{aBrowserModel:aBrowserModel},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["observeModel"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "observeModel",
-fn: function (){
-var self=this;
-function $HLMethodSelected(){return smalltalk.HLMethodSelected||(typeof HLMethodSelected=="undefined"?nil:HLMethodSelected)}
-function $HLClassSelected(){return smalltalk.HLClassSelected||(typeof HLClassSelected=="undefined"?nil:HLClassSelected)}
-function $HLProtocolSelected(){return smalltalk.HLProtocolSelected||(typeof HLProtocolSelected=="undefined"?nil:HLProtocolSelected)}
-function $HLSourceCodeFocusRequested(){return smalltalk.HLSourceCodeFocusRequested||(typeof HLSourceCodeFocusRequested=="undefined"?nil:HLSourceCodeFocusRequested)}
-return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=_st(_st(self)._model())._announcer();
-_st($1)._on_do_($HLMethodSelected(),(function(ann){
-return smalltalk.withContext(function($ctx2) {
-return _st(self)._onMethodSelected_(_st(ann)._item());
-}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
-_st($1)._on_do_($HLClassSelected(),(function(ann){
-return smalltalk.withContext(function($ctx2) {
-return _st(self)._onClassSelected_(_st(ann)._item());
-}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
-_st($1)._on_do_($HLProtocolSelected(),(function(ann){
-return smalltalk.withContext(function($ctx2) {
-return _st(self)._onProtocolSelected_(_st(ann)._item());
-}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
-$2=_st($1)._on_do_($HLSourceCodeFocusRequested(),(function(ann){
-return smalltalk.withContext(function($ctx2) {
-return _st(self)._onSourceCodeFocusRequested();
-}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"observeModel",{},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["on:do:", "onMethodSelected:", "item", "announcer", "model", "onClassSelected:", "onProtocolSelected:", "onSourceCodeFocusRequested"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "observeSystem",
-fn: function (){
-var self=this;
-function $MethodModified(){return smalltalk.MethodModified||(typeof MethodModified=="undefined"?nil:MethodModified)}
-function $SystemAnnouncer(){return smalltalk.SystemAnnouncer||(typeof SystemAnnouncer=="undefined"?nil:SystemAnnouncer)}
-return smalltalk.withContext(function($ctx1) { 
-_st(_st($SystemAnnouncer())._current())._on_do_($MethodModified(),(function(ann){
-return smalltalk.withContext(function($ctx2) {
-return _st(self)._onMethodModified_(_st(ann)._method());
-}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"observeSystem",{},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["on:do:", "onMethodModified:", "method", "current"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "onClassSelected:",
-fn: function (aClass){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=aClass;
-if(($receiver = $1) == nil || $receiver == undefined){
-$2=_st(self)._contents_("");
-return $2;
-} else {
-$1;
-};
-_st(self)._contents_(_st(aClass)._definition());
-return self}, function($ctx1) {$ctx1.fill(self,"onClassSelected:",{aClass:aClass},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["ifNil:", "contents:", "definition"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "onMethodModified:",
-fn: function (aMethod){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1,$2,$3,$4,$5,$6;
-$1=_st(_st(_st(self)._model())._selectedClass()).__eq(_st(aMethod)._methodClass());
-if(! smalltalk.assert($1)){
-$2=self;
-return $2;
-};
-$3=_st(_st(self)._model())._selectedMethod();
-if(($receiver = $3) == nil || $receiver == undefined){
-$4=self;
-return $4;
-} else {
-$3;
-};
-$5=_st(_st(_st(_st(self)._model())._selectedMethod())._selector()).__eq(_st(aMethod)._selector());
-if(! smalltalk.assert($5)){
-$6=self;
-return $6;
-};
-_st(self)._refresh();
-return self}, function($ctx1) {$ctx1.fill(self,"onMethodModified:",{aMethod:aMethod},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["ifFalse:", "=", "methodClass", "selectedClass", "model", "ifNil:", "selectedMethod", "selector", "refresh"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "onMethodSelected:",
-fn: function (aCompiledMethod){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=aCompiledMethod;
-if(($receiver = $1) == nil || $receiver == undefined){
-$2=_st(self)._contents_("");
-return $2;
-} else {
-$1;
-};
-_st(self)._contents_(_st(aCompiledMethod)._source());
-return self}, function($ctx1) {$ctx1.fill(self,"onMethodSelected:",{aCompiledMethod:aCompiledMethod},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["ifNil:", "contents:", "source"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "onProtocolSelected:",
-fn: function (aString){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=_st(_st(self)._model())._selectedClass();
-if(($receiver = $1) == nil || $receiver == undefined){
-$2=_st(self)._contents_("");
-return $2;
-} else {
-$1;
-};
-_st(self)._contents_(_st(_st(_st(self)._model())._selectedClass())._definition());
-return self}, function($ctx1) {$ctx1.fill(self,"onProtocolSelected:",{aString:aString},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["ifNil:", "contents:", "selectedClass", "model", "definition"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "onSourceCodeFocusRequested",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-_st(self)._focus();
-return self}, function($ctx1) {$ctx1.fill(self,"onSourceCodeFocusRequested",{},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["focus"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "previous",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-return self}, function($ctx1) {$ctx1.fill(self,"previous",{},smalltalk.HLBrowserSourceWidget)})},
-messageSends: []}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "previous:",
-fn: function (aWidget){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-return self}, function($ctx1) {$ctx1.fill(self,"previous:",{aWidget:aWidget},smalltalk.HLBrowserSourceWidget)})},
-messageSends: []}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "refresh",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1,$2,$3,$4;
-$1=_st(self)._hasModification();
-if(smalltalk.assert($1)){
-$2=self;
-return $2;
-};
-$3=_st(self)._hasFocus();
-if(smalltalk.assert($3)){
-$4=self;
-return $4;
-};
-_st(self)._contents_(_st(_st(_st(self)._model())._selectedMethod())._source());
-return self}, function($ctx1) {$ctx1.fill(self,"refresh",{},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["ifTrue:", "hasModification", "hasFocus", "contents:", "source", "selectedMethod", "model"]}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "renderContentOn:",
-fn: function (html){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-_st(_st(self)._codeWidget())._renderOn_(html);
-return self}, function($ctx1) {$ctx1.fill(self,"renderContentOn:",{html:html},smalltalk.HLBrowserSourceWidget)})},
-messageSends: ["renderOn:", "codeWidget"]}),
-smalltalk.HLBrowserSourceWidget);
-
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "on:",
-fn: function (aBrowserModel){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $2,$3,$1;
-$2=_st(self)._new();
-_st($2)._model_(aBrowserModel);
-$3=_st($2)._yourself();
-$1=$3;
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"on:",{aBrowserModel:aBrowserModel},smalltalk.HLBrowserSourceWidget.klass)})},
-messageSends: ["model:", "new", "yourself"]}),
-smalltalk.HLBrowserSourceWidget.klass);
-
-
 smalltalk.addClass('HLClassCache', smalltalk.Object, ['class', 'selectorsCache', 'overrideCache', 'overriddenCache'], 'Helios-Browser');
 smalltalk.addMethod(
 smalltalk.method({

+ 168 - 500
js/Helios-Browser.js

@@ -116,7 +116,7 @@ $1=$2;
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"methodsListWidget",{},smalltalk.HLBrowser)})},
 args: [],
-source: "methodsListWidget\x0a\x09^ methodsListWidget ifNil: [\x0a      \x09methodsListWidget := HLMethodsListWidget on: self model.\x0a\x09\x09methodsListWidget next: self sourceWidget]",
+source: "methodsListWidget\x0a\x09^ methodsListWidget ifNil: [\x0a      \x09methodsListWidget := HLMethodsListWidget on: self model.\x0a\x09\x09methodsListWidget next: self sourceWidget ]",
 messageSends: ["ifNil:", "on:", "model", "next:", "sourceWidget"],
 referencedClasses: ["HLMethodsListWidget"]
 }),
@@ -258,12 +258,15 @@ selector: "sourceWidget",
 category: 'widgets',
 fn: function (){
 var self=this;
-function $HLBrowserSourceWidget(){return smalltalk.HLBrowserSourceWidget||(typeof HLBrowserSourceWidget=="undefined"?nil:HLBrowserSourceWidget)}
+function $HLSourceCodeWidget(){return smalltalk.HLSourceCodeWidget||(typeof HLSourceCodeWidget=="undefined"?nil:HLSourceCodeWidget)}
 return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
+var $2,$3,$4,$1;
 $2=self["@sourceWidget"];
 if(($receiver = $2) == nil || $receiver == undefined){
-self["@sourceWidget"]=_st($HLBrowserSourceWidget())._on_(_st(self)._model());
+$3=_st($HLSourceCodeWidget())._new();
+_st($3)._browserModel_(_st(self)._model());
+$4=_st($3)._yourself();
+self["@sourceWidget"]=$4;
 $1=self["@sourceWidget"];
 } else {
 $1=$2;
@@ -271,9 +274,9 @@ $1=$2;
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"sourceWidget",{},smalltalk.HLBrowser)})},
 args: [],
-source: "sourceWidget\x0a\x09^ sourceWidget ifNil: [\x0a      \x09sourceWidget := HLBrowserSourceWidget on: self model ]",
-messageSends: ["ifNil:", "on:", "model"],
-referencedClasses: ["HLBrowserSourceWidget"]
+source: "sourceWidget\x0a\x09^ sourceWidget ifNil: [\x0a      \x09sourceWidget := HLSourceCodeWidget new\x0a\x09\x09\x09browserModel: self model;\x0a\x09\x09\x09yourself ]",
+messageSends: ["ifNil:", "browserModel:", "model", "new", "yourself"],
+referencedClasses: ["HLSourceCodeWidget"]
 }),
 smalltalk.HLBrowser);
 
@@ -941,7 +944,7 @@ fn: function (html){
 var self=this;
 function $String(){return smalltalk.String||(typeof String=="undefined"?nil:String)}
 return smalltalk.withContext(function($ctx1) { 
-var $1,$3,$4,$5,$6,$7,$8,$2;
+var $1,$3,$4,$5,$6,$7,$8,$9,$10,$11,$2;
 $1=_st(html)._div();
 _st($1)._class_("btn-group");
 _st($1)._at_put_("data-toggle","buttons-radio");
@@ -966,22 +969,37 @@ $6=_st(html)._button();
 _st($6)._class_(_st($String())._streamContents_((function(str){
 return smalltalk.withContext(function($ctx3) {
 _st(str)._nextPutAll_("btn");
-$7=_st(_st(self)._model())._showInstance();
-if(! smalltalk.assert($7)){
+$7=_st(self)._showClass();
+if(smalltalk.assert($7)){
 return _st(str)._nextPutAll_(" active");
 };
 }, function($ctx3) {$ctx3.fillBlock({str:str},$ctx1)})})));
 _st($6)._with_("Class");
 $8=_st($6)._onClick_((function(){
 return smalltalk.withContext(function($ctx3) {
-return _st(_st(self)._model())._showInstance_(false);
+return _st(self)._showInstance_(false);
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
-return $8;
+$8;
+$9=_st(html)._button();
+_st($9)._class_(_st($String())._streamContents_((function(str){
+return smalltalk.withContext(function($ctx3) {
+_st(str)._nextPutAll_("btn");
+$10=_st(self)._showComment();
+if(smalltalk.assert($10)){
+return _st(str)._nextPutAll_(" active");
+};
+}, function($ctx3) {$ctx3.fillBlock({str:str},$ctx1)})})));
+_st($9)._with_("Doc");
+$11=_st($9)._onClick_((function(){
+return smalltalk.withContext(function($ctx3) {
+return _st(self)._showComment_(true);
+}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
+return $11;
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"renderButtonsOn:",{html:html},smalltalk.HLClassesListWidget)})},
 args: ["html"],
-source: "renderButtonsOn: html\x0a\x09html div \x0a        class: 'btn-group';\x0a\x09\x09at: 'data-toggle' put: 'buttons-radio';\x0a\x09\x09with: [ \x0a           \x09html button \x0a                class: (String streamContents: [ :str |\x0a                \x09str nextPutAll: 'btn'.\x0a                    self showInstance ifTrue: [ \x0a                    \x09str nextPutAll: ' active'] ]);\x0a  \x09\x09\x09\x09with: 'Instance';\x0a                onClick: [ self showInstance: true ].\x0a  \x09\x09\x09html button\x0a  \x09\x09\x09\x09class: (String streamContents: [ :str |\x0a                \x09str nextPutAll: 'btn'.\x0a                    self model showInstance ifFalse: [ \x0a                    \x09str nextPutAll: ' active'] ]);\x0a  \x09\x09\x09\x09with: 'Class';\x0a\x09\x09\x09\x09onClick: [ self model showInstance: false ] ]",
-messageSends: ["class:", "div", "at:put:", "with:", "streamContents:", "nextPutAll:", "ifTrue:", "showInstance", "button", "onClick:", "showInstance:", "ifFalse:", "model"],
+source: "renderButtonsOn: html\x0a\x09html div \x0a        class: 'btn-group';\x0a\x09\x09at: 'data-toggle' put: 'buttons-radio';\x0a\x09\x09with: [ \x0a           \x09html button \x0a                class: (String streamContents: [ :str |\x0a                \x09str nextPutAll: 'btn'.\x0a                    self showInstance ifTrue: [ \x0a                    \x09str nextPutAll: ' active' ] ]);\x0a  \x09\x09\x09\x09with: 'Instance';\x0a                onClick: [ self showInstance: true ].\x0a  \x09\x09\x09html button\x0a  \x09\x09\x09\x09class: (String streamContents: [ :str |\x0a                \x09str nextPutAll: 'btn'.\x0a                    self showClass ifTrue: [ \x0a                    \x09str nextPutAll: ' active' ] ]);\x0a  \x09\x09\x09\x09with: 'Class';\x0a\x09\x09\x09\x09onClick: [ self showInstance: false ].\x0a\x09\x09\x09html button\x0a  \x09\x09\x09\x09class: (String streamContents: [ :str |\x0a                \x09str nextPutAll: 'btn'.\x0a                    self showComment ifTrue: [ \x0a                    \x09str nextPutAll: ' active' ] ]);\x0a  \x09\x09\x09\x09with: 'Doc';\x0a\x09\x09\x09\x09onClick: [ self showComment: true ] ]",
+messageSends: ["class:", "div", "at:put:", "with:", "streamContents:", "nextPutAll:", "ifTrue:", "showInstance", "button", "onClick:", "showInstance:", "showClass", "showComment", "showComment:"],
 referencedClasses: ["String"]
 }),
 smalltalk.HLClassesListWidget);
@@ -1167,6 +1185,61 @@ referencedClasses: []
 }),
 smalltalk.HLClassesListWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "showClass",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(_st(_st(self)._model())._showInstance())._not())._and_((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(_st(_st(self)._model())._showComment())._not();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"showClass",{},smalltalk.HLClassesListWidget)})},
+args: [],
+source: "showClass\x0a\x09^ self model showInstance not and: [\x0a\x09\x09self model showComment not ]",
+messageSends: ["and:", "not", "showComment", "model", "showInstance"],
+referencedClasses: []
+}),
+smalltalk.HLClassesListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "showComment",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(self)._model())._showComment();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"showComment",{},smalltalk.HLClassesListWidget)})},
+args: [],
+source: "showComment\x0a\x09^ self model showComment",
+messageSends: ["showComment", "model"],
+referencedClasses: []
+}),
+smalltalk.HLClassesListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "showComment:",
+category: 'actions',
+fn: function (aBoolean){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._model())._showComment_(aBoolean);
+return self}, function($ctx1) {$ctx1.fill(self,"showComment:",{aBoolean:aBoolean},smalltalk.HLClassesListWidget)})},
+args: ["aBoolean"],
+source: "showComment: aBoolean\x0a\x09self model showComment: aBoolean",
+messageSends: ["showComment:", "model"],
+referencedClasses: []
+}),
+smalltalk.HLClassesListWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "showInstance",
@@ -1175,12 +1248,15 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=_st(_st(self)._model())._showInstance();
+$1=_st(_st(_st(self)._model())._showInstance())._and_((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(_st(_st(self)._model())._showComment())._not();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"showInstance",{},smalltalk.HLClassesListWidget)})},
 args: [],
-source: "showInstance\x0a\x09^ self model showInstance",
-messageSends: ["showInstance", "model"],
+source: "showInstance\x0a\x09^ self model showInstance and: [\x0a\x09\x09self model showComment not ]",
+messageSends: ["and:", "not", "showComment", "model", "showInstance"],
 referencedClasses: []
 }),
 smalltalk.HLClassesListWidget);
@@ -2467,6 +2543,42 @@ referencedClasses: []
 }),
 smalltalk.HLBrowserModel);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "availablePackageNames",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(self)._environment())._availablePackageNames();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"availablePackageNames",{},smalltalk.HLBrowserModel)})},
+args: [],
+source: "availablePackageNames\x0a\x09^ self environment availablePackageNames",
+messageSends: ["availablePackageNames", "environment"],
+referencedClasses: []
+}),
+smalltalk.HLBrowserModel);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "availablePackages",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(self)._environment())._availablePackageNames();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"availablePackages",{},smalltalk.HLBrowserModel)})},
+args: [],
+source: "availablePackages\x0a\x09^ self environment availablePackageNames",
+messageSends: ["availablePackageNames", "environment"],
+referencedClasses: []
+}),
+smalltalk.HLBrowserModel);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "availableProtocols",
@@ -2811,6 +2923,22 @@ referencedClasses: ["HLManager"]
 }),
 smalltalk.HLBrowserModel);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "moveClassToPackage:",
+category: 'commands actions',
+fn: function (aPackageName){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._environment())._moveClass_toPackage_(_st(_st(self)._selectedClass())._theNonMetaClass(),aPackageName);
+return self}, function($ctx1) {$ctx1.fill(self,"moveClassToPackage:",{aPackageName:aPackageName},smalltalk.HLBrowserModel)})},
+args: ["aPackageName"],
+source: "moveClassToPackage: aPackageName\x0a\x09self environment \x0a\x09\x09moveClass: self selectedClass theNonMetaClass\x0a\x09\x09toPackage: aPackageName",
+messageSends: ["moveClass:toPackage:", "theNonMetaClass", "selectedClass", "environment"],
+referencedClasses: []
+}),
+smalltalk.HLBrowserModel);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "moveMethodToClass:",
@@ -2880,6 +3008,26 @@ referencedClasses: []
 }),
 smalltalk.HLBrowserModel);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "removeClass",
+category: 'commands actions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(self)._manager())._confirm_(_st("Do you REALLY want to remove class ").__comma(_st(_st(self)._selectedClass())._name()));
+if(smalltalk.assert($1)){
+_st(_st(self)._environment())._removeClass_(_st(self)._selectedClass());
+};
+return self}, function($ctx1) {$ctx1.fill(self,"removeClass",{},smalltalk.HLBrowserModel)})},
+args: [],
+source: "removeClass\x0a\x09(self manager confirm: 'Do you REALLY want to remove class ', self selectedClass name)\x0a\x09\x09ifTrue: [ self environment removeClass: self selectedClass ]",
+messageSends: ["ifTrue:", "removeClass:", "selectedClass", "environment", "confirm:", ",", "name", "manager"],
+referencedClasses: []
+}),
+smalltalk.HLBrowserModel);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "removeMethod",
@@ -3205,7 +3353,7 @@ self["@showComment"]=aBoolean;
 _st(_st(self)._announcer())._announce_(_st($HLShowCommentToggled())._new());
 return self}, function($ctx1) {$ctx1.fill(self,"showComment:",{aBoolean:aBoolean},smalltalk.HLBrowserModel)})},
 args: ["aBoolean"],
-source: "showComment: aBoolean\x0a\x09showComment := aBoolean.\x0a    \x0a    self announcer announce: HLShowCommentToggled new",
+source: "showComment: aBoolean\x0a\x09showComment := aBoolean.\x0a\x0a    self announcer announce: HLShowCommentToggled new",
 messageSends: ["announce:", "new", "announcer"],
 referencedClasses: ["HLShowCommentToggled"]
 }),
@@ -3244,6 +3392,7 @@ function $HLShowInstanceToggled(){return smalltalk.HLShowInstanceToggled||(typeo
 return smalltalk.withContext(function($ctx1) { 
 var $1,$2,$4,$3;
 self["@showInstance"]=aBoolean;
+self["@showComment"]=false;
 $1=_st(self)._selectedClass();
 if(($receiver = $1) == nil || $receiver == undefined){
 $1;
@@ -3260,7 +3409,7 @@ _st($2)._selectedClass_($3);
 _st(_st(self)._announcer())._announce_(_st($HLShowInstanceToggled())._new());
 return self}, function($ctx1) {$ctx1.fill(self,"showInstance:",{aBoolean:aBoolean},smalltalk.HLBrowserModel)})},
 args: ["aBoolean"],
-source: "showInstance: aBoolean\x0a\x09showInstance := aBoolean.\x0a    \x0a    self selectedClass ifNotNil: [\x0a    \x09self selectedClass: (aBoolean\x0a    \x09\x09ifTrue: [self selectedClass theNonMetaClass ]\x0a    \x09  \x09ifFalse: [ self selectedClass theMetaClass ]) ].\x0a    \x0a    self announcer announce: HLShowInstanceToggled new",
+source: "showInstance: aBoolean\x0a\x09showInstance := aBoolean.\x0a\x09showComment := false.\x0a\x0a    self selectedClass ifNotNil: [\x0a    \x09self selectedClass: (aBoolean\x0a    \x09\x09ifTrue: [self selectedClass theNonMetaClass ]\x0a    \x09  \x09ifFalse: [ self selectedClass theMetaClass ]) ].\x0a    \x0a    self announcer announce: HLShowInstanceToggled new",
 messageSends: ["ifNotNil:", "selectedClass:", "ifTrue:ifFalse:", "theNonMetaClass", "selectedClass", "theMetaClass", "announce:", "new", "announcer"],
 referencedClasses: ["HLShowInstanceToggled"]
 }),
@@ -3386,487 +3535,6 @@ referencedClasses: []
 smalltalk.HLBrowserModel.klass);
 
 
-smalltalk.addClass('HLBrowserSourceWidget', smalltalk.HLWidget, ['model', 'methodContents', 'codeWidget'], 'Helios-Browser');
-smalltalk.addMethod(
-smalltalk.method({
-selector: "codeWidget",
-category: 'accessing',
-fn: function (){
-var self=this;
-function $HLSourceCodeWidget(){return smalltalk.HLSourceCodeWidget||(typeof HLSourceCodeWidget=="undefined"?nil:HLSourceCodeWidget)}
-return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
-$2=self["@codeWidget"];
-if(($receiver = $2) == nil || $receiver == undefined){
-self["@codeWidget"]=_st($HLSourceCodeWidget())._on_(_st(self)._model());
-$1=self["@codeWidget"];
-} else {
-$1=$2;
-};
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"codeWidget",{},smalltalk.HLBrowserSourceWidget)})},
-args: [],
-source: "codeWidget\x0a\x09^ codeWidget ifNil: [ codeWidget := HLSourceCodeWidget on: self model ]",
-messageSends: ["ifNil:", "on:", "model"],
-referencedClasses: ["HLSourceCodeWidget"]
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "contents",
-category: 'accessing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st(_st(self)._codeWidget())._contents();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"contents",{},smalltalk.HLBrowserSourceWidget)})},
-args: [],
-source: "contents\x0a\x09^ self codeWidget contents",
-messageSends: ["contents", "codeWidget"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "contents:",
-category: 'accessing',
-fn: function (aString){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-_st(self)._methodContents_(aString);
-_st(_st(self)._codeWidget())._contents_(aString);
-return self}, function($ctx1) {$ctx1.fill(self,"contents:",{aString:aString},smalltalk.HLBrowserSourceWidget)})},
-args: ["aString"],
-source: "contents: aString\x0a\x09self methodContents: aString.\x0a\x09self codeWidget contents: aString",
-messageSends: ["methodContents:", "contents:", "codeWidget"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "focus",
-category: 'actions',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-_st(_st(self)._codeWidget())._focus();
-return self}, function($ctx1) {$ctx1.fill(self,"focus",{},smalltalk.HLBrowserSourceWidget)})},
-args: [],
-source: "focus\x0a\x09self codeWidget focus",
-messageSends: ["focus", "codeWidget"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "hasFocus",
-category: 'testing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st(_st(self)._codeWidget())._hasFocus();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"hasFocus",{},smalltalk.HLBrowserSourceWidget)})},
-args: [],
-source: "hasFocus\x0a\x09^ self codeWidget hasFocus",
-messageSends: ["hasFocus", "codeWidget"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "hasModification",
-category: 'testing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st(_st(_st(self)._methodContents()).__eq(_st(self)._contents()))._not();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"hasModification",{},smalltalk.HLBrowserSourceWidget)})},
-args: [],
-source: "hasModification\x0a\x09^ (self methodContents = self contents) not",
-messageSends: ["not", "=", "contents", "methodContents"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "initialize",
-category: 'initialization',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-smalltalk.HLWidget.fn.prototype._initialize.apply(_st(self), []);
-_st(self)._observeSystem();
-return self}, function($ctx1) {$ctx1.fill(self,"initialize",{},smalltalk.HLBrowserSourceWidget)})},
-args: [],
-source: "initialize\x0a\x09super initialize.\x0a    \x0a    self observeSystem",
-messageSends: ["initialize", "observeSystem"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "methodContents",
-category: 'accessing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
-$2=self["@methodContents"];
-if(($receiver = $2) == nil || $receiver == undefined){
-self["@methodContents"]="";
-$1=self["@methodContents"];
-} else {
-$1=$2;
-};
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"methodContents",{},smalltalk.HLBrowserSourceWidget)})},
-args: [],
-source: "methodContents\x0a\x09^ methodContents ifNil: [ methodContents := '' ]",
-messageSends: ["ifNil:"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "methodContents:",
-category: 'accessing',
-fn: function (aString){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self["@methodContents"]=aString;
-return self}, function($ctx1) {$ctx1.fill(self,"methodContents:",{aString:aString},smalltalk.HLBrowserSourceWidget)})},
-args: ["aString"],
-source: "methodContents: aString\x0a\x09methodContents := aString",
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "model",
-category: 'accessing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=self["@model"];
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"model",{},smalltalk.HLBrowserSourceWidget)})},
-args: [],
-source: "model\x0a\x09^ model",
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "model:",
-category: 'accessing',
-fn: function (aBrowserModel){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self["@model"]=aBrowserModel;
-_st(self)._observeModel();
-return self}, function($ctx1) {$ctx1.fill(self,"model:",{aBrowserModel:aBrowserModel},smalltalk.HLBrowserSourceWidget)})},
-args: ["aBrowserModel"],
-source: "model: aBrowserModel\x0a\x09model := aBrowserModel.\x0a    \x0a    self observeModel",
-messageSends: ["observeModel"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "observeModel",
-category: 'actions',
-fn: function (){
-var self=this;
-function $HLMethodSelected(){return smalltalk.HLMethodSelected||(typeof HLMethodSelected=="undefined"?nil:HLMethodSelected)}
-function $HLClassSelected(){return smalltalk.HLClassSelected||(typeof HLClassSelected=="undefined"?nil:HLClassSelected)}
-function $HLProtocolSelected(){return smalltalk.HLProtocolSelected||(typeof HLProtocolSelected=="undefined"?nil:HLProtocolSelected)}
-function $HLSourceCodeFocusRequested(){return smalltalk.HLSourceCodeFocusRequested||(typeof HLSourceCodeFocusRequested=="undefined"?nil:HLSourceCodeFocusRequested)}
-return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=_st(_st(self)._model())._announcer();
-_st($1)._on_do_($HLMethodSelected(),(function(ann){
-return smalltalk.withContext(function($ctx2) {
-return _st(self)._onMethodSelected_(_st(ann)._item());
-}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
-_st($1)._on_do_($HLClassSelected(),(function(ann){
-return smalltalk.withContext(function($ctx2) {
-return _st(self)._onClassSelected_(_st(ann)._item());
-}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
-_st($1)._on_do_($HLProtocolSelected(),(function(ann){
-return smalltalk.withContext(function($ctx2) {
-return _st(self)._onProtocolSelected_(_st(ann)._item());
-}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
-$2=_st($1)._on_do_($HLSourceCodeFocusRequested(),(function(ann){
-return smalltalk.withContext(function($ctx2) {
-return _st(self)._onSourceCodeFocusRequested();
-}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"observeModel",{},smalltalk.HLBrowserSourceWidget)})},
-args: [],
-source: "observeModel\x0a\x09self model announcer \x0a\x09\x09on: HLMethodSelected \x0a\x09\x09do: [ :ann | self onMethodSelected: ann item ];\x0a    \x09on: HLClassSelected \x0a\x09\x09do: [ :ann | self onClassSelected: ann item ];\x0a    \x09on: HLProtocolSelected \x0a\x09\x09do: [ :ann | self onProtocolSelected: ann item ];\x0a\x09\x09on: HLSourceCodeFocusRequested \x0a\x09\x09do: [ :ann | self onSourceCodeFocusRequested ]",
-messageSends: ["on:do:", "onMethodSelected:", "item", "announcer", "model", "onClassSelected:", "onProtocolSelected:", "onSourceCodeFocusRequested"],
-referencedClasses: ["HLMethodSelected", "HLClassSelected", "HLProtocolSelected", "HLSourceCodeFocusRequested"]
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "observeSystem",
-category: 'actions',
-fn: function (){
-var self=this;
-function $MethodModified(){return smalltalk.MethodModified||(typeof MethodModified=="undefined"?nil:MethodModified)}
-function $SystemAnnouncer(){return smalltalk.SystemAnnouncer||(typeof SystemAnnouncer=="undefined"?nil:SystemAnnouncer)}
-return smalltalk.withContext(function($ctx1) { 
-_st(_st($SystemAnnouncer())._current())._on_do_($MethodModified(),(function(ann){
-return smalltalk.withContext(function($ctx2) {
-return _st(self)._onMethodModified_(_st(ann)._method());
-}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"observeSystem",{},smalltalk.HLBrowserSourceWidget)})},
-args: [],
-source: "observeSystem\x0a\x09SystemAnnouncer current\x0a    \x09on: MethodModified\x0a        do: [ :ann | self onMethodModified: ann method ]",
-messageSends: ["on:do:", "onMethodModified:", "method", "current"],
-referencedClasses: ["MethodModified", "SystemAnnouncer"]
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "onClassSelected:",
-category: 'reactions',
-fn: function (aClass){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=aClass;
-if(($receiver = $1) == nil || $receiver == undefined){
-$2=_st(self)._contents_("");
-return $2;
-} else {
-$1;
-};
-_st(self)._contents_(_st(aClass)._definition());
-return self}, function($ctx1) {$ctx1.fill(self,"onClassSelected:",{aClass:aClass},smalltalk.HLBrowserSourceWidget)})},
-args: ["aClass"],
-source: "onClassSelected: aClass\x0a\x09aClass ifNil: [ ^ self contents: '' ].\x0a    \x0a    self contents: aClass definition",
-messageSends: ["ifNil:", "contents:", "definition"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "onMethodModified:",
-category: 'reactions',
-fn: function (aMethod){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1,$2,$3,$4,$5,$6;
-$1=_st(_st(_st(self)._model())._selectedClass()).__eq(_st(aMethod)._methodClass());
-if(! smalltalk.assert($1)){
-$2=self;
-return $2;
-};
-$3=_st(_st(self)._model())._selectedMethod();
-if(($receiver = $3) == nil || $receiver == undefined){
-$4=self;
-return $4;
-} else {
-$3;
-};
-$5=_st(_st(_st(_st(self)._model())._selectedMethod())._selector()).__eq(_st(aMethod)._selector());
-if(! smalltalk.assert($5)){
-$6=self;
-return $6;
-};
-_st(self)._refresh();
-return self}, function($ctx1) {$ctx1.fill(self,"onMethodModified:",{aMethod:aMethod},smalltalk.HLBrowserSourceWidget)})},
-args: ["aMethod"],
-source: "onMethodModified: aMethod\x0a\x0a\x09self model selectedClass = aMethod methodClass ifFalse: [ ^ self ].\x0a\x09self model selectedMethod ifNil: [ ^ self ].\x0a    self model selectedMethod selector = aMethod selector ifFalse: [ ^ self ].\x0a\x0a    self refresh",
-messageSends: ["ifFalse:", "=", "methodClass", "selectedClass", "model", "ifNil:", "selectedMethod", "selector", "refresh"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "onMethodSelected:",
-category: 'reactions',
-fn: function (aCompiledMethod){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=aCompiledMethod;
-if(($receiver = $1) == nil || $receiver == undefined){
-$2=_st(self)._contents_("");
-return $2;
-} else {
-$1;
-};
-_st(self)._contents_(_st(aCompiledMethod)._source());
-return self}, function($ctx1) {$ctx1.fill(self,"onMethodSelected:",{aCompiledMethod:aCompiledMethod},smalltalk.HLBrowserSourceWidget)})},
-args: ["aCompiledMethod"],
-source: "onMethodSelected: aCompiledMethod\x0a\x09aCompiledMethod ifNil: [ ^ self contents: '' ].\x0a    \x0a    self contents: aCompiledMethod source",
-messageSends: ["ifNil:", "contents:", "source"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "onProtocolSelected:",
-category: 'reactions',
-fn: function (aString){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=_st(_st(self)._model())._selectedClass();
-if(($receiver = $1) == nil || $receiver == undefined){
-$2=_st(self)._contents_("");
-return $2;
-} else {
-$1;
-};
-_st(self)._contents_(_st(_st(_st(self)._model())._selectedClass())._definition());
-return self}, function($ctx1) {$ctx1.fill(self,"onProtocolSelected:",{aString:aString},smalltalk.HLBrowserSourceWidget)})},
-args: ["aString"],
-source: "onProtocolSelected: aString\x0a\x09self model selectedClass ifNil: [ ^ self contents: '' ].\x0a    \x0a    self contents: self model selectedClass definition",
-messageSends: ["ifNil:", "contents:", "selectedClass", "model", "definition"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "onSourceCodeFocusRequested",
-category: 'reactions',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-_st(self)._focus();
-return self}, function($ctx1) {$ctx1.fill(self,"onSourceCodeFocusRequested",{},smalltalk.HLBrowserSourceWidget)})},
-args: [],
-source: "onSourceCodeFocusRequested\x0a\x09self focus",
-messageSends: ["focus"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "previous",
-category: 'accessing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-return self}, function($ctx1) {$ctx1.fill(self,"previous",{},smalltalk.HLBrowserSourceWidget)})},
-args: [],
-source: "previous\x0a\x09\x22for browser lists widget\x22",
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "previous:",
-category: 'accessing',
-fn: function (aWidget){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-return self}, function($ctx1) {$ctx1.fill(self,"previous:",{aWidget:aWidget},smalltalk.HLBrowserSourceWidget)})},
-args: ["aWidget"],
-source: "previous: aWidget\x0a\x09\x22for browser lists widget\x22",
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "refresh",
-category: 'updating',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1,$2,$3,$4;
-$1=_st(self)._hasModification();
-if(smalltalk.assert($1)){
-$2=self;
-return $2;
-};
-$3=_st(self)._hasFocus();
-if(smalltalk.assert($3)){
-$4=self;
-return $4;
-};
-_st(self)._contents_(_st(_st(_st(self)._model())._selectedMethod())._source());
-return self}, function($ctx1) {$ctx1.fill(self,"refresh",{},smalltalk.HLBrowserSourceWidget)})},
-args: [],
-source: "refresh\x0a\x09self hasModification ifTrue: [ ^ self ].\x0a    self hasFocus ifTrue: [ ^ self ].\x0a\x0a\x09self contents: self model selectedMethod source",
-messageSends: ["ifTrue:", "hasModification", "hasFocus", "contents:", "source", "selectedMethod", "model"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "renderContentOn:",
-category: 'rendering',
-fn: function (html){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-_st(_st(self)._codeWidget())._renderOn_(html);
-return self}, function($ctx1) {$ctx1.fill(self,"renderContentOn:",{html:html},smalltalk.HLBrowserSourceWidget)})},
-args: ["html"],
-source: "renderContentOn: html\x0a\x09self codeWidget renderOn: html",
-messageSends: ["renderOn:", "codeWidget"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget);
-
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "on:",
-category: 'instance creation',
-fn: function (aBrowserModel){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $2,$3,$1;
-$2=_st(self)._new();
-_st($2)._model_(aBrowserModel);
-$3=_st($2)._yourself();
-$1=$3;
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"on:",{aBrowserModel:aBrowserModel},smalltalk.HLBrowserSourceWidget.klass)})},
-args: ["aBrowserModel"],
-source: "on: aBrowserModel\x0a\x09^ self new\x0a    \x09model: aBrowserModel;\x0a        yourself",
-messageSends: ["model:", "new", "yourself"],
-referencedClasses: []
-}),
-smalltalk.HLBrowserSourceWidget.klass);
-
-
 smalltalk.addClass('HLClassCache', smalltalk.Object, ['class', 'selectorsCache', 'overrideCache', 'overriddenCache'], 'Helios-Browser');
 smalltalk.addMethod(
 smalltalk.method({

+ 261 - 0
js/Helios-Commands-Browser.deploy.js

@@ -435,6 +435,154 @@ messageSends: []}),
 smalltalk.HLMoveToCommand.klass);
 
 
+smalltalk.addClass('HLMoveClassToCommand', smalltalk.HLMoveToCommand, [], 'Helios-Commands-Browser');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isActive",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(_st(self)._model())._selectedClass())._notNil();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isActive",{},smalltalk.HLMoveClassToCommand)})},
+messageSends: ["notNil", "selectedClass", "model"]}),
+smalltalk.HLMoveClassToCommand);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "key",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=(67);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLMoveClassToCommand.klass)})},
+messageSends: []}),
+smalltalk.HLMoveClassToCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "label",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Class";
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLMoveClassToCommand.klass)})},
+messageSends: []}),
+smalltalk.HLMoveClassToCommand.klass);
+
+
+smalltalk.addClass('HLMoveClassCommand', smalltalk.HLMoveClassToCommand, [], 'Helios-Commands-Browser');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "displayLabel",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "select a package";
+}, function($ctx1) {$ctx1.fill(self,"displayLabel",{},smalltalk.HLMoveClassCommand)})},
+messageSends: []}),
+smalltalk.HLMoveClassCommand);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "execute",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._model())._moveClassToPackage_(_st(self)._input());
+return self}, function($ctx1) {$ctx1.fill(self,"execute",{},smalltalk.HLMoveClassCommand)})},
+messageSends: ["moveClassToPackage:", "input", "model"]}),
+smalltalk.HLMoveClassCommand);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "inputCompletion",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(self)._model())._availablePackageNames();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"inputCompletion",{},smalltalk.HLMoveClassCommand)})},
+messageSends: ["availablePackageNames", "model"]}),
+smalltalk.HLMoveClassCommand);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "inputLabel",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Move class to package:";
+}, function($ctx1) {$ctx1.fill(self,"inputLabel",{},smalltalk.HLMoveClassCommand)})},
+messageSends: []}),
+smalltalk.HLMoveClassCommand);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isInputRequired",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return true;
+}, function($ctx1) {$ctx1.fill(self,"isInputRequired",{},smalltalk.HLMoveClassCommand)})},
+messageSends: []}),
+smalltalk.HLMoveClassCommand);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isValidFor:",
+fn: function (anObject){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(anObject)._isBehavior();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isValidFor:",{anObject:anObject},smalltalk.HLMoveClassCommand.klass)})},
+messageSends: ["isBehavior"]}),
+smalltalk.HLMoveClassCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "key",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=(80);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLMoveClassCommand.klass)})},
+messageSends: []}),
+smalltalk.HLMoveClassCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "label",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "to package";
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLMoveClassCommand.klass)})},
+messageSends: []}),
+smalltalk.HLMoveClassCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "menuLabel",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Move to package...";
+}, function($ctx1) {$ctx1.fill(self,"menuLabel",{},smalltalk.HLMoveClassCommand.klass)})},
+messageSends: []}),
+smalltalk.HLMoveClassCommand.klass);
+
+
 smalltalk.addClass('HLMoveMethodToCommand', smalltalk.HLMoveToCommand, [], 'Helios-Commands-Browser');
 smalltalk.addMethod(
 smalltalk.method({
@@ -718,6 +866,81 @@ messageSends: []}),
 smalltalk.HLRemoveCommand.klass);
 
 
+smalltalk.addClass('HLRemoveClassCommand', smalltalk.HLRemoveCommand, [], 'Helios-Commands-Browser');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "execute",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._model())._removeClass();
+return self}, function($ctx1) {$ctx1.fill(self,"execute",{},smalltalk.HLRemoveClassCommand)})},
+messageSends: ["removeClass", "model"]}),
+smalltalk.HLRemoveClassCommand);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isActive",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(_st(self)._model())._selectedClass())._notNil();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isActive",{},smalltalk.HLRemoveClassCommand)})},
+messageSends: ["notNil", "selectedClass", "model"]}),
+smalltalk.HLRemoveClassCommand);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isValidFor:",
+fn: function (anObject){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(anObject)._isBehavior();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isValidFor:",{anObject:anObject},smalltalk.HLRemoveClassCommand.klass)})},
+messageSends: ["isBehavior"]}),
+smalltalk.HLRemoveClassCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "key",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=(67);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLRemoveClassCommand.klass)})},
+messageSends: []}),
+smalltalk.HLRemoveClassCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "label",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Class";
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLRemoveClassCommand.klass)})},
+messageSends: []}),
+smalltalk.HLRemoveClassCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "menuLabel",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Remove class";
+}, function($ctx1) {$ctx1.fill(self,"menuLabel",{},smalltalk.HLRemoveClassCommand.klass)})},
+messageSends: []}),
+smalltalk.HLRemoveClassCommand.klass);
+
+
 smalltalk.addClass('HLRemoveMethodCommand', smalltalk.HLRemoveCommand, [], 'Helios-Commands-Browser');
 smalltalk.addMethod(
 smalltalk.method({
@@ -820,6 +1043,44 @@ messageSends: []}),
 smalltalk.HLToggleCommand.klass);
 
 
+smalltalk.addClass('HLToggleClassCommentCommand', smalltalk.HLToggleCommand, [], 'Helios-Commands-Browser');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "execute",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._model())._showComment_(true);
+return self}, function($ctx1) {$ctx1.fill(self,"execute",{},smalltalk.HLToggleClassCommentCommand)})},
+messageSends: ["showComment:", "model"]}),
+smalltalk.HLToggleClassCommentCommand);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "key",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=(68);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLToggleClassCommentCommand.klass)})},
+messageSends: []}),
+smalltalk.HLToggleClassCommentCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "label",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Documentation";
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLToggleClassCommentCommand.klass)})},
+messageSends: []}),
+smalltalk.HLToggleClassCommentCommand.klass);
+
+
 smalltalk.addClass('HLToggleClassSideCommand', smalltalk.HLToggleCommand, [], 'Helios-Commands-Browser');
 smalltalk.addMethod(
 smalltalk.method({

+ 368 - 2
js/Helios-Commands-Browser.js

@@ -605,6 +605,214 @@ referencedClasses: []
 smalltalk.HLMoveToCommand.klass);
 
 
+smalltalk.addClass('HLMoveClassToCommand', smalltalk.HLMoveToCommand, [], 'Helios-Commands-Browser');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isActive",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(_st(self)._model())._selectedClass())._notNil();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isActive",{},smalltalk.HLMoveClassToCommand)})},
+args: [],
+source: "isActive\x0a\x09^ self model selectedClass notNil",
+messageSends: ["notNil", "selectedClass", "model"],
+referencedClasses: []
+}),
+smalltalk.HLMoveClassToCommand);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "key",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=(67);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLMoveClassToCommand.klass)})},
+args: [],
+source: "key\x0a\x09^ 67",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLMoveClassToCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "label",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Class";
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLMoveClassToCommand.klass)})},
+args: [],
+source: "label\x0a\x09^ 'Class'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLMoveClassToCommand.klass);
+
+
+smalltalk.addClass('HLMoveClassCommand', smalltalk.HLMoveClassToCommand, [], 'Helios-Commands-Browser');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "displayLabel",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "select a package";
+}, function($ctx1) {$ctx1.fill(self,"displayLabel",{},smalltalk.HLMoveClassCommand)})},
+args: [],
+source: "displayLabel\x0a\x09^ 'select a package'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLMoveClassCommand);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "execute",
+category: 'executing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._model())._moveClassToPackage_(_st(self)._input());
+return self}, function($ctx1) {$ctx1.fill(self,"execute",{},smalltalk.HLMoveClassCommand)})},
+args: [],
+source: "execute\x0a\x09self model moveClassToPackage: self input",
+messageSends: ["moveClassToPackage:", "input", "model"],
+referencedClasses: []
+}),
+smalltalk.HLMoveClassCommand);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "inputCompletion",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(self)._model())._availablePackageNames();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"inputCompletion",{},smalltalk.HLMoveClassCommand)})},
+args: [],
+source: "inputCompletion\x0a\x09^ self model availablePackageNames",
+messageSends: ["availablePackageNames", "model"],
+referencedClasses: []
+}),
+smalltalk.HLMoveClassCommand);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "inputLabel",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Move class to package:";
+}, function($ctx1) {$ctx1.fill(self,"inputLabel",{},smalltalk.HLMoveClassCommand)})},
+args: [],
+source: "inputLabel\x0a\x09^ 'Move class to package:'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLMoveClassCommand);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isInputRequired",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return true;
+}, function($ctx1) {$ctx1.fill(self,"isInputRequired",{},smalltalk.HLMoveClassCommand)})},
+args: [],
+source: "isInputRequired\x0a\x09^ true",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLMoveClassCommand);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isValidFor:",
+category: 'testing',
+fn: function (anObject){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(anObject)._isBehavior();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isValidFor:",{anObject:anObject},smalltalk.HLMoveClassCommand.klass)})},
+args: ["anObject"],
+source: "isValidFor: anObject\x0a\x09^ anObject isBehavior",
+messageSends: ["isBehavior"],
+referencedClasses: []
+}),
+smalltalk.HLMoveClassCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "key",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=(80);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLMoveClassCommand.klass)})},
+args: [],
+source: "key\x0a\x09^ 80",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLMoveClassCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "label",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "to package";
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLMoveClassCommand.klass)})},
+args: [],
+source: "label\x0a\x09^ 'to package'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLMoveClassCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "menuLabel",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Move to package...";
+}, function($ctx1) {$ctx1.fill(self,"menuLabel",{},smalltalk.HLMoveClassCommand.klass)})},
+args: [],
+source: "menuLabel\x09\x0a\x09^ 'Move to package...'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLMoveClassCommand.klass);
+
+
 smalltalk.addClass('HLMoveMethodToCommand', smalltalk.HLMoveToCommand, [], 'Helios-Commands-Browser');
 smalltalk.addMethod(
 smalltalk.method({
@@ -1003,6 +1211,111 @@ referencedClasses: []
 smalltalk.HLRemoveCommand.klass);
 
 
+smalltalk.addClass('HLRemoveClassCommand', smalltalk.HLRemoveCommand, [], 'Helios-Commands-Browser');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "execute",
+category: 'executing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._model())._removeClass();
+return self}, function($ctx1) {$ctx1.fill(self,"execute",{},smalltalk.HLRemoveClassCommand)})},
+args: [],
+source: "execute\x0a\x09self model removeClass",
+messageSends: ["removeClass", "model"],
+referencedClasses: []
+}),
+smalltalk.HLRemoveClassCommand);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isActive",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(_st(self)._model())._selectedClass())._notNil();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isActive",{},smalltalk.HLRemoveClassCommand)})},
+args: [],
+source: "isActive\x0a\x09^ self model selectedClass notNil",
+messageSends: ["notNil", "selectedClass", "model"],
+referencedClasses: []
+}),
+smalltalk.HLRemoveClassCommand);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isValidFor:",
+category: 'testing',
+fn: function (anObject){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(anObject)._isBehavior();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isValidFor:",{anObject:anObject},smalltalk.HLRemoveClassCommand.klass)})},
+args: ["anObject"],
+source: "isValidFor: anObject\x0a\x09^ anObject isBehavior",
+messageSends: ["isBehavior"],
+referencedClasses: []
+}),
+smalltalk.HLRemoveClassCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "key",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=(67);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLRemoveClassCommand.klass)})},
+args: [],
+source: "key\x0a\x09^ 67",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLRemoveClassCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "label",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Class";
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLRemoveClassCommand.klass)})},
+args: [],
+source: "label\x0a\x09^ 'Class'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLRemoveClassCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "menuLabel",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Remove class";
+}, function($ctx1) {$ctx1.fill(self,"menuLabel",{},smalltalk.HLRemoveClassCommand.klass)})},
+args: [],
+source: "menuLabel\x0a\x09^ 'Remove class'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLRemoveClassCommand.klass);
+
+
 smalltalk.addClass('HLRemoveMethodCommand', smalltalk.HLRemoveCommand, [], 'Helios-Commands-Browser');
 smalltalk.addMethod(
 smalltalk.method({
@@ -1042,7 +1355,7 @@ smalltalk.HLRemoveMethodCommand);
 smalltalk.addMethod(
 smalltalk.method({
 selector: "isValidFor:",
-category: 'accessing',
+category: 'testing',
 fn: function (anObject){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
@@ -1060,7 +1373,7 @@ smalltalk.HLRemoveMethodCommand.klass);
 smalltalk.addMethod(
 smalltalk.method({
 selector: "key",
-category: 'testing',
+category: 'accessing',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
@@ -1145,6 +1458,59 @@ referencedClasses: []
 smalltalk.HLToggleCommand.klass);
 
 
+smalltalk.addClass('HLToggleClassCommentCommand', smalltalk.HLToggleCommand, [], 'Helios-Commands-Browser');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "execute",
+category: 'executing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._model())._showComment_(true);
+return self}, function($ctx1) {$ctx1.fill(self,"execute",{},smalltalk.HLToggleClassCommentCommand)})},
+args: [],
+source: "execute\x0a\x09self model showComment: true",
+messageSends: ["showComment:", "model"],
+referencedClasses: []
+}),
+smalltalk.HLToggleClassCommentCommand);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "key",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=(68);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLToggleClassCommentCommand.klass)})},
+args: [],
+source: "key\x0a\x09\x22d\x22\x0a    \x0a\x09^ 68",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLToggleClassCommentCommand.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "label",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Documentation";
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLToggleClassCommentCommand.klass)})},
+args: [],
+source: "label\x0a\x09^ 'Documentation'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLToggleClassCommentCommand.klass);
+
+
 smalltalk.addClass('HLToggleClassSideCommand', smalltalk.HLToggleCommand, [], 'Helios-Commands-Browser');
 smalltalk.addMethod(
 smalltalk.method({

+ 31 - 47
js/Helios-Core.deploy.js

@@ -66,10 +66,10 @@ $1=self["@root"];
 if(($receiver = $1) == nil || $receiver == undefined){
 $1;
 } else {
-_st(_st(self["@root"])._asJQuery())._hide();
+_st(_st(self["@root"])._asJQuery())._css_put_("visibility","hidden");
 };
 return self}, function($ctx1) {$ctx1.fill(self,"hide",{},smalltalk.HLTab)})},
-messageSends: ["ifNotNil:", "hide", "asJQuery"]}),
+messageSends: ["ifNotNil:", "css:put:", "asJQuery"]}),
 smalltalk.HLTab);
 
 smalltalk.addMethod(
@@ -204,10 +204,10 @@ $1=self["@root"];
 if(($receiver = $1) == nil || $receiver == undefined){
 _st(self)._appendToJQuery_(_st("body")._asJQuery());
 } else {
-_st(_st(self["@root"])._asJQuery())._show();
+_st(_st(self["@root"])._asJQuery())._css_put_("visibility","visible");
 };
 return self}, function($ctx1) {$ctx1.fill(self,"show",{},smalltalk.HLTab)})},
-messageSends: ["ifNil:ifNotNil:", "appendToJQuery:", "asJQuery", "show"]}),
+messageSends: ["ifNil:ifNotNil:", "appendToJQuery:", "asJQuery", "css:put:"]}),
 smalltalk.HLTab);
 
 smalltalk.addMethod(
@@ -459,16 +459,16 @@ smalltalk.HLWidget.klass);
 smalltalk.addClass('HLDebugger', smalltalk.HLWidget, [], 'Helios-Core');
 
 
-smalltalk.addClass('HLFocusableWidget', smalltalk.HLWidget, ['hiddenInput'], 'Helios-Core');
+smalltalk.addClass('HLFocusableWidget', smalltalk.HLWidget, [], 'Helios-Core');
 smalltalk.addMethod(
 smalltalk.method({
 selector: "blur",
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-_st(_st(self["@hiddenInput"])._asJQuery())._blur();
+_st(_st(_st(self)._wrapper())._asJQuery())._blur();
 return self}, function($ctx1) {$ctx1.fill(self,"blur",{},smalltalk.HLFocusableWidget)})},
-messageSends: ["blur", "asJQuery"]}),
+messageSends: ["blur", "asJQuery", "wrapper"]}),
 smalltalk.HLFocusableWidget);
 
 smalltalk.addMethod(
@@ -488,9 +488,9 @@ selector: "focus",
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-_st(_st(self["@hiddenInput"])._asJQuery())._focus();
+_st(_st(_st(self)._wrapper())._asJQuery())._focus();
 return self}, function($ctx1) {$ctx1.fill(self,"focus",{},smalltalk.HLFocusableWidget)})},
-messageSends: ["focus", "asJQuery"]}),
+messageSends: ["focus", "asJQuery", "wrapper"]}),
 smalltalk.HLFocusableWidget);
 
 smalltalk.addMethod(
@@ -513,11 +513,11 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 $1=_st(_st(_st(self)._wrapper())._notNil())._and_((function(){
 return smalltalk.withContext(function($ctx2) {
-return _st(_st(_st(self)._wrapper())._asJQuery())._hasClass_(_st(self)._focusClass());
+return _st(_st(_st(self)._wrapper())._asJQuery())._is_(":focus");
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"hasFocus",{},smalltalk.HLFocusableWidget)})},
-messageSends: ["and:", "hasClass:", "focusClass", "asJQuery", "wrapper", "notNil"]}),
+messageSends: ["and:", "is:", "asJQuery", "wrapper", "notNil"]}),
 smalltalk.HLFocusableWidget);
 
 smalltalk.addMethod(
@@ -530,50 +530,34 @@ return self}, function($ctx1) {$ctx1.fill(self,"renderContentOn:",{html:html},sm
 messageSends: []}),
 smalltalk.HLFocusableWidget);
 
-smalltalk.addMethod(
-smalltalk.method({
-selector: "renderHiddenInputOn:",
-fn: function (html){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=_st(html)._input();
-_st($1)._style_("position: absolute; left: -100000px;");
-_st($1)._onBlur_((function(){
-return smalltalk.withContext(function($ctx2) {
-return _st(_st(_st(self)._wrapper())._asJQuery())._removeClass_(_st(self)._focusClass());
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-$2=_st($1)._onFocus_((function(){
-return smalltalk.withContext(function($ctx2) {
-return _st(_st(_st(self)._wrapper())._asJQuery())._addClass_(_st(self)._focusClass());
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-self["@hiddenInput"]=$2;
-return self}, function($ctx1) {$ctx1.fill(self,"renderHiddenInputOn:",{html:html},smalltalk.HLFocusableWidget)})},
-messageSends: ["style:", "input", "onBlur:", "removeClass:", "focusClass", "asJQuery", "wrapper", "onFocus:", "addClass:"]}),
-smalltalk.HLFocusableWidget);
-
 smalltalk.addMethod(
 smalltalk.method({
 selector: "renderOn:",
 fn: function (html){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
+var $1,$2,$3,$4;
 _st(self)._registerBindings();
-_st(self)._renderHiddenInputOn_(html);
 $1=_st(html)._div();
 _st($1)._class_("hl_widget");
-_st($1)._onClick_((function(){
+$2=_st($1)._yourself();
+self["@wrapper"]=$2;
+_st(self["@wrapper"])._with_((function(){
 return smalltalk.withContext(function($ctx2) {
-return _st(_st(self["@hiddenInput"])._asJQuery())._focus();
+return _st(self)._renderContentOn_(html);
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-$2=_st($1)._with_((function(){
+$3=self["@wrapper"];
+_st($3)._at_put_("tabindex","0");
+_st($3)._onBlur_((function(){
 return smalltalk.withContext(function($ctx2) {
-return _st(self)._renderContentOn_(html);
+return _st(_st(_st(self)._wrapper())._asJQuery())._removeClass_(_st(self)._focusClass());
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+$4=_st($3)._onFocus_((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(_st(_st(self)._wrapper())._asJQuery())._addClass_(_st(self)._focusClass());
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-self["@wrapper"]=$2;
 return self}, function($ctx1) {$ctx1.fill(self,"renderOn:",{html:html},smalltalk.HLFocusableWidget)})},
-messageSends: ["registerBindings", "renderHiddenInputOn:", "class:", "div", "onClick:", "focus", "asJQuery", "with:", "renderContentOn:"]}),
+messageSends: ["registerBindings", "class:", "div", "yourself", "with:", "renderContentOn:", "at:put:", "onBlur:", "removeClass:", "focusClass", "asJQuery", "wrapper", "onFocus:", "addClass:"]}),
 smalltalk.HLFocusableWidget);
 
 
@@ -935,8 +919,8 @@ return smalltalk.withContext(function($ctx1) {
 var $1,$2,$3,$4,$5;
 active=false;
 repeatInterval=(70);
-_st(_st(self["@hiddenInput"])._asJQuery())._unbind_("keydown");
-_st(_st(self["@hiddenInput"])._asJQuery())._keydown_((function(e){
+_st(_st(_st(self)._wrapper())._asJQuery())._unbind_("keydown");
+_st(_st(_st(self)._wrapper())._asJQuery())._keydown_((function(e){
 return smalltalk.withContext(function($ctx2) {
 $1=_st(_st(_st(e)._which()).__eq((38)))._and_((function(){
 return smalltalk.withContext(function($ctx3) {
@@ -975,7 +959,7 @@ return interval;
 return delay;
 };
 }, function($ctx2) {$ctx2.fillBlock({e:e},$ctx1)})}));
-_st(_st(self["@hiddenInput"])._asJQuery())._keyup_((function(e){
+_st(_st(_st(self)._wrapper())._asJQuery())._keyup_((function(e){
 return smalltalk.withContext(function($ctx2) {
 $3=active;
 if(smalltalk.assert($3)){
@@ -996,7 +980,7 @@ return _st(delay)._clearTimeout();
 };
 }, function($ctx2) {$ctx2.fillBlock({e:e},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"setupKeyBindings",{active:active,interval:interval,delay:delay,repeatInterval:repeatInterval},smalltalk.HLListWidget)})},
-messageSends: ["unbind:", "asJQuery", "keydown:", "ifTrue:", "activatePreviousListItem", "valueWithTimeout:", "valueWithInterval:", "and:", "=", "which", "activateNextListItem", "keyup:", "ifNotNil:", "clearInterval", "clearTimeout"]}),
+messageSends: ["unbind:", "asJQuery", "wrapper", "keydown:", "ifTrue:", "activatePreviousListItem", "valueWithTimeout:", "valueWithInterval:", "and:", "=", "which", "activateNextListItem", "keyup:", "ifNotNil:", "clearInterval", "clearTimeout"]}),
 smalltalk.HLListWidget);
 
 
@@ -1102,7 +1086,7 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
 var $1,$2;
 smalltalk.HLListWidget.fn.prototype._setupKeyBindings.apply(_st(self), []);
-_st(_st(self["@hiddenInput"])._asJQuery())._keydown_((function(e){
+_st(_st(_st(self)._wrapper())._asJQuery())._keydown_((function(e){
 return smalltalk.withContext(function($ctx2) {
 $1=_st(_st(e)._which()).__eq((39));
 if(smalltalk.assert($1)){
@@ -1114,7 +1098,7 @@ return _st(self)._previousFocus();
 };
 }, function($ctx2) {$ctx2.fillBlock({e:e},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"setupKeyBindings",{},smalltalk.HLNavigationListWidget)})},
-messageSends: ["setupKeyBindings", "keydown:", "ifTrue:", "nextFocus", "=", "which", "previousFocus", "asJQuery"]}),
+messageSends: ["setupKeyBindings", "keydown:", "ifTrue:", "nextFocus", "=", "which", "previousFocus", "asJQuery", "wrapper"]}),
 smalltalk.HLNavigationListWidget);
 
 

+ 39 - 60
js/Helios-Core.js

@@ -87,12 +87,12 @@ $1=self["@root"];
 if(($receiver = $1) == nil || $receiver == undefined){
 $1;
 } else {
-_st(_st(self["@root"])._asJQuery())._hide();
+_st(_st(self["@root"])._asJQuery())._css_put_("visibility","hidden");
 };
 return self}, function($ctx1) {$ctx1.fill(self,"hide",{},smalltalk.HLTab)})},
 args: [],
-source: "hide\x0a\x09root ifNotNil: [\x0a\x09\x09root asJQuery hide ]",
-messageSends: ["ifNotNil:", "hide", "asJQuery"],
+source: "hide\x0a\x09root ifNotNil: [ root asJQuery css: 'visibility' put: 'hidden' ]",
+messageSends: ["ifNotNil:", "css:put:", "asJQuery"],
 referencedClasses: []
 }),
 smalltalk.HLTab);
@@ -270,12 +270,12 @@ $1=self["@root"];
 if(($receiver = $1) == nil || $receiver == undefined){
 _st(self)._appendToJQuery_(_st("body")._asJQuery());
 } else {
-_st(_st(self["@root"])._asJQuery())._show();
+_st(_st(self["@root"])._asJQuery())._css_put_("visibility","visible");
 };
 return self}, function($ctx1) {$ctx1.fill(self,"show",{},smalltalk.HLTab)})},
 args: [],
-source: "show\x0a\x09root\x0a\x09\x09ifNil: [ self appendToJQuery: 'body' asJQuery ]\x0a\x09\x09ifNotNil: [ root asJQuery show ]\x09",
-messageSends: ["ifNil:ifNotNil:", "appendToJQuery:", "asJQuery", "show"],
+source: "show\x0a\x09root\x0a\x09\x09ifNil: [ self appendToJQuery: 'body' asJQuery ]\x0a\x09\x09ifNotNil: [ root asJQuery css: 'visibility' put: 'visible' ]",
+messageSends: ["ifNil:ifNotNil:", "appendToJQuery:", "asJQuery", "css:put:"],
 referencedClasses: []
 }),
 smalltalk.HLTab);
@@ -619,7 +619,7 @@ smalltalk.HLWidget.klass);
 smalltalk.addClass('HLDebugger', smalltalk.HLWidget, [], 'Helios-Core');
 
 
-smalltalk.addClass('HLFocusableWidget', smalltalk.HLWidget, ['hiddenInput'], 'Helios-Core');
+smalltalk.addClass('HLFocusableWidget', smalltalk.HLWidget, [], 'Helios-Core');
 smalltalk.addMethod(
 smalltalk.method({
 selector: "blur",
@@ -627,11 +627,11 @@ category: 'events',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-_st(_st(self["@hiddenInput"])._asJQuery())._blur();
+_st(_st(_st(self)._wrapper())._asJQuery())._blur();
 return self}, function($ctx1) {$ctx1.fill(self,"blur",{},smalltalk.HLFocusableWidget)})},
 args: [],
-source: "blur\x0a\x09hiddenInput asJQuery blur",
-messageSends: ["blur", "asJQuery"],
+source: "blur\x0a\x09self wrapper asJQuery blur",
+messageSends: ["blur", "asJQuery", "wrapper"],
 referencedClasses: []
 }),
 smalltalk.HLFocusableWidget);
@@ -659,11 +659,11 @@ category: 'events',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-_st(_st(self["@hiddenInput"])._asJQuery())._focus();
+_st(_st(_st(self)._wrapper())._asJQuery())._focus();
 return self}, function($ctx1) {$ctx1.fill(self,"focus",{},smalltalk.HLFocusableWidget)})},
 args: [],
-source: "focus\x0a\x09hiddenInput asJQuery focus",
-messageSends: ["focus", "asJQuery"],
+source: "focus\x0a\x09self wrapper asJQuery focus",
+messageSends: ["focus", "asJQuery", "wrapper"],
 referencedClasses: []
 }),
 smalltalk.HLFocusableWidget);
@@ -694,13 +694,13 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 $1=_st(_st(_st(self)._wrapper())._notNil())._and_((function(){
 return smalltalk.withContext(function($ctx2) {
-return _st(_st(_st(self)._wrapper())._asJQuery())._hasClass_(_st(self)._focusClass());
+return _st(_st(_st(self)._wrapper())._asJQuery())._is_(":focus");
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"hasFocus",{},smalltalk.HLFocusableWidget)})},
 args: [],
-source: "hasFocus\x0a\x09^ self wrapper notNil and: [ self wrapper asJQuery hasClass: self focusClass ]",
-messageSends: ["and:", "hasClass:", "focusClass", "asJQuery", "wrapper", "notNil"],
+source: "hasFocus\x0a\x09^ self wrapper notNil and: [ self wrapper asJQuery is: ':focus' ]",
+messageSends: ["and:", "is:", "asJQuery", "wrapper", "notNil"],
 referencedClasses: []
 }),
 smalltalk.HLFocusableWidget);
@@ -720,33 +720,6 @@ referencedClasses: []
 }),
 smalltalk.HLFocusableWidget);
 
-smalltalk.addMethod(
-smalltalk.method({
-selector: "renderHiddenInputOn:",
-category: 'rendering',
-fn: function (html){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=_st(html)._input();
-_st($1)._style_("position: absolute; left: -100000px;");
-_st($1)._onBlur_((function(){
-return smalltalk.withContext(function($ctx2) {
-return _st(_st(_st(self)._wrapper())._asJQuery())._removeClass_(_st(self)._focusClass());
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-$2=_st($1)._onFocus_((function(){
-return smalltalk.withContext(function($ctx2) {
-return _st(_st(_st(self)._wrapper())._asJQuery())._addClass_(_st(self)._focusClass());
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-self["@hiddenInput"]=$2;
-return self}, function($ctx1) {$ctx1.fill(self,"renderHiddenInputOn:",{html:html},smalltalk.HLFocusableWidget)})},
-args: ["html"],
-source: "renderHiddenInputOn: html\x0a\x09hiddenInput := html input\x0a    \x09style: 'position: absolute; left: -100000px;';\x0a    \x09onBlur: [ self wrapper asJQuery removeClass: self focusClass ];\x0a        onFocus: [ self wrapper asJQuery addClass: self focusClass ]",
-messageSends: ["style:", "input", "onBlur:", "removeClass:", "focusClass", "asJQuery", "wrapper", "onFocus:", "addClass:"],
-referencedClasses: []
-}),
-smalltalk.HLFocusableWidget);
-
 smalltalk.addMethod(
 smalltalk.method({
 selector: "renderOn:",
@@ -754,24 +727,30 @@ category: 'rendering',
 fn: function (html){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
+var $1,$2,$3,$4;
 _st(self)._registerBindings();
-_st(self)._renderHiddenInputOn_(html);
 $1=_st(html)._div();
 _st($1)._class_("hl_widget");
-_st($1)._onClick_((function(){
+$2=_st($1)._yourself();
+self["@wrapper"]=$2;
+_st(self["@wrapper"])._with_((function(){
 return smalltalk.withContext(function($ctx2) {
-return _st(_st(self["@hiddenInput"])._asJQuery())._focus();
+return _st(self)._renderContentOn_(html);
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-$2=_st($1)._with_((function(){
+$3=self["@wrapper"];
+_st($3)._at_put_("tabindex","0");
+_st($3)._onBlur_((function(){
 return smalltalk.withContext(function($ctx2) {
-return _st(self)._renderContentOn_(html);
+return _st(_st(_st(self)._wrapper())._asJQuery())._removeClass_(_st(self)._focusClass());
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+$4=_st($3)._onFocus_((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(_st(_st(self)._wrapper())._asJQuery())._addClass_(_st(self)._focusClass());
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-self["@wrapper"]=$2;
 return self}, function($ctx1) {$ctx1.fill(self,"renderOn:",{html:html},smalltalk.HLFocusableWidget)})},
 args: ["html"],
-source: "renderOn: html\x0a\x09self registerBindings.\x0a\x09self renderHiddenInputOn: html.\x0a    \x0a    wrapper := html div \x0a    \x09class: 'hl_widget'; \x0a        onClick: [ hiddenInput asJQuery focus ];\x0a        with: [\x0a\x09\x09\x09self renderContentOn: html ]",
-messageSends: ["registerBindings", "renderHiddenInputOn:", "class:", "div", "onClick:", "focus", "asJQuery", "with:", "renderContentOn:"],
+source: "renderOn: html\x0a\x09self registerBindings.\x0a    \x0a    wrapper := html div \x0a    \x09class: 'hl_widget';\x0a\x09\x09yourself.\x0a\x09\x09\x0a       wrapper with: [ self renderContentOn: html ].\x0a\x09\x0a\x09wrapper\x0a\x09\x09at: 'tabindex' put: '0';\x0a\x09\x09onBlur: [ self wrapper asJQuery removeClass: self focusClass ];\x0a        onFocus: [ self wrapper asJQuery addClass: self focusClass ]",
+messageSends: ["registerBindings", "class:", "div", "yourself", "with:", "renderContentOn:", "at:put:", "onBlur:", "removeClass:", "focusClass", "asJQuery", "wrapper", "onFocus:", "addClass:"],
 referencedClasses: []
 }),
 smalltalk.HLFocusableWidget);
@@ -1246,8 +1225,8 @@ return smalltalk.withContext(function($ctx1) {
 var $1,$2,$3,$4,$5;
 active=false;
 repeatInterval=(70);
-_st(_st(self["@hiddenInput"])._asJQuery())._unbind_("keydown");
-_st(_st(self["@hiddenInput"])._asJQuery())._keydown_((function(e){
+_st(_st(_st(self)._wrapper())._asJQuery())._unbind_("keydown");
+_st(_st(_st(self)._wrapper())._asJQuery())._keydown_((function(e){
 return smalltalk.withContext(function($ctx2) {
 $1=_st(_st(_st(e)._which()).__eq((38)))._and_((function(){
 return smalltalk.withContext(function($ctx3) {
@@ -1286,7 +1265,7 @@ return interval;
 return delay;
 };
 }, function($ctx2) {$ctx2.fillBlock({e:e},$ctx1)})}));
-_st(_st(self["@hiddenInput"])._asJQuery())._keyup_((function(e){
+_st(_st(_st(self)._wrapper())._asJQuery())._keyup_((function(e){
 return smalltalk.withContext(function($ctx2) {
 $3=active;
 if(smalltalk.assert($3)){
@@ -1308,8 +1287,8 @@ return _st(delay)._clearTimeout();
 }, function($ctx2) {$ctx2.fillBlock({e:e},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"setupKeyBindings",{active:active,interval:interval,delay:delay,repeatInterval:repeatInterval},smalltalk.HLListWidget)})},
 args: [],
-source: "setupKeyBindings\x0a\x09\x22TODO: refactor this!\x22\x0a\x09\x0a\x09| active interval delay repeatInterval |\x0a\x09\x0a\x09active := false.\x0a\x09repeatInterval := 70.\x0a\x09hiddenInput asJQuery unbind: 'keydown'.\x0a\x0a\x09hiddenInput asJQuery keydown: [ :e |\x0a\x09\x09\x0a        (e which = 38 and: [ active = false ]) ifTrue: [ \x0a\x09\x09\x09active := true.\x0a\x09\x09\x09self activatePreviousListItem.\x0a        \x09delay := [\x0a\x09\x09\x09\x09interval := [ self activatePreviousListItem ]\x0a\x09\x09\x09\x09\x09valueWithInterval: repeatInterval ]\x0a\x09\x09\x09\x09\x09\x09valueWithTimeout: 300 ].\x0a\x09\x09\x09\x0a      \x09(e which = 40 and: [ active = false ]) ifTrue: [\x0a            active := true.\x0a\x09\x09\x09self activateNextListItem.\x0a        \x09delay := [\x0a\x09\x09\x09\x09interval := [ self activateNextListItem ]\x0a\x09\x09\x09\x09\x09valueWithInterval: repeatInterval ]\x0a\x09\x09\x09\x09\x09\x09valueWithTimeout: 300 ] ].\x0a\x09\x0a\x09hiddenInput asJQuery keyup: [ :e |\x0a\x09\x09active ifTrue: [\x0a\x09\x09\x09active := false.\x0a\x09\x09\x09interval ifNotNil: [ interval clearInterval ].\x0a\x09\x09\x09delay ifNotNil: [ delay clearTimeout] ] ]",
-messageSends: ["unbind:", "asJQuery", "keydown:", "ifTrue:", "activatePreviousListItem", "valueWithTimeout:", "valueWithInterval:", "and:", "=", "which", "activateNextListItem", "keyup:", "ifNotNil:", "clearInterval", "clearTimeout"],
+source: "setupKeyBindings\x0a\x09\x22TODO: refactor this!\x22\x0a\x09\x0a\x09| active interval delay repeatInterval |\x0a\x09\x0a\x09active := false.\x0a\x09repeatInterval := 70.\x0a\x09self wrapper asJQuery unbind: 'keydown'.\x0a\x0a\x09self wrapper asJQuery keydown: [ :e |\x0a\x09\x09\x0a        (e which = 38 and: [ active = false ]) ifTrue: [ \x0a\x09\x09\x09active := true.\x0a\x09\x09\x09self activatePreviousListItem.\x0a        \x09delay := [\x0a\x09\x09\x09\x09interval := [ self activatePreviousListItem ]\x0a\x09\x09\x09\x09\x09valueWithInterval: repeatInterval ]\x0a\x09\x09\x09\x09\x09\x09valueWithTimeout: 300 ].\x0a\x09\x09\x09\x0a      \x09(e which = 40 and: [ active = false ]) ifTrue: [\x0a            active := true.\x0a\x09\x09\x09self activateNextListItem.\x0a        \x09delay := [\x0a\x09\x09\x09\x09interval := [ self activateNextListItem ]\x0a\x09\x09\x09\x09\x09valueWithInterval: repeatInterval ]\x0a\x09\x09\x09\x09\x09\x09valueWithTimeout: 300 ] ].\x0a\x09\x0a\x09self wrapper asJQuery keyup: [ :e |\x0a\x09\x09active ifTrue: [\x0a\x09\x09\x09active := false.\x0a\x09\x09\x09interval ifNotNil: [ interval clearInterval ].\x0a\x09\x09\x09delay ifNotNil: [ delay clearTimeout] ] ]",
+messageSends: ["unbind:", "asJQuery", "wrapper", "keydown:", "ifTrue:", "activatePreviousListItem", "valueWithTimeout:", "valueWithInterval:", "and:", "=", "which", "activateNextListItem", "keyup:", "ifNotNil:", "clearInterval", "clearTimeout"],
 referencedClasses: []
 }),
 smalltalk.HLListWidget);
@@ -1448,7 +1427,7 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
 var $1,$2;
 smalltalk.HLListWidget.fn.prototype._setupKeyBindings.apply(_st(self), []);
-_st(_st(self["@hiddenInput"])._asJQuery())._keydown_((function(e){
+_st(_st(_st(self)._wrapper())._asJQuery())._keydown_((function(e){
 return smalltalk.withContext(function($ctx2) {
 $1=_st(_st(e)._which()).__eq((39));
 if(smalltalk.assert($1)){
@@ -1461,8 +1440,8 @@ return _st(self)._previousFocus();
 }, function($ctx2) {$ctx2.fillBlock({e:e},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"setupKeyBindings",{},smalltalk.HLNavigationListWidget)})},
 args: [],
-source: "setupKeyBindings\x0a\x09super setupKeyBindings.\x0a\x0a\x09hiddenInput asJQuery keydown: [ :e |\x0a        e which = 39 ifTrue: [ \x0a        \x09self nextFocus ].\x0a\x09\x09e which = 37 ifTrue: [ \x0a        \x09self previousFocus ] ]",
-messageSends: ["setupKeyBindings", "keydown:", "ifTrue:", "nextFocus", "=", "which", "previousFocus", "asJQuery"],
+source: "setupKeyBindings\x0a\x09super setupKeyBindings.\x0a\x0a\x09self wrapper asJQuery keydown: [ :e |\x0a        e which = 39 ifTrue: [ \x0a        \x09self nextFocus ].\x0a\x09\x09e which = 37 ifTrue: [ \x0a        \x09self previousFocus ] ]",
+messageSends: ["setupKeyBindings", "keydown:", "ifTrue:", "nextFocus", "=", "which", "previousFocus", "asJQuery", "wrapper"],
 referencedClasses: []
 }),
 smalltalk.HLNavigationListWidget);

+ 88 - 0
js/Helios-Environments.deploy.js

@@ -26,6 +26,17 @@ return self}, function($ctx1) {$ctx1.fill(self,"availableClassNames",{},smalltal
 messageSends: ["subclassResponsibility"]}),
 smalltalk.HLEnvironment);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "availablePackageNames",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(self)._subclassResponsibility();
+return self}, function($ctx1) {$ctx1.fill(self,"availablePackageNames",{},smalltalk.HLEnvironment)})},
+messageSends: ["subclassResponsibility"]}),
+smalltalk.HLEnvironment);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "availableProtocolsFor:",
@@ -119,6 +130,17 @@ return $1;
 messageSends: ["subclassResponsibility"]}),
 smalltalk.HLEnvironment);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "moveClass:toPackage:",
+fn: function (aClass,aPackageName){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(self)._subclassResponsibility();
+return self}, function($ctx1) {$ctx1.fill(self,"moveClass:toPackage:",{aClass:aClass,aPackageName:aPackageName},smalltalk.HLEnvironment)})},
+messageSends: ["subclassResponsibility"]}),
+smalltalk.HLEnvironment);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "moveMethod:toClass:",
@@ -154,6 +176,17 @@ return $1;
 messageSends: ["subclassResponsibility"]}),
 smalltalk.HLEnvironment);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "removeClass:",
+fn: function (aClass){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(self)._sublcassResponsibility();
+return self}, function($ctx1) {$ctx1.fill(self,"removeClass:",{aClass:aClass},smalltalk.HLEnvironment)})},
+messageSends: ["sublcassResponsibility"]}),
+smalltalk.HLEnvironment);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "removeMethod:",
@@ -198,6 +231,23 @@ return $1;
 messageSends: ["collect:", "name", "classes", "current"]}),
 smalltalk.HLLocalEnvironment);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "availablePackageNames",
+fn: function (){
+var self=this;
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(_st($Smalltalk())._current())._packages())._collect_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(each)._name();
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"availablePackageNames",{},smalltalk.HLLocalEnvironment)})},
+messageSends: ["collect:", "name", "packages", "current"]}),
+smalltalk.HLLocalEnvironment);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "availableProtocolsFor:",
@@ -292,6 +342,32 @@ catch(e) {if(e===$early)return e[0]; throw e}
 messageSends: ["new", "on:do:", "alert:", "messageText", "parseExpression:", "evaluateExpression:on:"]}),
 smalltalk.HLLocalEnvironment);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "moveClass:toPackage:",
+fn: function (aClass,aPackageName){
+var self=this;
+var package_;
+function $Package(){return smalltalk.Package||(typeof Package=="undefined"?nil:Package)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2,$3;
+package_=_st($Package())._named_(aPackageName);
+$1=package_;
+if(($receiver = $1) == nil || $receiver == undefined){
+_st(self)._error_("Invalid package name");
+} else {
+$1;
+};
+$2=_st(package_).__eq_eq(_st(aClass)._package());
+if(smalltalk.assert($2)){
+$3=self;
+return $3;
+};
+_st(package_)._addClass_(aClass);
+return self}, function($ctx1) {$ctx1.fill(self,"moveClass:toPackage:",{aClass:aClass,aPackageName:aPackageName,package_:package_},smalltalk.HLLocalEnvironment)})},
+messageSends: ["named:", "ifNil:", "error:", "ifTrue:", "==", "package", "addClass:"]}),
+smalltalk.HLLocalEnvironment);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "moveMethod:toClass:",
@@ -344,6 +420,18 @@ return $1;
 messageSends: ["packages", "current"]}),
 smalltalk.HLLocalEnvironment);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "removeClass:",
+fn: function (aClass){
+var self=this;
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
+return smalltalk.withContext(function($ctx1) { 
+_st(_st($Smalltalk())._current())._removeClass_(aClass);
+return self}, function($ctx1) {$ctx1.fill(self,"removeClass:",{aClass:aClass},smalltalk.HLLocalEnvironment)})},
+messageSends: ["removeClass:", "current"]}),
+smalltalk.HLLocalEnvironment);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "removeMethod:",

+ 118 - 0
js/Helios-Environments.js

@@ -37,6 +37,22 @@ referencedClasses: []
 }),
 smalltalk.HLEnvironment);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "availablePackageNames",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(self)._subclassResponsibility();
+return self}, function($ctx1) {$ctx1.fill(self,"availablePackageNames",{},smalltalk.HLEnvironment)})},
+args: [],
+source: "availablePackageNames\x0a\x09self subclassResponsibility",
+messageSends: ["subclassResponsibility"],
+referencedClasses: []
+}),
+smalltalk.HLEnvironment);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "availableProtocolsFor:",
@@ -170,6 +186,22 @@ referencedClasses: []
 }),
 smalltalk.HLEnvironment);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "moveClass:toPackage:",
+category: 'actions',
+fn: function (aClass,aPackageName){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(self)._subclassResponsibility();
+return self}, function($ctx1) {$ctx1.fill(self,"moveClass:toPackage:",{aClass:aClass,aPackageName:aPackageName},smalltalk.HLEnvironment)})},
+args: ["aClass", "aPackageName"],
+source: "moveClass: aClass toPackage: aPackageName\x0a\x09self subclassResponsibility",
+messageSends: ["subclassResponsibility"],
+referencedClasses: []
+}),
+smalltalk.HLEnvironment);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "moveMethod:toClass:",
@@ -220,6 +252,22 @@ referencedClasses: []
 }),
 smalltalk.HLEnvironment);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "removeClass:",
+category: 'actions',
+fn: function (aClass){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(self)._sublcassResponsibility();
+return self}, function($ctx1) {$ctx1.fill(self,"removeClass:",{aClass:aClass},smalltalk.HLEnvironment)})},
+args: ["aClass"],
+source: "removeClass: aClass\x0a\x09self sublcassResponsibility",
+messageSends: ["sublcassResponsibility"],
+referencedClasses: []
+}),
+smalltalk.HLEnvironment);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "removeMethod:",
@@ -279,6 +327,28 @@ referencedClasses: ["Smalltalk"]
 }),
 smalltalk.HLLocalEnvironment);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "availablePackageNames",
+category: 'accessing',
+fn: function (){
+var self=this;
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(_st($Smalltalk())._current())._packages())._collect_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(each)._name();
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"availablePackageNames",{},smalltalk.HLLocalEnvironment)})},
+args: [],
+source: "availablePackageNames\x0a\x09^ Smalltalk current packages \x0a\x09\x09collect: [ :each | each name ]",
+messageSends: ["collect:", "name", "packages", "current"],
+referencedClasses: ["Smalltalk"]
+}),
+smalltalk.HLLocalEnvironment);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "availableProtocolsFor:",
@@ -398,6 +468,37 @@ referencedClasses: ["Compiler", "Error"]
 }),
 smalltalk.HLLocalEnvironment);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "moveClass:toPackage:",
+category: 'actions',
+fn: function (aClass,aPackageName){
+var self=this;
+var package_;
+function $Package(){return smalltalk.Package||(typeof Package=="undefined"?nil:Package)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2,$3;
+package_=_st($Package())._named_(aPackageName);
+$1=package_;
+if(($receiver = $1) == nil || $receiver == undefined){
+_st(self)._error_("Invalid package name");
+} else {
+$1;
+};
+$2=_st(package_).__eq_eq(_st(aClass)._package());
+if(smalltalk.assert($2)){
+$3=self;
+return $3;
+};
+_st(package_)._addClass_(aClass);
+return self}, function($ctx1) {$ctx1.fill(self,"moveClass:toPackage:",{aClass:aClass,aPackageName:aPackageName,package_:package_},smalltalk.HLLocalEnvironment)})},
+args: ["aClass", "aPackageName"],
+source: "moveClass: aClass toPackage: aPackageName\x0a\x09| package |\x0a\x09\x0a\x09package := Package named: aPackageName.\x0a\x09package ifNil: [ self error: 'Invalid package name' ].\x0a\x09package == aClass package ifTrue: [ ^ self ].\x0a\x09\x0a\x09package addClass: aClass",
+messageSends: ["named:", "ifNil:", "error:", "ifTrue:", "==", "package", "addClass:"],
+referencedClasses: ["Package"]
+}),
+smalltalk.HLLocalEnvironment);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "moveMethod:toClass:",
@@ -465,6 +566,23 @@ referencedClasses: ["Smalltalk"]
 }),
 smalltalk.HLLocalEnvironment);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "removeClass:",
+category: 'actions',
+fn: function (aClass){
+var self=this;
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
+return smalltalk.withContext(function($ctx1) { 
+_st(_st($Smalltalk())._current())._removeClass_(aClass);
+return self}, function($ctx1) {$ctx1.fill(self,"removeClass:",{aClass:aClass},smalltalk.HLLocalEnvironment)})},
+args: ["aClass"],
+source: "removeClass: aClass\x0a\x09Smalltalk current removeClass: aClass",
+messageSends: ["removeClass:", "current"],
+referencedClasses: ["Smalltalk"]
+}),
+smalltalk.HLLocalEnvironment);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "removeMethod:",

+ 15 - 2
js/Helios-Inspector.deploy.js

@@ -762,6 +762,19 @@ return $1;
 messageSends: ["keys", "variables", "model"]}),
 smalltalk.HLInspectorVariablesWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "label",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(_st(_st(self)._model())._inspectee())._class())._name();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLInspectorVariablesWidget)})},
+messageSends: ["name", "class", "inspectee", "model"]}),
+smalltalk.HLInspectorVariablesWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "model",
@@ -847,9 +860,9 @@ return smalltalk.withContext(function($ctx1) {
 var $1,$2;
 $1=_st(html)._div();
 _st($1)._class_("list-label");
-$2=_st($1)._with_(_st(_st(_st(self)._model())._inspectee())._asString());
+$2=_st($1)._with_(_st(self)._label());
 return self}, function($ctx1) {$ctx1.fill(self,"renderHeadOn:",{html:html},smalltalk.HLInspectorVariablesWidget)})},
-messageSends: ["class:", "div", "with:", "asString", "inspectee", "model"]}),
+messageSends: ["class:", "div", "with:", "label"]}),
 smalltalk.HLInspectorVariablesWidget);
 
 smalltalk.addMethod(

+ 21 - 3
js/Helios-Inspector.js

@@ -1022,6 +1022,24 @@ referencedClasses: []
 }),
 smalltalk.HLInspectorVariablesWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "label",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(_st(_st(self)._model())._inspectee())._class())._name();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLInspectorVariablesWidget)})},
+args: [],
+source: "label\x0a\x09^ self model inspectee class name",
+messageSends: ["name", "class", "inspectee", "model"],
+referencedClasses: []
+}),
+smalltalk.HLInspectorVariablesWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "model",
@@ -1133,11 +1151,11 @@ return smalltalk.withContext(function($ctx1) {
 var $1,$2;
 $1=_st(html)._div();
 _st($1)._class_("list-label");
-$2=_st($1)._with_(_st(_st(_st(self)._model())._inspectee())._asString());
+$2=_st($1)._with_(_st(self)._label());
 return self}, function($ctx1) {$ctx1.fill(self,"renderHeadOn:",{html:html},smalltalk.HLInspectorVariablesWidget)})},
 args: ["html"],
-source: "renderHeadOn: html\x0a\x09html div \x0a\x09\x09class: 'list-label';\x0a\x09\x09with: self model inspectee asString",
-messageSends: ["class:", "div", "with:", "asString", "inspectee", "model"],
+source: "renderHeadOn: html\x0a\x09html div \x0a\x09\x09class: 'list-label';\x0a\x09\x09with: self label",
+messageSends: ["class:", "div", "with:", "label"],
 referencedClasses: []
 }),
 smalltalk.HLInspectorVariablesWidget);

+ 30 - 39
js/Helios-Layout.deploy.js

@@ -1,5 +1,5 @@
 smalltalk.addPackage('Helios-Layout');
-smalltalk.addClass('HLContainer', smalltalk.Widget, ['splitter'], 'Helios-Layout');
+smalltalk.addClass('HLContainer', smalltalk.HLWidget, ['splitter'], 'Helios-Layout');
 smalltalk.addMethod(
 smalltalk.method({
 selector: "renderOn:",
@@ -10,12 +10,8 @@ var $1,$2;
 $1=_st(html)._div();
 _st($1)._class_("tool_container");
 $2=_st($1)._with_(_st(self)._splitter());
-_st(_st(window)._jQuery_(window))._bind_do_("resize",(function(){
-return smalltalk.withContext(function($ctx2) {
-return _st(_st(self)._splitter())._resize();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"renderOn:",{html:html},smalltalk.HLContainer)})},
-messageSends: ["class:", "div", "with:", "splitter", "bind:do:", "resize", "jQuery:"]}),
+messageSends: ["class:", "div", "with:", "splitter"]}),
 smalltalk.HLContainer);
 
 smalltalk.addMethod(
@@ -124,7 +120,7 @@ selector: "renderOn:",
 fn: function (html){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-var $1,$3,$4,$5,$6,$2,$7,$8;
+var $1,$3,$4,$5,$6,$2;
 $1=_st(html)._div();
 _st($1)._class_(_st(self)._panesCssClass());
 $2=_st($1)._with_((function(){
@@ -142,11 +138,9 @@ $6=_st($5)._with_(_st(self)._secondWidget());
 self["@secondPane"]=$6;
 return self["@secondPane"];
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-$7=self;
-_st($7)._setupSplitter();
-$8=_st($7)._resize();
+_st(self)._setupSplitter();
 return self}, function($ctx1) {$ctx1.fill(self,"renderOn:",{html:html},smalltalk.HLSplitter)})},
-messageSends: ["class:", "panesCssClass", "div", "with:", "firstWidget", "cssClass", "secondWidget", "setupSplitter", "resize"]}),
+messageSends: ["class:", "panesCssClass", "div", "with:", "firstWidget", "cssClass", "secondWidget", "setupSplitter"]}),
 smalltalk.HLSplitter);
 
 smalltalk.addMethod(
@@ -155,17 +149,8 @@ selector: "resize",
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=_st(_st(self)._firstWidget())._isHeliosSplitter();
-if(smalltalk.assert($1)){
-_st(_st(self)._firstWidget())._resize();
-};
-$2=_st(_st(self)._secondWidget())._isHeliosSplitter();
-if(smalltalk.assert($2)){
-_st(_st(self)._secondWidget())._resize();
-};
 return self}, function($ctx1) {$ctx1.fill(self,"resize",{},smalltalk.HLSplitter)})},
-messageSends: ["ifTrue:", "resize", "firstWidget", "isHeliosSplitter", "secondWidget"]}),
+messageSends: []}),
 smalltalk.HLSplitter);
 
 smalltalk.addMethod(
@@ -254,9 +239,9 @@ selector: "resize",
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-_st(self)._resize_(_st(_st(_st(self["@splitter"])._asJQuery())._offset())._top());
+_st(self)._resize_(_st(_st(self["@splitter"])._asJQuery())._css_("top"));
 return self}, function($ctx1) {$ctx1.fill(self,"resize",{},smalltalk.HLHorizontalSplitter)})},
-messageSends: ["resize:", "top", "offset", "asJQuery"]}),
+messageSends: ["resize:", "css:", "asJQuery"]}),
 smalltalk.HLHorizontalSplitter);
 
 smalltalk.addMethod(
@@ -264,15 +249,18 @@ smalltalk.method({
 selector: "resize:",
 fn: function (anInteger){
 var self=this;
-var container,position;
+var container,size,offset,percentage;
 return smalltalk.withContext(function($ctx1) { 
 container=_st(_st(self["@firstPane"])._asJQuery())._parent();
-position=_st(anInteger).__minus(_st(_st(container)._offset())._top());
-_st(_st(self["@firstPane"])._asJQuery())._height_(_st(_st(position)._min_(_st(_st(container)._height()).__minus((100))))._max_((100)));
-_st(_st(self["@secondPane"])._asJQuery())._height_(_st(_st(_st(_st(_st(container)._height()).__minus(position))._min_(_st(_st(container)._height()).__minus((100))))._max_((100))).__minus((1)));
-smalltalk.HLSplitter.fn.prototype._resize.apply(_st(self), []);
-return self}, function($ctx1) {$ctx1.fill(self,"resize:",{anInteger:anInteger,container:container,position:position},smalltalk.HLHorizontalSplitter)})},
-messageSends: ["parent", "asJQuery", "-", "top", "offset", "height:", "max:", "min:", "height", "resize"]}),
+offset=_st(_st(_st(self["@firstPane"])._asJQuery())._offset())._top();
+size=_st(container)._height();
+percentage=_st(_st(_st(size).__minus(_st(anInteger).__minus(offset))).__slash(size)).__star((100));
+percentage=_st((80))._min_(_st(percentage)._max_((20)));
+_st(_st(self["@firstPane"])._asJQuery())._css_put_("bottom",_st(_st(percentage)._asString()).__comma("%"));
+_st(_st(self["@splitter"])._asJQuery())._css_put_("top",_st(_st(_st((100)).__minus(percentage))._asString()).__comma("%"));
+_st(_st(self["@secondPane"])._asJQuery())._css_put_("top",_st(_st(_st((100)).__minus(percentage))._asString()).__comma("%"));
+return self}, function($ctx1) {$ctx1.fill(self,"resize:",{anInteger:anInteger,container:container,size:size,offset:offset,percentage:percentage},smalltalk.HLHorizontalSplitter)})},
+messageSends: ["parent", "asJQuery", "top", "offset", "height", "*", "/", "-", "min:", "max:", "css:put:", ",", "asString"]}),
 smalltalk.HLHorizontalSplitter);
 
 smalltalk.addMethod(
@@ -338,9 +326,9 @@ selector: "resize",
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-_st(self)._resize_(_st(_st(_st(self["@splitter"])._asJQuery())._offset())._left());
+_st(self)._resize_(_st(_st(self["@splitter"])._asJQuery())._css_("left"));
 return self}, function($ctx1) {$ctx1.fill(self,"resize",{},smalltalk.HLVerticalSplitter)})},
-messageSends: ["resize:", "left", "offset", "asJQuery"]}),
+messageSends: ["resize:", "css:", "asJQuery"]}),
 smalltalk.HLVerticalSplitter);
 
 smalltalk.addMethod(
@@ -348,15 +336,18 @@ smalltalk.method({
 selector: "resize:",
 fn: function (anInteger){
 var self=this;
-var container,position;
+var container,size,offset,percentage;
 return smalltalk.withContext(function($ctx1) { 
 container=_st(_st(self["@firstPane"])._asJQuery())._parent();
-position=_st(anInteger).__minus(_st(_st(container)._offset())._left());
-_st(_st(self["@firstPane"])._asJQuery())._width_(_st(_st(position)._min_(_st(_st(container)._width()).__minus((100))))._max_((100)));
-_st(_st(self["@secondPane"])._asJQuery())._width_(_st(_st(_st(_st(_st(container)._width()).__minus(position))._min_(_st(_st(container)._width()).__minus((100))))._max_((100))).__minus((1)));
-smalltalk.HLSplitter.fn.prototype._resize.apply(_st(self), []);
-return self}, function($ctx1) {$ctx1.fill(self,"resize:",{anInteger:anInteger,container:container,position:position},smalltalk.HLVerticalSplitter)})},
-messageSends: ["parent", "asJQuery", "-", "left", "offset", "width:", "max:", "min:", "width", "resize"]}),
+offset=_st(_st(_st(self["@firstPane"])._asJQuery())._offset())._left();
+size=_st(container)._width();
+percentage=_st(_st(_st(size).__minus(_st(anInteger).__minus(offset))).__slash(size)).__star((100));
+percentage=_st((80))._min_(_st(percentage)._max_((20)));
+_st(_st(self["@firstPane"])._asJQuery())._css_put_("right",_st(_st(percentage)._asString()).__comma("%"));
+_st(_st(self["@splitter"])._asJQuery())._css_put_("left",_st(_st(_st((100)).__minus(percentage))._asString()).__comma("%"));
+_st(_st(self["@secondPane"])._asJQuery())._css_put_("left",_st(_st(_st((100)).__minus(percentage))._asString()).__comma("%"));
+return self}, function($ctx1) {$ctx1.fill(self,"resize:",{anInteger:anInteger,container:container,size:size,offset:offset,percentage:percentage},smalltalk.HLVerticalSplitter)})},
+messageSends: ["parent", "asJQuery", "left", "offset", "width", "*", "/", "-", "min:", "max:", "css:put:", ",", "asString"]}),
 smalltalk.HLVerticalSplitter);
 
 smalltalk.addMethod(

+ 38 - 47
js/Helios-Layout.js

@@ -1,5 +1,5 @@
 smalltalk.addPackage('Helios-Layout');
-smalltalk.addClass('HLContainer', smalltalk.Widget, ['splitter'], 'Helios-Layout');
+smalltalk.addClass('HLContainer', smalltalk.HLWidget, ['splitter'], 'Helios-Layout');
 smalltalk.addMethod(
 smalltalk.method({
 selector: "renderOn:",
@@ -11,14 +11,10 @@ var $1,$2;
 $1=_st(html)._div();
 _st($1)._class_("tool_container");
 $2=_st($1)._with_(_st(self)._splitter());
-_st(_st(window)._jQuery_(window))._bind_do_("resize",(function(){
-return smalltalk.withContext(function($ctx2) {
-return _st(_st(self)._splitter())._resize();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"renderOn:",{html:html},smalltalk.HLContainer)})},
 args: ["html"],
-source: "renderOn: html\x0a\x09html div \x0a    \x09class: 'tool_container'; \x0a        with: self splitter.\x0a        \x0a   (window jQuery: window) bind: 'resize' do: [ self splitter resize ]",
-messageSends: ["class:", "div", "with:", "splitter", "bind:do:", "resize", "jQuery:"],
+source: "renderOn: html\x0a\x09html div \x0a    \x09class: 'tool_container'; \x0a        with: self splitter",
+messageSends: ["class:", "div", "with:", "splitter"],
 referencedClasses: []
 }),
 smalltalk.HLContainer);
@@ -170,7 +166,7 @@ category: 'rendering',
 fn: function (html){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-var $1,$3,$4,$5,$6,$2,$7,$8;
+var $1,$3,$4,$5,$6,$2;
 $1=_st(html)._div();
 _st($1)._class_(_st(self)._panesCssClass());
 $2=_st($1)._with_((function(){
@@ -188,13 +184,11 @@ $6=_st($5)._with_(_st(self)._secondWidget());
 self["@secondPane"]=$6;
 return self["@secondPane"];
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-$7=self;
-_st($7)._setupSplitter();
-$8=_st($7)._resize();
+_st(self)._setupSplitter();
 return self}, function($ctx1) {$ctx1.fill(self,"renderOn:",{html:html},smalltalk.HLSplitter)})},
 args: ["html"],
-source: "renderOn: html\x0a\x09html div class: self panesCssClass; with: [\x0a\x09\x09firstPane := html div class: 'pane'; with: self firstWidget.\x0a    \x09splitter := html div class: self cssClass.\x0a    \x09secondPane := html div class: 'pane'; with: self secondWidget ].\x0a        \x0a\x09self \x0a    \x09setupSplitter;\x0a        resize",
-messageSends: ["class:", "panesCssClass", "div", "with:", "firstWidget", "cssClass", "secondWidget", "setupSplitter", "resize"],
+source: "renderOn: html\x0a\x09html div class: self panesCssClass; with: [\x0a\x09\x09firstPane := html div class: 'pane'; with: self firstWidget.\x0a    \x09splitter := html div class: self cssClass.\x0a    \x09secondPane := html div class: 'pane'; with: self secondWidget ].\x0a        \x0a\x09self setupSplitter",
+messageSends: ["class:", "panesCssClass", "div", "with:", "firstWidget", "cssClass", "secondWidget", "setupSplitter"],
 referencedClasses: []
 }),
 smalltalk.HLSplitter);
@@ -206,19 +200,10 @@ category: 'rendering',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=_st(_st(self)._firstWidget())._isHeliosSplitter();
-if(smalltalk.assert($1)){
-_st(_st(self)._firstWidget())._resize();
-};
-$2=_st(_st(self)._secondWidget())._isHeliosSplitter();
-if(smalltalk.assert($2)){
-_st(_st(self)._secondWidget())._resize();
-};
 return self}, function($ctx1) {$ctx1.fill(self,"resize",{},smalltalk.HLSplitter)})},
 args: [],
-source: "resize\x0a\x09self firstWidget isHeliosSplitter ifTrue: [ self firstWidget resize ].\x0a    self secondWidget isHeliosSplitter ifTrue: [ self secondWidget resize ]",
-messageSends: ["ifTrue:", "resize", "firstWidget", "isHeliosSplitter", "secondWidget"],
+source: "resize",
+messageSends: [],
 referencedClasses: []
 }),
 smalltalk.HLSplitter);
@@ -340,11 +325,11 @@ category: 'actions',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-_st(self)._resize_(_st(_st(_st(self["@splitter"])._asJQuery())._offset())._top());
+_st(self)._resize_(_st(_st(self["@splitter"])._asJQuery())._css_("top"));
 return self}, function($ctx1) {$ctx1.fill(self,"resize",{},smalltalk.HLHorizontalSplitter)})},
 args: [],
-source: "resize\x0a\x09self resize: splitter asJQuery offset top",
-messageSends: ["resize:", "top", "offset", "asJQuery"],
+source: "resize\x0a\x09self resize: (splitter asJQuery css: 'top')",
+messageSends: ["resize:", "css:", "asJQuery"],
 referencedClasses: []
 }),
 smalltalk.HLHorizontalSplitter);
@@ -355,17 +340,20 @@ selector: "resize:",
 category: 'actions',
 fn: function (anInteger){
 var self=this;
-var container,position;
+var container,size,offset,percentage;
 return smalltalk.withContext(function($ctx1) { 
 container=_st(_st(self["@firstPane"])._asJQuery())._parent();
-position=_st(anInteger).__minus(_st(_st(container)._offset())._top());
-_st(_st(self["@firstPane"])._asJQuery())._height_(_st(_st(position)._min_(_st(_st(container)._height()).__minus((100))))._max_((100)));
-_st(_st(self["@secondPane"])._asJQuery())._height_(_st(_st(_st(_st(_st(container)._height()).__minus(position))._min_(_st(_st(container)._height()).__minus((100))))._max_((100))).__minus((1)));
-smalltalk.HLSplitter.fn.prototype._resize.apply(_st(self), []);
-return self}, function($ctx1) {$ctx1.fill(self,"resize:",{anInteger:anInteger,container:container,position:position},smalltalk.HLHorizontalSplitter)})},
+offset=_st(_st(_st(self["@firstPane"])._asJQuery())._offset())._top();
+size=_st(container)._height();
+percentage=_st(_st(_st(size).__minus(_st(anInteger).__minus(offset))).__slash(size)).__star((100));
+percentage=_st((80))._min_(_st(percentage)._max_((20)));
+_st(_st(self["@firstPane"])._asJQuery())._css_put_("bottom",_st(_st(percentage)._asString()).__comma("%"));
+_st(_st(self["@splitter"])._asJQuery())._css_put_("top",_st(_st(_st((100)).__minus(percentage))._asString()).__comma("%"));
+_st(_st(self["@secondPane"])._asJQuery())._css_put_("top",_st(_st(_st((100)).__minus(percentage))._asString()).__comma("%"));
+return self}, function($ctx1) {$ctx1.fill(self,"resize:",{anInteger:anInteger,container:container,size:size,offset:offset,percentage:percentage},smalltalk.HLHorizontalSplitter)})},
 args: ["anInteger"],
-source: "resize: anInteger\x0a\x09| container position |\x0a    \x0a    container := firstPane asJQuery parent.\x0a    position := anInteger - container offset top.\x0a    \x0a\x09firstPane asJQuery height: ((position min: container height - 100) max: 100).\x0a    secondPane asJQuery height: (((container height - position) min: container height - 100) max: 100) - 1.\x0a    \x0a    super resize",
-messageSends: ["parent", "asJQuery", "-", "top", "offset", "height:", "max:", "min:", "height", "resize"],
+source: "resize: anInteger\x0a\x09| container size offset percentage |\x0a    \x0a    container := firstPane asJQuery parent.\x0a\x09offset := firstPane asJQuery offset top.\x0a    size := container height.\x0a\x09\x0a\x09percentage := (size - (anInteger - offset)) / size * 100.\x0a\x09percentage := 80 min: (percentage max: 20).\x0a\x09\x0a    firstPane asJQuery css: 'bottom' put: percentage asString, '%'.\x0a\x09\x0a\x09splitter asJQuery css: 'top' put: (100 - percentage) asString, '%'.\x0a\x09secondPane asJQuery css: 'top' put: (100 - percentage) asString, '%'",
+messageSends: ["parent", "asJQuery", "top", "offset", "height", "*", "/", "-", "min:", "max:", "css:put:", ",", "asString"],
 referencedClasses: []
 }),
 smalltalk.HLHorizontalSplitter);
@@ -454,11 +442,11 @@ category: 'actions',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-_st(self)._resize_(_st(_st(_st(self["@splitter"])._asJQuery())._offset())._left());
+_st(self)._resize_(_st(_st(self["@splitter"])._asJQuery())._css_("left"));
 return self}, function($ctx1) {$ctx1.fill(self,"resize",{},smalltalk.HLVerticalSplitter)})},
 args: [],
-source: "resize\x0a\x09self resize: splitter asJQuery offset left",
-messageSends: ["resize:", "left", "offset", "asJQuery"],
+source: "resize\x0a\x09self resize: (splitter asJQuery css: 'left')",
+messageSends: ["resize:", "css:", "asJQuery"],
 referencedClasses: []
 }),
 smalltalk.HLVerticalSplitter);
@@ -469,17 +457,20 @@ selector: "resize:",
 category: 'actions',
 fn: function (anInteger){
 var self=this;
-var container,position;
+var container,size,offset,percentage;
 return smalltalk.withContext(function($ctx1) { 
 container=_st(_st(self["@firstPane"])._asJQuery())._parent();
-position=_st(anInteger).__minus(_st(_st(container)._offset())._left());
-_st(_st(self["@firstPane"])._asJQuery())._width_(_st(_st(position)._min_(_st(_st(container)._width()).__minus((100))))._max_((100)));
-_st(_st(self["@secondPane"])._asJQuery())._width_(_st(_st(_st(_st(_st(container)._width()).__minus(position))._min_(_st(_st(container)._width()).__minus((100))))._max_((100))).__minus((1)));
-smalltalk.HLSplitter.fn.prototype._resize.apply(_st(self), []);
-return self}, function($ctx1) {$ctx1.fill(self,"resize:",{anInteger:anInteger,container:container,position:position},smalltalk.HLVerticalSplitter)})},
+offset=_st(_st(_st(self["@firstPane"])._asJQuery())._offset())._left();
+size=_st(container)._width();
+percentage=_st(_st(_st(size).__minus(_st(anInteger).__minus(offset))).__slash(size)).__star((100));
+percentage=_st((80))._min_(_st(percentage)._max_((20)));
+_st(_st(self["@firstPane"])._asJQuery())._css_put_("right",_st(_st(percentage)._asString()).__comma("%"));
+_st(_st(self["@splitter"])._asJQuery())._css_put_("left",_st(_st(_st((100)).__minus(percentage))._asString()).__comma("%"));
+_st(_st(self["@secondPane"])._asJQuery())._css_put_("left",_st(_st(_st((100)).__minus(percentage))._asString()).__comma("%"));
+return self}, function($ctx1) {$ctx1.fill(self,"resize:",{anInteger:anInteger,container:container,size:size,offset:offset,percentage:percentage},smalltalk.HLVerticalSplitter)})},
 args: ["anInteger"],
-source: "resize: anInteger\x0a\x09| container position |\x0a    \x0a    container := firstPane asJQuery parent.\x0a    position := anInteger - container offset left.\x0a    \x0a\x09firstPane asJQuery width: ((position min: container width - 100) max: 100).\x0a    secondPane asJQuery width: (((container width - position) min: container width - 100) max: 100) - 1.\x0a    \x0a    super resize",
-messageSends: ["parent", "asJQuery", "-", "left", "offset", "width:", "max:", "min:", "width", "resize"],
+source: "resize: anInteger\x0a\x09| container size offset percentage |\x0a    \x0a    container := firstPane asJQuery parent.\x0a\x09offset := firstPane asJQuery offset left.\x0a    size := container width.\x0a\x09\x0a\x09percentage := (size - (anInteger - offset)) / size * 100.\x0a\x09percentage := 80 min: (percentage max: 20).\x0a\x09\x0a    firstPane asJQuery css: 'right' put: percentage asString, '%'.\x0a\x09\x0a\x09splitter asJQuery css: 'left' put: (100 - percentage) asString, '%'.\x0a\x09secondPane asJQuery css: 'left' put: (100 - percentage) asString, '%'",
+messageSends: ["parent", "asJQuery", "left", "offset", "width", "*", "/", "-", "min:", "max:", "css:put:", ",", "asString"],
 referencedClasses: []
 }),
 smalltalk.HLVerticalSplitter);
@@ -500,7 +491,7 @@ return _st(self)._resize_(_st(_st(ui)._offset())._left());
 }, function($ctx2) {$ctx2.fillBlock({e:e,ui:ui},$ctx1)})}))]));
 return self}, function($ctx1) {$ctx1.fill(self,"setupSplitter",{},smalltalk.HLVerticalSplitter)})},
 args: [],
-source: "setupSplitter\x0a\x09splitter asJQuery draggable: #{ \x0a    \x09'axis' -> 'x'. \x0a        'containment' -> splitter asJQuery parent.\x0a        'helper' -> 'clone'.\x0a        'start' -> [ :e :ui | self startResizing: ui helper ].\x0a        'drag' -> [ :e :ui | self resize: ui offset left ] }",
+source: "setupSplitter\x0a\x09splitter asJQuery draggable: #{ \x0a    \x09'axis' -> 'x'. \x0a        'containment' -> splitter asJQuery parent.\x0a        'helper' -> 'clone'.\x0a        'start' -> [ :e :ui | self startResizing: ui helper ].\x0a        'drag' -> [ :e :ui | self resize: (ui offset left) ] }",
 messageSends: ["draggable:", "->", "parent", "asJQuery", "startResizing:", "helper", "resize:", "left", "offset"],
 referencedClasses: []
 }),

+ 241 - 5
js/Helios-Workspace.deploy.js

@@ -827,7 +827,7 @@ messageSends: ["variableHintFor:token:", "at:"]}),
 smalltalk.HLCodeWidget.klass);
 
 
-smalltalk.addClass('HLSourceCodeWidget', smalltalk.HLCodeWidget, ['browserModel'], 'Helios-Workspace');
+smalltalk.addClass('HLSourceCodeWidget', smalltalk.HLCodeWidget, ['browserModel', 'methodContents'], 'Helios-Workspace');
 smalltalk.addMethod(
 smalltalk.method({
 selector: "browserModel",
@@ -847,10 +847,50 @@ selector: "browserModel:",
 fn: function (aBrowserModel){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
 self["@browserModel"]=aBrowserModel;
-_st(self)._observeBrowserModel();
+$1=self;
+_st($1)._observeSystem();
+$2=_st($1)._observeBrowserModel();
 return self}, function($ctx1) {$ctx1.fill(self,"browserModel:",{aBrowserModel:aBrowserModel},smalltalk.HLSourceCodeWidget)})},
-messageSends: ["observeBrowserModel"]}),
+messageSends: ["observeSystem", "observeBrowserModel"]}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "hasModification",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(_st(self)._methodContents()).__eq(_st(self)._contents()))._not();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"hasModification",{},smalltalk.HLSourceCodeWidget)})},
+messageSends: ["not", "=", "contents", "methodContents"]}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "methodContents",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self["@methodContents"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"methodContents",{},smalltalk.HLSourceCodeWidget)})},
+messageSends: []}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "methodContents:",
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@methodContents"]=aString;
+return self}, function($ctx1) {$ctx1.fill(self,"methodContents:",{aString:aString},smalltalk.HLSourceCodeWidget)})},
+messageSends: []}),
 smalltalk.HLSourceCodeWidget);
 
 smalltalk.addMethod(
@@ -863,6 +903,10 @@ function $HLParseErrorRaised(){return smalltalk.HLParseErrorRaised||(typeof HLPa
 function $HLCompileErrorRaised(){return smalltalk.HLCompileErrorRaised||(typeof HLCompileErrorRaised=="undefined"?nil:HLCompileErrorRaised)}
 function $HLUnknownVariableErrorRaised(){return smalltalk.HLUnknownVariableErrorRaised||(typeof HLUnknownVariableErrorRaised=="undefined"?nil:HLUnknownVariableErrorRaised)}
 function $HLInstVarAdded(){return smalltalk.HLInstVarAdded||(typeof HLInstVarAdded=="undefined"?nil:HLInstVarAdded)}
+function $HLMethodSelected(){return smalltalk.HLMethodSelected||(typeof HLMethodSelected=="undefined"?nil:HLMethodSelected)}
+function $HLClassSelected(){return smalltalk.HLClassSelected||(typeof HLClassSelected=="undefined"?nil:HLClassSelected)}
+function $HLProtocolSelected(){return smalltalk.HLProtocolSelected||(typeof HLProtocolSelected=="undefined"?nil:HLProtocolSelected)}
+function $HLSourceCodeFocusRequested(){return smalltalk.HLSourceCodeFocusRequested||(typeof HLSourceCodeFocusRequested=="undefined"?nil:HLSourceCodeFocusRequested)}
 return smalltalk.withContext(function($ctx1) { 
 var $1,$2;
 $1=_st(_st(self)._browserModel())._announcer();
@@ -882,12 +926,84 @@ _st($1)._on_do_($HLUnknownVariableErrorRaised(),(function(ann){
 return smalltalk.withContext(function($ctx2) {
 return _st(self)._onUnknownVariableError_(_st(ann)._error());
 }, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
-$2=_st($1)._on_do_($HLInstVarAdded(),(function(ann){
+_st($1)._on_do_($HLInstVarAdded(),(function(ann){
 return smalltalk.withContext(function($ctx2) {
 return _st(self)._onInstVarAdded();
 }, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+_st($1)._on_do_($HLMethodSelected(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onMethodSelected_(_st(ann)._item());
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+_st($1)._on_do_($HLClassSelected(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onClassSelected_(_st(ann)._item());
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+_st($1)._on_do_($HLProtocolSelected(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onProtocolSelected_(_st(ann)._item());
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+$2=_st($1)._on_do_($HLSourceCodeFocusRequested(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onSourceCodeFocusRequested();
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"observeBrowserModel",{},smalltalk.HLSourceCodeWidget)})},
-messageSends: ["on:do:", "onSaveIt", "announcer", "browserModel", "onParseError:", "onCompileError:", "error", "onUnknownVariableError:", "onInstVarAdded"]}),
+messageSends: ["on:do:", "onSaveIt", "announcer", "browserModel", "onParseError:", "onCompileError:", "error", "onUnknownVariableError:", "onInstVarAdded", "onMethodSelected:", "item", "onClassSelected:", "onProtocolSelected:", "onSourceCodeFocusRequested"]}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "observeSystem",
+fn: function (){
+var self=this;
+function $MethodModified(){return smalltalk.MethodModified||(typeof MethodModified=="undefined"?nil:MethodModified)}
+function $HLMethodSelected(){return smalltalk.HLMethodSelected||(typeof HLMethodSelected=="undefined"?nil:HLMethodSelected)}
+function $HLClassSelected(){return smalltalk.HLClassSelected||(typeof HLClassSelected=="undefined"?nil:HLClassSelected)}
+function $HLProtocolSelected(){return smalltalk.HLProtocolSelected||(typeof HLProtocolSelected=="undefined"?nil:HLProtocolSelected)}
+function $HLSourceCodeFocusRequested(){return smalltalk.HLSourceCodeFocusRequested||(typeof HLSourceCodeFocusRequested=="undefined"?nil:HLSourceCodeFocusRequested)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=_st(_st(self)._browserModel())._systemAnnouncer();
+_st($1)._on_do_($MethodModified(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onMethodModified_(_st(ann)._method());
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+_st($1)._on_do_($HLMethodSelected(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onMethodSelected_(_st(ann)._item());
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+_st($1)._on_do_($HLClassSelected(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onClassSelected_(_st(ann)._item());
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+_st($1)._on_do_($HLProtocolSelected(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onProtocolSelected_(_st(ann)._item());
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+$2=_st($1)._on_do_($HLSourceCodeFocusRequested(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onSourceCodeFocusRequested();
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"observeSystem",{},smalltalk.HLSourceCodeWidget)})},
+messageSends: ["on:do:", "onMethodModified:", "method", "systemAnnouncer", "browserModel", "onMethodSelected:", "item", "onClassSelected:", "onProtocolSelected:", "onSourceCodeFocusRequested"]}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "onClassSelected:",
+fn: function (aClass){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=aClass;
+if(($receiver = $1) == nil || $receiver == undefined){
+$2=_st(self)._contents_("");
+return $2;
+} else {
+$1;
+};
+_st(self)._contents_(_st(aClass)._definition());
+return self}, function($ctx1) {$ctx1.fill(self,"onClassSelected:",{aClass:aClass},smalltalk.HLSourceCodeWidget)})},
+messageSends: ["ifNil:", "contents:", "definition"]}),
 smalltalk.HLSourceCodeWidget);
 
 smalltalk.addMethod(
@@ -912,6 +1028,54 @@ return self}, function($ctx1) {$ctx1.fill(self,"onInstVarAdded",{},smalltalk.HLS
 messageSends: ["save:", "contents", "browserModel"]}),
 smalltalk.HLSourceCodeWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "onMethodModified:",
+fn: function (aMethod){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2,$3,$4,$5,$6;
+$1=_st(_st(_st(self)._browserModel())._selectedClass()).__eq(_st(aMethod)._methodClass());
+if(! smalltalk.assert($1)){
+$2=self;
+return $2;
+};
+$3=_st(_st(self)._browserModel())._selectedMethod();
+if(($receiver = $3) == nil || $receiver == undefined){
+$4=self;
+return $4;
+} else {
+$3;
+};
+$5=_st(_st(_st(_st(self)._browserModel())._selectedMethod())._selector()).__eq(_st(aMethod)._selector());
+if(! smalltalk.assert($5)){
+$6=self;
+return $6;
+};
+_st(self)._refresh();
+return self}, function($ctx1) {$ctx1.fill(self,"onMethodModified:",{aMethod:aMethod},smalltalk.HLSourceCodeWidget)})},
+messageSends: ["ifFalse:", "=", "methodClass", "selectedClass", "browserModel", "ifNil:", "selectedMethod", "selector", "refresh"]}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "onMethodSelected:",
+fn: function (aCompiledMethod){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=aCompiledMethod;
+if(($receiver = $1) == nil || $receiver == undefined){
+$2=_st(self)._contents_("");
+return $2;
+} else {
+$1;
+};
+_st(self)._contents_(_st(aCompiledMethod)._source());
+return self}, function($ctx1) {$ctx1.fill(self,"onMethodSelected:",{aCompiledMethod:aCompiledMethod},smalltalk.HLSourceCodeWidget)})},
+messageSends: ["ifNil:", "contents:", "source"]}),
+smalltalk.HLSourceCodeWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "onParseError:",
@@ -947,6 +1111,25 @@ return self}, function($ctx1) {$ctx1.fill(self,"onParseError:",{anAnnouncement:a
 messageSends: ["contents:", "streamContents:", "linesDo:", "ifTrue:ifFalse:", "nextPutAll:", "copyFrom:to:", "column", "message", "+", "size", "=", "line", "cr", "contents"]}),
 smalltalk.HLSourceCodeWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "onProtocolSelected:",
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=_st(_st(self)._browserModel())._selectedClass();
+if(($receiver = $1) == nil || $receiver == undefined){
+$2=_st(self)._contents_("");
+return $2;
+} else {
+$1;
+};
+_st(self)._contents_(_st(_st(_st(self)._browserModel())._selectedClass())._definition());
+return self}, function($ctx1) {$ctx1.fill(self,"onProtocolSelected:",{aString:aString},smalltalk.HLSourceCodeWidget)})},
+messageSends: ["ifNil:", "contents:", "selectedClass", "browserModel", "definition"]}),
+smalltalk.HLSourceCodeWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "onSaveIt",
@@ -958,6 +1141,17 @@ return self}, function($ctx1) {$ctx1.fill(self,"onSaveIt",{},smalltalk.HLSourceC
 messageSends: ["save:", "contents", "browserModel"]}),
 smalltalk.HLSourceCodeWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "onSourceCodeFocusRequested",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(self)._focus();
+return self}, function($ctx1) {$ctx1.fill(self,"onSourceCodeFocusRequested",{},smalltalk.HLSourceCodeWidget)})},
+messageSends: ["focus"]}),
+smalltalk.HLSourceCodeWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "onUnknownVariableError:",
@@ -985,6 +1179,48 @@ return self}, function($ctx1) {$ctx1.fill(self,"onUnknownVariableError:",{anErro
 messageSends: ["confirm:", "streamContents:", "nextPutAll:", "messageText", "cr", "ifFalse:", "addInstVarNamed:", "variableName", "browserModel"]}),
 smalltalk.HLSourceCodeWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "previous",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return self}, function($ctx1) {$ctx1.fill(self,"previous",{},smalltalk.HLSourceCodeWidget)})},
+messageSends: []}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "previous:",
+fn: function (aWidget){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return self}, function($ctx1) {$ctx1.fill(self,"previous:",{aWidget:aWidget},smalltalk.HLSourceCodeWidget)})},
+messageSends: []}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "refresh",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2,$3,$4;
+$1=_st(self)._hasModification();
+if(smalltalk.assert($1)){
+$2=self;
+return $2;
+};
+$3=_st(self)._hasFocus();
+if(smalltalk.assert($3)){
+$4=self;
+return $4;
+};
+_st(self)._contents_(_st(_st(_st(self)._model())._selectedMethod())._source());
+return self}, function($ctx1) {$ctx1.fill(self,"refresh",{},smalltalk.HLSourceCodeWidget)})},
+messageSends: ["ifTrue:", "hasModification", "hasFocus", "contents:", "source", "selectedMethod", "model"]}),
+smalltalk.HLSourceCodeWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "saveIt",

+ 305 - 9
js/Helios-Workspace.js

@@ -1107,7 +1107,7 @@ referencedClasses: []
 smalltalk.HLCodeWidget.klass);
 
 
-smalltalk.addClass('HLSourceCodeWidget', smalltalk.HLCodeWidget, ['browserModel'], 'Helios-Workspace');
+smalltalk.addClass('HLSourceCodeWidget', smalltalk.HLCodeWidget, ['browserModel', 'methodContents'], 'Helios-Workspace');
 smalltalk.addMethod(
 smalltalk.method({
 selector: "browserModel",
@@ -1133,12 +1133,67 @@ category: 'accessing',
 fn: function (aBrowserModel){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
 self["@browserModel"]=aBrowserModel;
-_st(self)._observeBrowserModel();
+$1=self;
+_st($1)._observeSystem();
+$2=_st($1)._observeBrowserModel();
 return self}, function($ctx1) {$ctx1.fill(self,"browserModel:",{aBrowserModel:aBrowserModel},smalltalk.HLSourceCodeWidget)})},
 args: ["aBrowserModel"],
-source: "browserModel: aBrowserModel\x0a\x09browserModel := aBrowserModel.\x0a\x09self observeBrowserModel",
-messageSends: ["observeBrowserModel"],
+source: "browserModel: aBrowserModel\x0a\x09browserModel := aBrowserModel.\x0a\x09self \x0a\x09\x09observeSystem;\x0a\x09\x09observeBrowserModel",
+messageSends: ["observeSystem", "observeBrowserModel"],
+referencedClasses: []
+}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "hasModification",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(_st(self)._methodContents()).__eq(_st(self)._contents()))._not();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"hasModification",{},smalltalk.HLSourceCodeWidget)})},
+args: [],
+source: "hasModification\x0a\x09^ (self methodContents = self contents) not",
+messageSends: ["not", "=", "contents", "methodContents"],
+referencedClasses: []
+}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "methodContents",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self["@methodContents"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"methodContents",{},smalltalk.HLSourceCodeWidget)})},
+args: [],
+source: "methodContents\x0a\x09^ methodContents",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "methodContents:",
+category: 'accessing',
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@methodContents"]=aString;
+return self}, function($ctx1) {$ctx1.fill(self,"methodContents:",{aString:aString},smalltalk.HLSourceCodeWidget)})},
+args: ["aString"],
+source: "methodContents: aString\x0a\x09methodContents := aString",
+messageSends: [],
 referencedClasses: []
 }),
 smalltalk.HLSourceCodeWidget);
@@ -1154,6 +1209,10 @@ function $HLParseErrorRaised(){return smalltalk.HLParseErrorRaised||(typeof HLPa
 function $HLCompileErrorRaised(){return smalltalk.HLCompileErrorRaised||(typeof HLCompileErrorRaised=="undefined"?nil:HLCompileErrorRaised)}
 function $HLUnknownVariableErrorRaised(){return smalltalk.HLUnknownVariableErrorRaised||(typeof HLUnknownVariableErrorRaised=="undefined"?nil:HLUnknownVariableErrorRaised)}
 function $HLInstVarAdded(){return smalltalk.HLInstVarAdded||(typeof HLInstVarAdded=="undefined"?nil:HLInstVarAdded)}
+function $HLMethodSelected(){return smalltalk.HLMethodSelected||(typeof HLMethodSelected=="undefined"?nil:HLMethodSelected)}
+function $HLClassSelected(){return smalltalk.HLClassSelected||(typeof HLClassSelected=="undefined"?nil:HLClassSelected)}
+function $HLProtocolSelected(){return smalltalk.HLProtocolSelected||(typeof HLProtocolSelected=="undefined"?nil:HLProtocolSelected)}
+function $HLSourceCodeFocusRequested(){return smalltalk.HLSourceCodeFocusRequested||(typeof HLSourceCodeFocusRequested=="undefined"?nil:HLSourceCodeFocusRequested)}
 return smalltalk.withContext(function($ctx1) { 
 var $1,$2;
 $1=_st(_st(self)._browserModel())._announcer();
@@ -1173,15 +1232,97 @@ _st($1)._on_do_($HLUnknownVariableErrorRaised(),(function(ann){
 return smalltalk.withContext(function($ctx2) {
 return _st(self)._onUnknownVariableError_(_st(ann)._error());
 }, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
-$2=_st($1)._on_do_($HLInstVarAdded(),(function(ann){
+_st($1)._on_do_($HLInstVarAdded(),(function(ann){
 return smalltalk.withContext(function($ctx2) {
 return _st(self)._onInstVarAdded();
 }, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+_st($1)._on_do_($HLMethodSelected(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onMethodSelected_(_st(ann)._item());
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+_st($1)._on_do_($HLClassSelected(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onClassSelected_(_st(ann)._item());
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+_st($1)._on_do_($HLProtocolSelected(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onProtocolSelected_(_st(ann)._item());
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+$2=_st($1)._on_do_($HLSourceCodeFocusRequested(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onSourceCodeFocusRequested();
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"observeBrowserModel",{},smalltalk.HLSourceCodeWidget)})},
 args: [],
-source: "observeBrowserModel\x0a\x09self browserModel announcer\x0a\x09\x09on: HLSaveSourceCode\x0a\x09\x09do: [ :ann | self onSaveIt ];\x0a\x09\x09on: HLParseErrorRaised\x0a\x09\x09do: [ :ann | self onParseError: ann ];\x0a\x09\x09on: HLCompileErrorRaised\x0a\x09\x09do: [ :ann | self onCompileError: ann error ];\x0a\x09\x09on: HLUnknownVariableErrorRaised\x0a\x09\x09do: [ :ann | self onUnknownVariableError: ann error ];\x0a\x09\x09on: HLInstVarAdded \x0a\x09\x09do: [ :ann | self onInstVarAdded ]",
-messageSends: ["on:do:", "onSaveIt", "announcer", "browserModel", "onParseError:", "onCompileError:", "error", "onUnknownVariableError:", "onInstVarAdded"],
-referencedClasses: ["HLSaveSourceCode", "HLParseErrorRaised", "HLCompileErrorRaised", "HLUnknownVariableErrorRaised", "HLInstVarAdded"]
+source: "observeBrowserModel\x0a\x09self browserModel announcer\x0a\x09\x09on: HLSaveSourceCode\x0a\x09\x09do: [ :ann | self onSaveIt ];\x0a\x09\x09on: HLParseErrorRaised\x0a\x09\x09do: [ :ann | self onParseError: ann ];\x0a\x09\x09on: HLCompileErrorRaised\x0a\x09\x09do: [ :ann | self onCompileError: ann error ];\x0a\x09\x09on: HLUnknownVariableErrorRaised\x0a\x09\x09do: [ :ann | self onUnknownVariableError: ann error ];\x0a\x09\x09on: HLInstVarAdded \x0a\x09\x09do: [ :ann | self onInstVarAdded ];\x0a\x09\x09on: HLMethodSelected \x0a\x09\x09do: [ :ann | self onMethodSelected: ann item ];\x0a    \x09on: HLClassSelected \x0a\x09\x09do: [ :ann | self onClassSelected: ann item ];\x0a    \x09on: HLProtocolSelected \x0a\x09\x09do: [ :ann | self onProtocolSelected: ann item ];\x0a\x09\x09on: HLSourceCodeFocusRequested \x0a\x09\x09do: [ :ann | self onSourceCodeFocusRequested ]",
+messageSends: ["on:do:", "onSaveIt", "announcer", "browserModel", "onParseError:", "onCompileError:", "error", "onUnknownVariableError:", "onInstVarAdded", "onMethodSelected:", "item", "onClassSelected:", "onProtocolSelected:", "onSourceCodeFocusRequested"],
+referencedClasses: ["HLSaveSourceCode", "HLParseErrorRaised", "HLCompileErrorRaised", "HLUnknownVariableErrorRaised", "HLInstVarAdded", "HLMethodSelected", "HLClassSelected", "HLProtocolSelected", "HLSourceCodeFocusRequested"]
+}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "observeSystem",
+category: 'actions',
+fn: function (){
+var self=this;
+function $MethodModified(){return smalltalk.MethodModified||(typeof MethodModified=="undefined"?nil:MethodModified)}
+function $HLMethodSelected(){return smalltalk.HLMethodSelected||(typeof HLMethodSelected=="undefined"?nil:HLMethodSelected)}
+function $HLClassSelected(){return smalltalk.HLClassSelected||(typeof HLClassSelected=="undefined"?nil:HLClassSelected)}
+function $HLProtocolSelected(){return smalltalk.HLProtocolSelected||(typeof HLProtocolSelected=="undefined"?nil:HLProtocolSelected)}
+function $HLSourceCodeFocusRequested(){return smalltalk.HLSourceCodeFocusRequested||(typeof HLSourceCodeFocusRequested=="undefined"?nil:HLSourceCodeFocusRequested)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=_st(_st(self)._browserModel())._systemAnnouncer();
+_st($1)._on_do_($MethodModified(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onMethodModified_(_st(ann)._method());
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+_st($1)._on_do_($HLMethodSelected(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onMethodSelected_(_st(ann)._item());
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+_st($1)._on_do_($HLClassSelected(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onClassSelected_(_st(ann)._item());
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+_st($1)._on_do_($HLProtocolSelected(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onProtocolSelected_(_st(ann)._item());
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+$2=_st($1)._on_do_($HLSourceCodeFocusRequested(),(function(ann){
+return smalltalk.withContext(function($ctx2) {
+return _st(self)._onSourceCodeFocusRequested();
+}, function($ctx2) {$ctx2.fillBlock({ann:ann},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"observeSystem",{},smalltalk.HLSourceCodeWidget)})},
+args: [],
+source: "observeSystem\x0a\x09self browserModel systemAnnouncer\x0a    \x09on: MethodModified\x0a        do: [ :ann | self onMethodModified: ann method ];\x0a\x09\x09on: HLMethodSelected \x0a\x09\x09do: [ :ann | self onMethodSelected: ann item ];\x0a    \x09on: HLClassSelected \x0a\x09\x09do: [ :ann | self onClassSelected: ann item ];\x0a    \x09on: HLProtocolSelected \x0a\x09\x09do: [ :ann | self onProtocolSelected: ann item ];\x0a\x09\x09on: HLSourceCodeFocusRequested \x0a\x09\x09do: [ :ann | self onSourceCodeFocusRequested ]",
+messageSends: ["on:do:", "onMethodModified:", "method", "systemAnnouncer", "browserModel", "onMethodSelected:", "item", "onClassSelected:", "onProtocolSelected:", "onSourceCodeFocusRequested"],
+referencedClasses: ["MethodModified", "HLMethodSelected", "HLClassSelected", "HLProtocolSelected", "HLSourceCodeFocusRequested"]
+}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "onClassSelected:",
+category: 'reactions',
+fn: function (aClass){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=aClass;
+if(($receiver = $1) == nil || $receiver == undefined){
+$2=_st(self)._contents_("");
+return $2;
+} else {
+$1;
+};
+_st(self)._contents_(_st(aClass)._definition());
+return self}, function($ctx1) {$ctx1.fill(self,"onClassSelected:",{aClass:aClass},smalltalk.HLSourceCodeWidget)})},
+args: ["aClass"],
+source: "onClassSelected: aClass\x0a\x09aClass ifNil: [ ^ self contents: '' ].\x0a    \x0a    self contents: aClass definition",
+messageSends: ["ifNil:", "contents:", "definition"],
+referencedClasses: []
 }),
 smalltalk.HLSourceCodeWidget);
 
@@ -1217,6 +1358,64 @@ referencedClasses: []
 }),
 smalltalk.HLSourceCodeWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "onMethodModified:",
+category: 'reactions',
+fn: function (aMethod){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2,$3,$4,$5,$6;
+$1=_st(_st(_st(self)._browserModel())._selectedClass()).__eq(_st(aMethod)._methodClass());
+if(! smalltalk.assert($1)){
+$2=self;
+return $2;
+};
+$3=_st(_st(self)._browserModel())._selectedMethod();
+if(($receiver = $3) == nil || $receiver == undefined){
+$4=self;
+return $4;
+} else {
+$3;
+};
+$5=_st(_st(_st(_st(self)._browserModel())._selectedMethod())._selector()).__eq(_st(aMethod)._selector());
+if(! smalltalk.assert($5)){
+$6=self;
+return $6;
+};
+_st(self)._refresh();
+return self}, function($ctx1) {$ctx1.fill(self,"onMethodModified:",{aMethod:aMethod},smalltalk.HLSourceCodeWidget)})},
+args: ["aMethod"],
+source: "onMethodModified: aMethod\x0a\x09self browserModel selectedClass = aMethod methodClass ifFalse: [ ^ self ].\x0a\x09self browserModel selectedMethod ifNil: [ ^ self ].\x0a    self browserModel selectedMethod selector = aMethod selector ifFalse: [ ^ self ].\x0a\x0a    self refresh",
+messageSends: ["ifFalse:", "=", "methodClass", "selectedClass", "browserModel", "ifNil:", "selectedMethod", "selector", "refresh"],
+referencedClasses: []
+}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "onMethodSelected:",
+category: 'reactions',
+fn: function (aCompiledMethod){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=aCompiledMethod;
+if(($receiver = $1) == nil || $receiver == undefined){
+$2=_st(self)._contents_("");
+return $2;
+} else {
+$1;
+};
+_st(self)._contents_(_st(aCompiledMethod)._source());
+return self}, function($ctx1) {$ctx1.fill(self,"onMethodSelected:",{aCompiledMethod:aCompiledMethod},smalltalk.HLSourceCodeWidget)})},
+args: ["aCompiledMethod"],
+source: "onMethodSelected: aCompiledMethod\x0a\x09aCompiledMethod ifNil: [ ^ self contents: '' ].\x0a    \x0a    self contents: aCompiledMethod source",
+messageSends: ["ifNil:", "contents:", "source"],
+referencedClasses: []
+}),
+smalltalk.HLSourceCodeWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "onParseError:",
@@ -1257,6 +1456,30 @@ referencedClasses: ["String"]
 }),
 smalltalk.HLSourceCodeWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "onProtocolSelected:",
+category: 'reactions',
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=_st(_st(self)._browserModel())._selectedClass();
+if(($receiver = $1) == nil || $receiver == undefined){
+$2=_st(self)._contents_("");
+return $2;
+} else {
+$1;
+};
+_st(self)._contents_(_st(_st(_st(self)._browserModel())._selectedClass())._definition());
+return self}, function($ctx1) {$ctx1.fill(self,"onProtocolSelected:",{aString:aString},smalltalk.HLSourceCodeWidget)})},
+args: ["aString"],
+source: "onProtocolSelected: aString\x0a\x09self browserModel selectedClass ifNil: [ ^ self contents: '' ].\x0a    \x0a    self contents: self browserModel selectedClass definition",
+messageSends: ["ifNil:", "contents:", "selectedClass", "browserModel", "definition"],
+referencedClasses: []
+}),
+smalltalk.HLSourceCodeWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "onSaveIt",
@@ -1267,12 +1490,28 @@ return smalltalk.withContext(function($ctx1) {
 _st(_st(self)._browserModel())._save_(_st(self)._contents());
 return self}, function($ctx1) {$ctx1.fill(self,"onSaveIt",{},smalltalk.HLSourceCodeWidget)})},
 args: [],
-source: "onSaveIt\x0a\x09self  browserModel save: self contents",
+source: "onSaveIt\x0a\x09self browserModel save: self contents",
 messageSends: ["save:", "contents", "browserModel"],
 referencedClasses: []
 }),
 smalltalk.HLSourceCodeWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "onSourceCodeFocusRequested",
+category: 'reactions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(self)._focus();
+return self}, function($ctx1) {$ctx1.fill(self,"onSourceCodeFocusRequested",{},smalltalk.HLSourceCodeWidget)})},
+args: [],
+source: "onSourceCodeFocusRequested\x0a\x09self focus",
+messageSends: ["focus"],
+referencedClasses: []
+}),
+smalltalk.HLSourceCodeWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "onUnknownVariableError:",
@@ -1305,6 +1544,63 @@ referencedClasses: ["String"]
 }),
 smalltalk.HLSourceCodeWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "previous",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return self}, function($ctx1) {$ctx1.fill(self,"previous",{},smalltalk.HLSourceCodeWidget)})},
+args: [],
+source: "previous\x0a\x09\x22for browser lists widget\x22",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "previous:",
+category: 'accessing',
+fn: function (aWidget){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return self}, function($ctx1) {$ctx1.fill(self,"previous:",{aWidget:aWidget},smalltalk.HLSourceCodeWidget)})},
+args: ["aWidget"],
+source: "previous: aWidget\x0a\x09\x22for browser lists widget\x22",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLSourceCodeWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "refresh",
+category: 'actions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2,$3,$4;
+$1=_st(self)._hasModification();
+if(smalltalk.assert($1)){
+$2=self;
+return $2;
+};
+$3=_st(self)._hasFocus();
+if(smalltalk.assert($3)){
+$4=self;
+return $4;
+};
+_st(self)._contents_(_st(_st(_st(self)._model())._selectedMethod())._source());
+return self}, function($ctx1) {$ctx1.fill(self,"refresh",{},smalltalk.HLSourceCodeWidget)})},
+args: [],
+source: "refresh\x0a\x09self hasModification ifTrue: [ ^ self ].\x0a    self hasFocus ifTrue: [ ^ self ].\x0a\x0a\x09self contents: self model selectedMethod source",
+messageSends: ["ifTrue:", "hasModification", "hasFocus", "contents:", "source", "selectedMethod", "model"],
+referencedClasses: []
+}),
+smalltalk.HLSourceCodeWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "saveIt",

+ 11 - 0
js/Kernel-Classes.deploy.js

@@ -328,6 +328,17 @@ return self}, function($ctx1) {$ctx1.fill(self,"instanceVariableNames",{},smallt
 messageSends: []}),
 smalltalk.Behavior);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isBehavior",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return true;
+}, function($ctx1) {$ctx1.fill(self,"isBehavior",{},smalltalk.Behavior)})},
+messageSends: []}),
+smalltalk.Behavior);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "lookupSelector:",

+ 16 - 0
js/Kernel-Classes.js

@@ -429,6 +429,22 @@ referencedClasses: []
 }),
 smalltalk.Behavior);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isBehavior",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return true;
+}, function($ctx1) {$ctx1.fill(self,"isBehavior",{},smalltalk.Behavior)})},
+args: [],
+source: "isBehavior\x0a\x09^ true",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Behavior);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "lookupSelector:",

+ 11 - 0
js/Kernel-Objects.deploy.js

@@ -351,6 +351,17 @@ return self}, function($ctx1) {$ctx1.fill(self,"instVarAt:put:",{aString:aString
 messageSends: []}),
 smalltalk.Object);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isBehavior",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return false;
+}, function($ctx1) {$ctx1.fill(self,"isBehavior",{},smalltalk.Object)})},
+messageSends: []}),
+smalltalk.Object);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "isBoolean",

+ 16 - 0
js/Kernel-Objects.js

@@ -487,6 +487,22 @@ referencedClasses: []
 }),
 smalltalk.Object);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isBehavior",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return false;
+}, function($ctx1) {$ctx1.fill(self,"isBehavior",{},smalltalk.Object)})},
+args: [],
+source: "isBehavior\x0a\x09^ false",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Object);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "isBoolean",

+ 1454 - 0
js/lib/showdown.js

@@ -0,0 +1,1454 @@
+//
+// showdown.js -- A javascript port of Markdown.
+//
+// Copyright (c) 2007 John Fraser.
+//
+// Original Markdown Copyright (c) 2004-2005 John Gruber
+//   <http://daringfireball.net/projects/markdown/>
+//
+// Redistributable under a BSD-style open source license.
+// See license.txt for more information.
+//
+// The full source distribution is at:
+//
+//				A A L
+//				T C A
+//				T K B
+//
+//   <http://www.attacklab.net/>
+//
+
+//
+// Wherever possible, Showdown is a straight, line-by-line port
+// of the Perl version of Markdown.
+//
+// This is not a normal parser design; it's basically just a
+// series of string substitutions.  It's hard to read and
+// maintain this way,  but keeping Showdown close to the original
+// design makes it easier to port new features.
+//
+// More importantly, Showdown behaves like markdown.pl in most
+// edge cases.  So web applications can do client-side preview
+// in Javascript, and then build identical HTML on the server.
+//
+// This port needs the new RegExp functionality of ECMA 262,
+// 3rd Edition (i.e. Javascript 1.5).  Most modern web browsers
+// should do fine.  Even with the new regular expression features,
+// We do a lot of work to emulate Perl's regex functionality.
+// The tricky changes in this file mostly have the "attacklab:"
+// label.  Major or self-explanatory changes don't.
+//
+// Smart diff tools like Araxis Merge will be able to match up
+// this file with markdown.pl in a useful way.  A little tweaking
+// helps: in a copy of markdown.pl, replace "#" with "//" and
+// replace "$text" with "text".  Be sure to ignore whitespace
+// and line endings.
+//
+
+
+//
+// Showdown usage:
+//
+//   var text = "Markdown *rocks*.";
+//
+//   var converter = new Showdown.converter();
+//   var html = converter.makeHtml(text);
+//
+//   alert(html);
+//
+// Note: move the sample code to the bottom of this
+// file before uncommenting it.
+//
+
+
+//
+// Showdown namespace
+//
+var Showdown = { extensions: {} };
+
+//
+// forEach
+//
+var forEach = Showdown.forEach = function(obj, callback) {
+	if (typeof obj.forEach === 'function') {
+		obj.forEach(callback);
+	} else {
+		var i, len = obj.length;
+		for (i = 0; i < len; i++) {
+			callback(obj[i], i, obj);
+		}
+	}
+};
+
+//
+// Standard extension naming
+//
+var stdExtName = function(s) {
+	return s.replace(/[_-]||\s/g, '').toLowerCase();
+};
+
+//
+// converter
+//
+// Wraps all "globals" so that the only thing
+// exposed is makeHtml().
+//
+Showdown.converter = function(converter_options) {
+
+//
+// Globals:
+//
+
+// Global hashes, used by various utility routines
+var g_urls;
+var g_titles;
+var g_html_blocks;
+
+// Used to track when we're inside an ordered or unordered list
+// (see _ProcessListItems() for details):
+var g_list_level = 0;
+
+// Global extensions
+var g_lang_extensions = [];
+var g_output_modifiers = [];
+
+
+//
+// Automatic Extension Loading (node only):
+//
+
+if (typeof module !== 'undefind' && typeof exports !== 'undefined' && typeof require !== 'undefind') {
+	var fs = require('fs');
+
+	if (fs) {
+		// Search extensions folder
+		var extensions = fs.readdirSync((__dirname || '.')+'/extensions').filter(function(file){
+			return ~file.indexOf('.js');
+		}).map(function(file){
+			return file.replace(/\.js$/, '');
+		});
+		// Load extensions into Showdown namespace
+		Showdown.forEach(extensions, function(ext){
+			var name = stdExtName(ext);
+			Showdown.extensions[name] = require('./extensions/' + ext);
+		});
+	}
+}
+
+this.makeHtml = function(text) {
+//
+// Main function. The order in which other subs are called here is
+// essential. Link and image substitutions need to happen before
+// _EscapeSpecialCharsWithinTagAttributes(), so that any *'s or _'s in the <a>
+// and <img> tags get encoded.
+//
+
+	// Clear the global hashes. If we don't clear these, you get conflicts
+	// from other articles when generating a page which contains more than
+	// one article (e.g. an index page that shows the N most recent
+	// articles):
+	g_urls = {};
+	g_titles = {};
+	g_html_blocks = [];
+
+	// attacklab: Replace ~ with ~T
+	// This lets us use tilde as an escape char to avoid md5 hashes
+	// The choice of character is arbitray; anything that isn't
+	// magic in Markdown will work.
+	text = text.replace(/~/g,"~T");
+
+	// attacklab: Replace $ with ~D
+	// RegExp interprets $ as a special character
+	// when it's in a replacement string
+	text = text.replace(/\$/g,"~D");
+
+	// Standardize line endings
+	text = text.replace(/\r\n/g,"\n"); // DOS to Unix
+	text = text.replace(/\r/g,"\n"); // Mac to Unix
+
+	// Make sure text begins and ends with a couple of newlines:
+	text = "\n\n" + text + "\n\n";
+
+	// Convert all tabs to spaces.
+	text = _Detab(text);
+
+	// Strip any lines consisting only of spaces and tabs.
+	// This makes subsequent regexen easier to write, because we can
+	// match consecutive blank lines with /\n+/ instead of something
+	// contorted like /[ \t]*\n+/ .
+	text = text.replace(/^[ \t]+$/mg,"");
+
+	// Run language extensions
+	Showdown.forEach(g_lang_extensions, function(x){
+		text = _ExecuteExtension(x, text);
+	});
+
+	// Handle github codeblocks prior to running HashHTML so that
+	// HTML contained within the codeblock gets escaped propertly
+	text = _DoGithubCodeBlocks(text);
+
+	// Turn block-level HTML blocks into hash entries
+	text = _HashHTMLBlocks(text);
+
+	// Strip link definitions, store in hashes.
+	text = _StripLinkDefinitions(text);
+
+	text = _RunBlockGamut(text);
+
+	text = _UnescapeSpecialChars(text);
+
+	// attacklab: Restore dollar signs
+	text = text.replace(/~D/g,"$$");
+
+	// attacklab: Restore tildes
+	text = text.replace(/~T/g,"~");
+
+	// Run output modifiers
+	Showdown.forEach(g_output_modifiers, function(x){
+		text = _ExecuteExtension(x, text);
+	});
+
+	return text;
+};
+//
+// Options:
+//
+
+// Parse extensions options into separate arrays
+if (converter_options && converter_options.extensions) {
+
+  var self = this;
+
+	// Iterate over each plugin
+	Showdown.forEach(converter_options.extensions, function(plugin){
+
+		// Assume it's a bundled plugin if a string is given
+		if (typeof plugin === 'string') {
+			plugin = Showdown.extensions[stdExtName(plugin)];
+		}
+
+		if (typeof plugin === 'function') {
+			// Iterate over each extension within that plugin
+			Showdown.forEach(plugin(self), function(ext){
+				// Sort extensions by type
+				if (ext.type) {
+					if (ext.type === 'language' || ext.type === 'lang') {
+						g_lang_extensions.push(ext);
+					} else if (ext.type === 'output' || ext.type === 'html') {
+						g_output_modifiers.push(ext);
+					}
+				} else {
+					// Assume language extension
+					g_output_modifiers.push(ext);
+				}
+			});
+		} else {
+			throw "Extension '" + plugin + "' could not be loaded.  It was either not found or is not a valid extension.";
+		}
+	});
+}
+
+
+var _ExecuteExtension = function(ext, text) {
+	if (ext.regex) {
+		var re = new RegExp(ext.regex, 'g');
+		return text.replace(re, ext.replace);
+	} else if (ext.filter) {
+		return ext.filter(text);
+	}
+};
+
+var _StripLinkDefinitions = function(text) {
+//
+// Strips link definitions from text, stores the URLs and titles in
+// hash references.
+//
+
+	// Link defs are in the form: ^[id]: url "optional title"
+
+	/*
+		var text = text.replace(/
+				^[ ]{0,3}\[(.+)\]:  // id = $1  attacklab: g_tab_width - 1
+				  [ \t]*
+				  \n?				// maybe *one* newline
+				  [ \t]*
+				<?(\S+?)>?			// url = $2
+				  [ \t]*
+				  \n?				// maybe one newline
+				  [ \t]*
+				(?:
+				  (\n*)				// any lines skipped = $3 attacklab: lookbehind removed
+				  ["(]
+				  (.+?)				// title = $4
+				  [")]
+				  [ \t]*
+				)?					// title is optional
+				(?:\n+|$)
+			  /gm,
+			  function(){...});
+	*/
+
+	// attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
+	text += "~0";
+
+	text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|(?=~0))/gm,
+		function (wholeMatch,m1,m2,m3,m4) {
+			m1 = m1.toLowerCase();
+			g_urls[m1] = _EncodeAmpsAndAngles(m2);  // Link IDs are case-insensitive
+			if (m3) {
+				// Oops, found blank lines, so it's not a title.
+				// Put back the parenthetical statement we stole.
+				return m3+m4;
+			} else if (m4) {
+				g_titles[m1] = m4.replace(/"/g,"&quot;");
+			}
+
+			// Completely remove the definition from the text
+			return "";
+		}
+	);
+
+	// attacklab: strip sentinel
+	text = text.replace(/~0/,"");
+
+	return text;
+}
+
+
+var _HashHTMLBlocks = function(text) {
+	// attacklab: Double up blank lines to reduce lookaround
+	text = text.replace(/\n/g,"\n\n");
+
+	// Hashify HTML blocks:
+	// We only want to do this for block-level HTML tags, such as headers,
+	// lists, and tables. That's because we still want to wrap <p>s around
+	// "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+	// phrase emphasis, and spans. The list of tags we're looking for is
+	// hard-coded:
+	var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del|style|section|header|footer|nav|article|aside";
+	var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside";
+
+	// First, look for nested blocks, e.g.:
+	//   <div>
+	//     <div>
+	//     tags for inner block must be indented.
+	//     </div>
+	//   </div>
+	//
+	// The outermost tags must start at the left margin for this to match, and
+	// the inner nested divs must be indented.
+	// We need to do this before the next, more liberal match, because the next
+	// match will start at the first `<div>` and stop at the first `</div>`.
+
+	// attacklab: This regex can be expensive when it fails.
+	/*
+		var text = text.replace(/
+		(						// save in $1
+			^					// start of line  (with /m)
+			<($block_tags_a)	// start tag = $2
+			\b					// word break
+								// attacklab: hack around khtml/pcre bug...
+			[^\r]*?\n			// any number of lines, minimally matching
+			</\2>				// the matching end tag
+			[ \t]*				// trailing spaces/tabs
+			(?=\n+)				// followed by a newline
+		)						// attacklab: there are sentinel newlines at end of document
+		/gm,function(){...}};
+	*/
+	text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,hashElement);
+
+	//
+	// Now match more liberally, simply from `\n<tag>` to `</tag>\n`
+	//
+
+	/*
+		var text = text.replace(/
+		(						// save in $1
+			^					// start of line  (with /m)
+			<($block_tags_b)	// start tag = $2
+			\b					// word break
+								// attacklab: hack around khtml/pcre bug...
+			[^\r]*?				// any number of lines, minimally matching
+			</\2>				// the matching end tag
+			[ \t]*				// trailing spaces/tabs
+			(?=\n+)				// followed by a newline
+		)						// attacklab: there are sentinel newlines at end of document
+		/gm,function(){...}};
+	*/
+	text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside)\b[^\r]*?<\/\2>[ \t]*(?=\n+)\n)/gm,hashElement);
+
+	// Special case just for <hr />. It was easier to make a special case than
+	// to make the other regex more complicated.
+
+	/*
+		text = text.replace(/
+		(						// save in $1
+			\n\n				// Starting after a blank line
+			[ ]{0,3}
+			(<(hr)				// start tag = $2
+			\b					// word break
+			([^<>])*?			//
+			\/?>)				// the matching end tag
+			[ \t]*
+			(?=\n{2,})			// followed by a blank line
+		)
+		/g,hashElement);
+	*/
+	text = text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,hashElement);
+
+	// Special case for standalone HTML comments:
+
+	/*
+		text = text.replace(/
+		(						// save in $1
+			\n\n				// Starting after a blank line
+			[ ]{0,3}			// attacklab: g_tab_width - 1
+			<!
+			(--[^\r]*?--\s*)+
+			>
+			[ \t]*
+			(?=\n{2,})			// followed by a blank line
+		)
+		/g,hashElement);
+	*/
+	text = text.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,hashElement);
+
+	// PHP and ASP-style processor instructions (<?...?> and <%...%>)
+
+	/*
+		text = text.replace(/
+		(?:
+			\n\n				// Starting after a blank line
+		)
+		(						// save in $1
+			[ ]{0,3}			// attacklab: g_tab_width - 1
+			(?:
+				<([?%])			// $2
+				[^\r]*?
+				\2>
+			)
+			[ \t]*
+			(?=\n{2,})			// followed by a blank line
+		)
+		/g,hashElement);
+	*/
+	text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,hashElement);
+
+	// attacklab: Undo double lines (see comment at top of this function)
+	text = text.replace(/\n\n/g,"\n");
+	return text;
+}
+
+var hashElement = function(wholeMatch,m1) {
+	var blockText = m1;
+
+	// Undo double lines
+	blockText = blockText.replace(/\n\n/g,"\n");
+	blockText = blockText.replace(/^\n/,"");
+
+	// strip trailing blank lines
+	blockText = blockText.replace(/\n+$/g,"");
+
+	// Replace the element text with a marker ("~KxK" where x is its key)
+	blockText = "\n\n~K" + (g_html_blocks.push(blockText)-1) + "K\n\n";
+
+	return blockText;
+};
+
+var _RunBlockGamut = function(text) {
+//
+// These are all the transformations that form block-level
+// tags like paragraphs, headers, and list items.
+//
+	text = _DoHeaders(text);
+
+	// Do Horizontal Rules:
+	var key = hashBlock("<hr />");
+	text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,key);
+	text = text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,key);
+	text = text.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,key);
+
+	text = _DoLists(text);
+	text = _DoCodeBlocks(text);
+	text = _DoBlockQuotes(text);
+
+	// We already ran _HashHTMLBlocks() before, in Markdown(), but that
+	// was to escape raw HTML in the original Markdown source. This time,
+	// we're escaping the markup we've just created, so that we don't wrap
+	// <p> tags around block-level tags.
+	text = _HashHTMLBlocks(text);
+	text = _FormParagraphs(text);
+
+	return text;
+};
+
+
+var _RunSpanGamut = function(text) {
+//
+// These are all the transformations that occur *within* block-level
+// tags like paragraphs, headers, and list items.
+//
+
+	text = _DoCodeSpans(text);
+	text = _EscapeSpecialCharsWithinTagAttributes(text);
+	text = _EncodeBackslashEscapes(text);
+
+	// Process anchor and image tags. Images must come first,
+	// because ![foo][f] looks like an anchor.
+	text = _DoImages(text);
+	text = _DoAnchors(text);
+
+	// Make links out of things like `<http://example.com/>`
+	// Must come after _DoAnchors(), because you can use < and >
+	// delimiters in inline links like [this](<url>).
+	text = _DoAutoLinks(text);
+	text = _EncodeAmpsAndAngles(text);
+	text = _DoItalicsAndBold(text);
+
+	// Do hard breaks:
+	text = text.replace(/  +\n/g," <br />\n");
+
+	return text;
+}
+
+var _EscapeSpecialCharsWithinTagAttributes = function(text) {
+//
+// Within tags -- meaning between < and > -- encode [\ ` * _] so they
+// don't conflict with their use in Markdown for code, italics and strong.
+//
+
+	// Build a regex to find HTML tags and comments.  See Friedl's
+	// "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
+	var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;
+
+	text = text.replace(regex, function(wholeMatch) {
+		var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g,"$1`");
+		tag = escapeCharacters(tag,"\\`*_");
+		return tag;
+	});
+
+	return text;
+}
+
+var _DoAnchors = function(text) {
+//
+// Turn Markdown link shortcuts into XHTML <a> tags.
+//
+	//
+	// First, handle reference-style links: [link text] [id]
+	//
+
+	/*
+		text = text.replace(/
+		(							// wrap whole match in $1
+			\[
+			(
+				(?:
+					\[[^\]]*\]		// allow brackets nested one level
+					|
+					[^\[]			// or anything else
+				)*
+			)
+			\]
+
+			[ ]?					// one optional space
+			(?:\n[ ]*)?				// one optional newline followed by spaces
+
+			\[
+			(.*?)					// id = $3
+			\]
+		)()()()()					// pad remaining backreferences
+		/g,_DoAnchors_callback);
+	*/
+	text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeAnchorTag);
+
+	//
+	// Next, inline-style links: [link text](url "optional title")
+	//
+
+	/*
+		text = text.replace(/
+			(						// wrap whole match in $1
+				\[
+				(
+					(?:
+						\[[^\]]*\]	// allow brackets nested one level
+					|
+					[^\[\]]			// or anything else
+				)
+			)
+			\]
+			\(						// literal paren
+			[ \t]*
+			()						// no id, so leave $3 empty
+			<?(.*?)>?				// href = $4
+			[ \t]*
+			(						// $5
+				(['"])				// quote char = $6
+				(.*?)				// Title = $7
+				\6					// matching quote
+				[ \t]*				// ignore any spaces/tabs between closing quote and )
+			)?						// title is optional
+			\)
+		)
+		/g,writeAnchorTag);
+	*/
+	text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?(?:\(.*?\).*?)?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeAnchorTag);
+
+	//
+	// Last, handle reference-style shortcuts: [link text]
+	// These must come last in case you've also got [link test][1]
+	// or [link test](/foo)
+	//
+
+	/*
+		text = text.replace(/
+		(		 					// wrap whole match in $1
+			\[
+			([^\[\]]+)				// link text = $2; can't contain '[' or ']'
+			\]
+		)()()()()()					// pad rest of backreferences
+		/g, writeAnchorTag);
+	*/
+	text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag);
+
+	return text;
+}
+
+var writeAnchorTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) {
+	if (m7 == undefined) m7 = "";
+	var whole_match = m1;
+	var link_text   = m2;
+	var link_id	 = m3.toLowerCase();
+	var url		= m4;
+	var title	= m7;
+
+	if (url == "") {
+		if (link_id == "") {
+			// lower-case and turn embedded newlines into spaces
+			link_id = link_text.toLowerCase().replace(/ ?\n/g," ");
+		}
+		url = "#"+link_id;
+
+		if (g_urls[link_id] != undefined) {
+			url = g_urls[link_id];
+			if (g_titles[link_id] != undefined) {
+				title = g_titles[link_id];
+			}
+		}
+		else {
+			if (whole_match.search(/\(\s*\)$/m)>-1) {
+				// Special case for explicit empty url
+				url = "";
+			} else {
+				return whole_match;
+			}
+		}
+	}
+
+	url = escapeCharacters(url,"*_");
+	var result = "<a href=\"" + url + "\"";
+
+	if (title != "") {
+		title = title.replace(/"/g,"&quot;");
+		title = escapeCharacters(title,"*_");
+		result +=  " title=\"" + title + "\"";
+	}
+
+	result += ">" + link_text + "</a>";
+
+	return result;
+}
+
+
+var _DoImages = function(text) {
+//
+// Turn Markdown image shortcuts into <img> tags.
+//
+
+	//
+	// First, handle reference-style labeled images: ![alt text][id]
+	//
+
+	/*
+		text = text.replace(/
+		(						// wrap whole match in $1
+			!\[
+			(.*?)				// alt text = $2
+			\]
+
+			[ ]?				// one optional space
+			(?:\n[ ]*)?			// one optional newline followed by spaces
+
+			\[
+			(.*?)				// id = $3
+			\]
+		)()()()()				// pad rest of backreferences
+		/g,writeImageTag);
+	*/
+	text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeImageTag);
+
+	//
+	// Next, handle inline images:  ![alt text](url "optional title")
+	// Don't forget: encode * and _
+
+	/*
+		text = text.replace(/
+		(						// wrap whole match in $1
+			!\[
+			(.*?)				// alt text = $2
+			\]
+			\s?					// One optional whitespace character
+			\(					// literal paren
+			[ \t]*
+			()					// no id, so leave $3 empty
+			<?(\S+?)>?			// src url = $4
+			[ \t]*
+			(					// $5
+				(['"])			// quote char = $6
+				(.*?)			// title = $7
+				\6				// matching quote
+				[ \t]*
+			)?					// title is optional
+		\)
+		)
+		/g,writeImageTag);
+	*/
+	text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeImageTag);
+
+	return text;
+}
+
+var writeImageTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) {
+	var whole_match = m1;
+	var alt_text   = m2;
+	var link_id	 = m3.toLowerCase();
+	var url		= m4;
+	var title	= m7;
+
+	if (!title) title = "";
+
+	if (url == "") {
+		if (link_id == "") {
+			// lower-case and turn embedded newlines into spaces
+			link_id = alt_text.toLowerCase().replace(/ ?\n/g," ");
+		}
+		url = "#"+link_id;
+
+		if (g_urls[link_id] != undefined) {
+			url = g_urls[link_id];
+			if (g_titles[link_id] != undefined) {
+				title = g_titles[link_id];
+			}
+		}
+		else {
+			return whole_match;
+		}
+	}
+
+	alt_text = alt_text.replace(/"/g,"&quot;");
+	url = escapeCharacters(url,"*_");
+	var result = "<img src=\"" + url + "\" alt=\"" + alt_text + "\"";
+
+	// attacklab: Markdown.pl adds empty title attributes to images.
+	// Replicate this bug.
+
+	//if (title != "") {
+		title = title.replace(/"/g,"&quot;");
+		title = escapeCharacters(title,"*_");
+		result +=  " title=\"" + title + "\"";
+	//}
+
+	result += " />";
+
+	return result;
+}
+
+
+var _DoHeaders = function(text) {
+
+	// Setext-style headers:
+	//	Header 1
+	//	========
+	//
+	//	Header 2
+	//	--------
+	//
+	text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,
+		function(wholeMatch,m1){return hashBlock('<h1 id="' + headerId(m1) + '">' + _RunSpanGamut(m1) + "</h1>");});
+
+	text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,
+		function(matchFound,m1){return hashBlock('<h2 id="' + headerId(m1) + '">' + _RunSpanGamut(m1) + "</h2>");});
+
+	// atx-style headers:
+	//  # Header 1
+	//  ## Header 2
+	//  ## Header 2 with closing hashes ##
+	//  ...
+	//  ###### Header 6
+	//
+
+	/*
+		text = text.replace(/
+			^(\#{1,6})				// $1 = string of #'s
+			[ \t]*
+			(.+?)					// $2 = Header text
+			[ \t]*
+			\#*						// optional closing #'s (not counted)
+			\n+
+		/gm, function() {...});
+	*/
+
+	text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,
+		function(wholeMatch,m1,m2) {
+			var h_level = m1.length;
+			return hashBlock("<h" + h_level + ' id="' + headerId(m2) + '">' + _RunSpanGamut(m2) + "</h" + h_level + ">");
+		});
+
+	function headerId(m) {
+		return m.replace(/[^\w]/g, '').toLowerCase();
+	}
+	return text;
+}
+
+// This declaration keeps Dojo compressor from outputting garbage:
+var _ProcessListItems;
+
+var _DoLists = function(text) {
+//
+// Form HTML ordered (numbered) and unordered (bulleted) lists.
+//
+
+	// attacklab: add sentinel to hack around khtml/safari bug:
+	// http://bugs.webkit.org/show_bug.cgi?id=11231
+	text += "~0";
+
+	// Re-usable pattern to match any entirel ul or ol list:
+
+	/*
+		var whole_list = /
+		(									// $1 = whole list
+			(								// $2
+				[ ]{0,3}					// attacklab: g_tab_width - 1
+				([*+-]|\d+[.])				// $3 = first list item marker
+				[ \t]+
+			)
+			[^\r]+?
+			(								// $4
+				~0							// sentinel for workaround; should be $
+			|
+				\n{2,}
+				(?=\S)
+				(?!							// Negative lookahead for another list item marker
+					[ \t]*
+					(?:[*+-]|\d+[.])[ \t]+
+				)
+			)
+		)/g
+	*/
+	var whole_list = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
+
+	if (g_list_level) {
+		text = text.replace(whole_list,function(wholeMatch,m1,m2) {
+			var list = m1;
+			var list_type = (m2.search(/[*+-]/g)>-1) ? "ul" : "ol";
+
+			// Turn double returns into triple returns, so that we can make a
+			// paragraph for the last item in a list, if necessary:
+			list = list.replace(/\n{2,}/g,"\n\n\n");;
+			var result = _ProcessListItems(list);
+
+			// Trim any trailing whitespace, to put the closing `</$list_type>`
+			// up on the preceding line, to get it past the current stupid
+			// HTML block parser. This is a hack to work around the terrible
+			// hack that is the HTML block parser.
+			result = result.replace(/\s+$/,"");
+			result = "<"+list_type+">" + result + "</"+list_type+">\n";
+			return result;
+		});
+	} else {
+		whole_list = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;
+		text = text.replace(whole_list,function(wholeMatch,m1,m2,m3) {
+			var runup = m1;
+			var list = m2;
+
+			var list_type = (m3.search(/[*+-]/g)>-1) ? "ul" : "ol";
+			// Turn double returns into triple returns, so that we can make a
+			// paragraph for the last item in a list, if necessary:
+			var list = list.replace(/\n{2,}/g,"\n\n\n");;
+			var result = _ProcessListItems(list);
+			result = runup + "<"+list_type+">\n" + result + "</"+list_type+">\n";
+			return result;
+		});
+	}
+
+	// attacklab: strip sentinel
+	text = text.replace(/~0/,"");
+
+	return text;
+}
+
+_ProcessListItems = function(list_str) {
+//
+//  Process the contents of a single ordered or unordered list, splitting it
+//  into individual list items.
+//
+	// The $g_list_level global keeps track of when we're inside a list.
+	// Each time we enter a list, we increment it; when we leave a list,
+	// we decrement. If it's zero, we're not in a list anymore.
+	//
+	// We do this because when we're not inside a list, we want to treat
+	// something like this:
+	//
+	//    I recommend upgrading to version
+	//    8. Oops, now this line is treated
+	//    as a sub-list.
+	//
+	// As a single paragraph, despite the fact that the second line starts
+	// with a digit-period-space sequence.
+	//
+	// Whereas when we're inside a list (or sub-list), that line will be
+	// treated as the start of a sub-list. What a kludge, huh? This is
+	// an aspect of Markdown's syntax that's hard to parse perfectly
+	// without resorting to mind-reading. Perhaps the solution is to
+	// change the syntax rules such that sub-lists must start with a
+	// starting cardinal number; e.g. "1." or "a.".
+
+	g_list_level++;
+
+	// trim trailing blank lines:
+	list_str = list_str.replace(/\n{2,}$/,"\n");
+
+	// attacklab: add sentinel to emulate \z
+	list_str += "~0";
+
+	/*
+		list_str = list_str.replace(/
+			(\n)?							// leading line = $1
+			(^[ \t]*)						// leading whitespace = $2
+			([*+-]|\d+[.]) [ \t]+			// list marker = $3
+			([^\r]+?						// list item text   = $4
+			(\n{1,2}))
+			(?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+))
+		/gm, function(){...});
+	*/
+	list_str = list_str.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,
+		function(wholeMatch,m1,m2,m3,m4){
+			var item = m4;
+			var leading_line = m1;
+			var leading_space = m2;
+
+			if (leading_line || (item.search(/\n{2,}/)>-1)) {
+				item = _RunBlockGamut(_Outdent(item));
+			}
+			else {
+				// Recursion for sub-lists:
+				item = _DoLists(_Outdent(item));
+				item = item.replace(/\n$/,""); // chomp(item)
+				item = _RunSpanGamut(item);
+			}
+
+			return  "<li>" + item + "</li>\n";
+		}
+	);
+
+	// attacklab: strip sentinel
+	list_str = list_str.replace(/~0/g,"");
+
+	g_list_level--;
+	return list_str;
+}
+
+
+var _DoCodeBlocks = function(text) {
+//
+//  Process Markdown `<pre><code>` blocks.
+//
+
+	/*
+		text = text.replace(text,
+			/(?:\n\n|^)
+			(								// $1 = the code block -- one or more lines, starting with a space/tab
+				(?:
+					(?:[ ]{4}|\t)			// Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
+					.*\n+
+				)+
+			)
+			(\n*[ ]{0,3}[^ \t\n]|(?=~0))	// attacklab: g_tab_width
+		/g,function(){...});
+	*/
+
+	// attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
+	text += "~0";
+
+	text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
+		function(wholeMatch,m1,m2) {
+			var codeblock = m1;
+			var nextChar = m2;
+
+			codeblock = _EncodeCode( _Outdent(codeblock));
+			codeblock = _Detab(codeblock);
+			codeblock = codeblock.replace(/^\n+/g,""); // trim leading newlines
+			codeblock = codeblock.replace(/\n+$/g,""); // trim trailing whitespace
+
+			codeblock = "<pre><code>" + codeblock + "\n</code></pre>";
+
+			return hashBlock(codeblock) + nextChar;
+		}
+	);
+
+	// attacklab: strip sentinel
+	text = text.replace(/~0/,"");
+
+	return text;
+};
+
+var _DoGithubCodeBlocks = function(text) {
+//
+//  Process Github-style code blocks
+//  Example:
+//  ```ruby
+//  def hello_world(x)
+//    puts "Hello, #{x}"
+//  end
+//  ```
+//
+
+
+	// attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
+	text += "~0";
+
+	text = text.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g,
+		function(wholeMatch,m1,m2) {
+			var language = m1;
+			var codeblock = m2;
+
+			codeblock = _EncodeCode(codeblock);
+			codeblock = _Detab(codeblock);
+			codeblock = codeblock.replace(/^\n+/g,""); // trim leading newlines
+			codeblock = codeblock.replace(/\n+$/g,""); // trim trailing whitespace
+
+			codeblock = "<pre><code" + (language ? " class=\"" + language + '"' : "") + ">" + codeblock + "\n</code></pre>";
+
+			return hashBlock(codeblock);
+		}
+	);
+
+	// attacklab: strip sentinel
+	text = text.replace(/~0/,"");
+
+	return text;
+}
+
+var hashBlock = function(text) {
+	text = text.replace(/(^\n+|\n+$)/g,"");
+	return "\n\n~K" + (g_html_blocks.push(text)-1) + "K\n\n";
+}
+
+var _DoCodeSpans = function(text) {
+//
+//   *  Backtick quotes are used for <code></code> spans.
+//
+//   *  You can use multiple backticks as the delimiters if you want to
+//	 include literal backticks in the code span. So, this input:
+//
+//		 Just type ``foo `bar` baz`` at the prompt.
+//
+//	   Will translate to:
+//
+//		 <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
+//
+//	There's no arbitrary limit to the number of backticks you
+//	can use as delimters. If you need three consecutive backticks
+//	in your code, use four for delimiters, etc.
+//
+//  *  You can use spaces to get literal backticks at the edges:
+//
+//		 ... type `` `bar` `` ...
+//
+//	   Turns to:
+//
+//		 ... type <code>`bar`</code> ...
+//
+
+	/*
+		text = text.replace(/
+			(^|[^\\])					// Character before opening ` can't be a backslash
+			(`+)						// $2 = Opening run of `
+			(							// $3 = The code block
+				[^\r]*?
+				[^`]					// attacklab: work around lack of lookbehind
+			)
+			\2							// Matching closer
+			(?!`)
+		/gm, function(){...});
+	*/
+
+	text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
+		function(wholeMatch,m1,m2,m3,m4) {
+			var c = m3;
+			c = c.replace(/^([ \t]*)/g,"");	// leading whitespace
+			c = c.replace(/[ \t]*$/g,"");	// trailing whitespace
+			c = _EncodeCode(c);
+			return m1+"<code>"+c+"</code>";
+		});
+
+	return text;
+}
+
+var _EncodeCode = function(text) {
+//
+// Encode/escape certain characters inside Markdown code runs.
+// The point is that in code, these characters are literals,
+// and lose their special Markdown meanings.
+//
+	// Encode all ampersands; HTML entities are not
+	// entities within a Markdown code span.
+	text = text.replace(/&/g,"&amp;");
+
+	// Do the angle bracket song and dance:
+	text = text.replace(/</g,"&lt;");
+	text = text.replace(/>/g,"&gt;");
+
+	// Now, escape characters that are magic in Markdown:
+	text = escapeCharacters(text,"\*_{}[]\\",false);
+
+// jj the line above breaks this:
+//---
+
+//* Item
+
+//   1. Subitem
+
+//            special char: *
+//---
+
+	return text;
+}
+
+
+var _DoItalicsAndBold = function(text) {
+
+	// <strong> must go first:
+	text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,
+		"<strong>$2</strong>");
+
+	text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,
+		"<em>$2</em>");
+
+	return text;
+}
+
+
+var _DoBlockQuotes = function(text) {
+
+	/*
+		text = text.replace(/
+		(								// Wrap whole match in $1
+			(
+				^[ \t]*>[ \t]?			// '>' at the start of a line
+				.+\n					// rest of the first line
+				(.+\n)*					// subsequent consecutive lines
+				\n*						// blanks
+			)+
+		)
+		/gm, function(){...});
+	*/
+
+	text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,
+		function(wholeMatch,m1) {
+			var bq = m1;
+
+			// attacklab: hack around Konqueror 3.5.4 bug:
+			// "----------bug".replace(/^-/g,"") == "bug"
+
+			bq = bq.replace(/^[ \t]*>[ \t]?/gm,"~0");	// trim one level of quoting
+
+			// attacklab: clean up hack
+			bq = bq.replace(/~0/g,"");
+
+			bq = bq.replace(/^[ \t]+$/gm,"");		// trim whitespace-only lines
+			bq = _RunBlockGamut(bq);				// recurse
+
+			bq = bq.replace(/(^|\n)/g,"$1  ");
+			// These leading spaces screw with <pre> content, so we need to fix that:
+			bq = bq.replace(
+					/(\s*<pre>[^\r]+?<\/pre>)/gm,
+				function(wholeMatch,m1) {
+					var pre = m1;
+					// attacklab: hack around Konqueror 3.5.4 bug:
+					pre = pre.replace(/^  /mg,"~0");
+					pre = pre.replace(/~0/g,"");
+					return pre;
+				});
+
+			return hashBlock("<blockquote>\n" + bq + "\n</blockquote>");
+		});
+	return text;
+}
+
+
+var _FormParagraphs = function(text) {
+//
+//  Params:
+//    $text - string to process with html <p> tags
+//
+
+	// Strip leading and trailing lines:
+	text = text.replace(/^\n+/g,"");
+	text = text.replace(/\n+$/g,"");
+
+	var grafs = text.split(/\n{2,}/g);
+	var grafsOut = [];
+
+	//
+	// Wrap <p> tags.
+	//
+	var end = grafs.length;
+	for (var i=0; i<end; i++) {
+		var str = grafs[i];
+
+		// if this is an HTML marker, copy it
+		if (str.search(/~K(\d+)K/g) >= 0) {
+			grafsOut.push(str);
+		}
+		else if (str.search(/\S/) >= 0) {
+			str = _RunSpanGamut(str);
+			str = str.replace(/^([ \t]*)/g,"<p>");
+			str += "</p>"
+			grafsOut.push(str);
+		}
+
+	}
+
+	//
+	// Unhashify HTML blocks
+	//
+	end = grafsOut.length;
+	for (var i=0; i<end; i++) {
+		// if this is a marker for an html block...
+		while (grafsOut[i].search(/~K(\d+)K/) >= 0) {
+			var blockText = g_html_blocks[RegExp.$1];
+			blockText = blockText.replace(/\$/g,"$$$$"); // Escape any dollar signs
+			grafsOut[i] = grafsOut[i].replace(/~K\d+K/,blockText);
+		}
+	}
+
+	return grafsOut.join("\n\n");
+}
+
+
+var _EncodeAmpsAndAngles = function(text) {
+// Smart processing for ampersands and angle brackets that need to be encoded.
+
+	// Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
+	//   http://bumppo.net/projects/amputator/
+	text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&amp;");
+
+	// Encode naked <'s
+	text = text.replace(/<(?![a-z\/?\$!])/gi,"&lt;");
+
+	return text;
+}
+
+
+var _EncodeBackslashEscapes = function(text) {
+//
+//   Parameter:  String.
+//   Returns:	The string, with after processing the following backslash
+//			   escape sequences.
+//
+
+	// attacklab: The polite way to do this is with the new
+	// escapeCharacters() function:
+	//
+	// 	text = escapeCharacters(text,"\\",true);
+	// 	text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
+	//
+	// ...but we're sidestepping its use of the (slow) RegExp constructor
+	// as an optimization for Firefox.  This function gets called a LOT.
+
+	text = text.replace(/\\(\\)/g,escapeCharacters_callback);
+	text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g,escapeCharacters_callback);
+	return text;
+}
+
+
+var _DoAutoLinks = function(text) {
+
+	text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,"<a href=\"$1\">$1</a>");
+
+	// Email addresses: <address@domain.foo>
+
+	/*
+		text = text.replace(/
+			<
+			(?:mailto:)?
+			(
+				[-.\w]+
+				\@
+				[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
+			)
+			>
+		/gi, _DoAutoLinks_callback());
+	*/
+	text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
+		function(wholeMatch,m1) {
+			return _EncodeEmailAddress( _UnescapeSpecialChars(m1) );
+		}
+	);
+
+	return text;
+}
+
+
+var _EncodeEmailAddress = function(addr) {
+//
+//  Input: an email address, e.g. "foo@example.com"
+//
+//  Output: the email address as a mailto link, with each character
+//	of the address encoded as either a decimal or hex entity, in
+//	the hopes of foiling most address harvesting spam bots. E.g.:
+//
+//	<a href="&#x6D;&#97;&#105;&#108;&#x74;&#111;:&#102;&#111;&#111;&#64;&#101;
+//	   x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;">&#102;&#111;&#111;
+//	   &#64;&#101;x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;</a>
+//
+//  Based on a filter by Matthew Wickline, posted to the BBEdit-Talk
+//  mailing list: <http://tinyurl.com/yu7ue>
+//
+
+	var encode = [
+		function(ch){return "&#"+ch.charCodeAt(0)+";";},
+		function(ch){return "&#x"+ch.charCodeAt(0).toString(16)+";";},
+		function(ch){return ch;}
+	];
+
+	addr = "mailto:" + addr;
+
+	addr = addr.replace(/./g, function(ch) {
+		if (ch == "@") {
+		   	// this *must* be encoded. I insist.
+			ch = encode[Math.floor(Math.random()*2)](ch);
+		} else if (ch !=":") {
+			// leave ':' alone (to spot mailto: later)
+			var r = Math.random();
+			// roughly 10% raw, 45% hex, 45% dec
+			ch =  (
+					r > .9  ?	encode[2](ch)   :
+					r > .45 ?	encode[1](ch)   :
+								encode[0](ch)
+				);
+		}
+		return ch;
+	});
+
+	addr = "<a href=\"" + addr + "\">" + addr + "</a>";
+	addr = addr.replace(/">.+:/g,"\">"); // strip the mailto: from the visible part
+
+	return addr;
+}
+
+
+var _UnescapeSpecialChars = function(text) {
+//
+// Swap back in all the special characters we've hidden.
+//
+	text = text.replace(/~E(\d+)E/g,
+		function(wholeMatch,m1) {
+			var charCodeToReplace = parseInt(m1);
+			return String.fromCharCode(charCodeToReplace);
+		}
+	);
+	return text;
+}
+
+
+var _Outdent = function(text) {
+//
+// Remove one level of line-leading tabs or spaces
+//
+
+	// attacklab: hack around Konqueror 3.5.4 bug:
+	// "----------bug".replace(/^-/g,"") == "bug"
+
+	text = text.replace(/^(\t|[ ]{1,4})/gm,"~0"); // attacklab: g_tab_width
+
+	// attacklab: clean up hack
+	text = text.replace(/~0/g,"")
+
+	return text;
+}
+
+var _Detab = function(text) {
+// attacklab: Detab's completely rewritten for speed.
+// In perl we could fix it by anchoring the regexp with \G.
+// In javascript we're less fortunate.
+
+	// expand first n-1 tabs
+	text = text.replace(/\t(?=\t)/g,"    "); // attacklab: g_tab_width
+
+	// replace the nth with two sentinels
+	text = text.replace(/\t/g,"~A~B");
+
+	// use the sentinel to anchor our regex so it doesn't explode
+	text = text.replace(/~B(.+?)~A/g,
+		function(wholeMatch,m1,m2) {
+			var leadingText = m1;
+			var numSpaces = 4 - leadingText.length % 4;  // attacklab: g_tab_width
+
+			// there *must* be a better way to do this:
+			for (var i=0; i<numSpaces; i++) leadingText+=" ";
+
+			return leadingText;
+		}
+	);
+
+	// clean up sentinels
+	text = text.replace(/~A/g,"    ");  // attacklab: g_tab_width
+	text = text.replace(/~B/g,"");
+
+	return text;
+}
+
+
+//
+//  attacklab: Utility functions
+//
+
+
+var escapeCharacters = function(text, charsToEscape, afterBackslash) {
+	// First we have to escape the escape characters so that
+	// we can build a character class out of them
+	var regexString = "([" + charsToEscape.replace(/([\[\]\\])/g,"\\$1") + "])";
+
+	if (afterBackslash) {
+		regexString = "\\\\" + regexString;
+	}
+
+	var regex = new RegExp(regexString,"g");
+	text = text.replace(regex,escapeCharacters_callback);
+
+	return text;
+}
+
+
+var escapeCharacters_callback = function(wholeMatch,m1) {
+	var charCodeToEscape = m1.charCodeAt(0);
+	return "~E"+charCodeToEscape+"E";
+}
+
+} // end of Showdown.converter
+
+
+// export
+if (typeof module !== 'undefined') module.exports = Showdown;
+
+// stolen from AMD branch of underscore
+// AMD define happens at the end for compatibility with AMD loaders
+// that don't enforce next-turn semantics on modules.
+if (typeof define === 'function' && define.amd) {
+    define('showdown', function() {
+        return Showdown;
+    });
+}

+ 52 - 152
st/Helios-Browser.st

@@ -68,7 +68,7 @@ classesListWidget
 methodsListWidget
 	^ methodsListWidget ifNil: [
       	methodsListWidget := HLMethodsListWidget on: self model.
-		methodsListWidget next: self sourceWidget]
+		methodsListWidget next: self sourceWidget ]
 !
 
 packagesListWidget
@@ -85,7 +85,9 @@ protocolsListWidget
 
 sourceWidget
 	^ sourceWidget ifNil: [
-      	sourceWidget := HLBrowserSourceWidget on: self model ]
+      	sourceWidget := HLSourceCodeWidget new
+			browserModel: self model;
+			yourself ]
 ! !
 
 HLBrowser class instanceVariableNames: 'nextId'!
@@ -235,8 +237,18 @@ label
 	^ 'Classes'
 !
 
+showClass
+	^ self model showInstance not and: [
+		self model showComment not ]
+!
+
+showComment
+	^ self model showComment
+!
+
 showInstance
-	^ self model showInstance
+	^ self model showInstance and: [
+		self model showComment not ]
 ! !
 
 !HLClassesListWidget methodsFor: 'actions'!
@@ -269,6 +281,10 @@ selectItem: aClass
     self model selectedClass: aClass
 !
 
+showComment: aBoolean
+	self model showComment: aBoolean
+!
+
 showInstance: aBoolean
 	self model showInstance: aBoolean
 ! !
@@ -344,16 +360,23 @@ renderButtonsOn: html
                 class: (String streamContents: [ :str |
                 	str nextPutAll: 'btn'.
                     self showInstance ifTrue: [ 
-                    	str nextPutAll: ' active'] ]);
+                    	str nextPutAll: ' active' ] ]);
   				with: 'Instance';
                 onClick: [ self showInstance: true ].
   			html button
   				class: (String streamContents: [ :str |
                 	str nextPutAll: 'btn'.
-                    self model showInstance ifFalse: [ 
-                    	str nextPutAll: ' active'] ]);
+                    self showClass ifTrue: [ 
+                    	str nextPutAll: ' active' ] ]);
   				with: 'Class';
-				onClick: [ self model showInstance: false ] ]
+				onClick: [ self showInstance: false ].
+			html button
+  				class: (String streamContents: [ :str |
+                	str nextPutAll: 'btn'.
+                    self showComment ifTrue: [ 
+                    	str nextPutAll: ' active' ] ]);
+  				with: 'Doc';
+				onClick: [ self showComment: true ] ]
 !
 
 renderItem: aClass level: anInteger on: html
@@ -797,6 +820,14 @@ availableClassNames
 	^ self environment availableClassNames
 !
 
+availablePackageNames
+	^ self environment availablePackageNames
+!
+
+availablePackages
+	^ self environment availablePackageNames
+!
+
 availableProtocols
 	^ self environment availableProtocolsFor: self selectedClass
 !
@@ -891,7 +922,7 @@ showComment
 
 showComment: aBoolean
 	showComment := aBoolean.
-    
+
     self announcer announce: HLShowCommentToggled new
 !
 
@@ -901,7 +932,8 @@ showInstance
 
 showInstance: aBoolean
 	showInstance := aBoolean.
-    
+	showComment := false.
+
     self selectedClass ifNotNil: [
     	self selectedClass: (aBoolean
     		ifTrue: [self selectedClass theNonMetaClass ]
@@ -962,6 +994,12 @@ commitPackage
 		do: [ self environment commitPackage: self selectedPackage ]
 !
 
+moveClassToPackage: aPackageName
+	self environment 
+		moveClass: self selectedClass theNonMetaClass
+		toPackage: aPackageName
+!
+
 moveMethodToClass: aClassName
 	self environment 
 		moveMethod: self selectedMethod 
@@ -980,6 +1018,11 @@ openClassNamed: aString
 	self selectedClass: class
 !
 
+removeClass
+	(self manager confirm: 'Do you REALLY want to remove class ', self selectedClass name)
+		ifTrue: [ self environment removeClass: self selectedClass ]
+!
+
 removeMethod
 	(self manager confirm: 'Do you REALLY want to remove method ', self selectedMethod methodClass name,' >> #', self selectedMethod selector)
 		ifTrue: [ self environment removeMethod: self selectedMethod ]
@@ -1105,149 +1148,6 @@ on: anEnvironment
         yourself
 ! !
 
-HLWidget subclass: #HLBrowserSourceWidget
-	instanceVariableNames: 'model methodContents codeWidget'
-	package: 'Helios-Browser'!
-
-!HLBrowserSourceWidget methodsFor: 'accessing'!
-
-codeWidget
-	^ codeWidget ifNil: [ codeWidget := HLSourceCodeWidget on: self model ]
-!
-
-contents
-	^ self codeWidget contents
-!
-
-contents: aString
-	self methodContents: aString.
-	self codeWidget contents: aString
-!
-
-methodContents
-	^ methodContents ifNil: [ methodContents := '' ]
-!
-
-methodContents: aString
-	methodContents := aString
-!
-
-model
-	^ model
-!
-
-model: aBrowserModel
-	model := aBrowserModel.
-    
-    self observeModel
-!
-
-previous
-	"for browser lists widget"
-!
-
-previous: aWidget
-	"for browser lists widget"
-! !
-
-!HLBrowserSourceWidget methodsFor: 'actions'!
-
-focus
-	self codeWidget focus
-!
-
-observeModel
-	self model announcer 
-		on: HLMethodSelected 
-		do: [ :ann | self onMethodSelected: ann item ];
-    	on: HLClassSelected 
-		do: [ :ann | self onClassSelected: ann item ];
-    	on: HLProtocolSelected 
-		do: [ :ann | self onProtocolSelected: ann item ];
-		on: HLSourceCodeFocusRequested 
-		do: [ :ann | self onSourceCodeFocusRequested ]
-!
-
-observeSystem
-	SystemAnnouncer current
-    	on: MethodModified
-        do: [ :ann | self onMethodModified: ann method ]
-! !
-
-!HLBrowserSourceWidget methodsFor: 'initialization'!
-
-initialize
-	super initialize.
-    
-    self observeSystem
-! !
-
-!HLBrowserSourceWidget methodsFor: 'reactions'!
-
-onClassSelected: aClass
-	aClass ifNil: [ ^ self contents: '' ].
-    
-    self contents: aClass definition
-!
-
-onMethodModified: aMethod
-
-	self model selectedClass = aMethod methodClass ifFalse: [ ^ self ].
-	self model selectedMethod ifNil: [ ^ self ].
-    self model selectedMethod selector = aMethod selector ifFalse: [ ^ self ].
-
-    self refresh
-!
-
-onMethodSelected: aCompiledMethod
-	aCompiledMethod ifNil: [ ^ self contents: '' ].
-    
-    self contents: aCompiledMethod source
-!
-
-onProtocolSelected: aString
-	self model selectedClass ifNil: [ ^ self contents: '' ].
-    
-    self contents: self model selectedClass definition
-!
-
-onSourceCodeFocusRequested
-	self focus
-! !
-
-!HLBrowserSourceWidget methodsFor: 'rendering'!
-
-renderContentOn: html
-	self codeWidget renderOn: html
-! !
-
-!HLBrowserSourceWidget methodsFor: 'testing'!
-
-hasFocus
-	^ self codeWidget hasFocus
-!
-
-hasModification
-	^ (self methodContents = self contents) not
-! !
-
-!HLBrowserSourceWidget methodsFor: 'updating'!
-
-refresh
-	self hasModification ifTrue: [ ^ self ].
-    self hasFocus ifTrue: [ ^ self ].
-
-	self contents: self model selectedMethod source
-! !
-
-!HLBrowserSourceWidget class methodsFor: 'instance creation'!
-
-on: aBrowserModel
-	^ self new
-    	model: aBrowserModel;
-        yourself
-! !
-
 Object subclass: #HLClassCache
 	instanceVariableNames: 'class selectorsCache overrideCache overriddenCache'
 	package: 'Helios-Browser'!

+ 132 - 4
st/Helios-Commands-Browser.st

@@ -236,6 +236,76 @@ label
 	^ 'Move'
 ! !
 
+HLMoveToCommand subclass: #HLMoveClassToCommand
+	instanceVariableNames: ''
+	package: 'Helios-Commands-Browser'!
+
+!HLMoveClassToCommand methodsFor: 'testing'!
+
+isActive
+	^ self model selectedClass notNil
+! !
+
+!HLMoveClassToCommand class methodsFor: 'accessing'!
+
+key
+	^ 67
+!
+
+label
+	^ 'Class'
+! !
+
+HLMoveClassToCommand subclass: #HLMoveClassCommand
+	instanceVariableNames: ''
+	package: 'Helios-Commands-Browser'!
+
+!HLMoveClassCommand methodsFor: 'accessing'!
+
+displayLabel
+	^ 'select a package'
+!
+
+inputCompletion
+	^ self model availablePackageNames
+!
+
+inputLabel
+	^ 'Move class to package:'
+! !
+
+!HLMoveClassCommand methodsFor: 'executing'!
+
+execute
+	self model moveClassToPackage: self input
+! !
+
+!HLMoveClassCommand methodsFor: 'testing'!
+
+isInputRequired
+	^ true
+! !
+
+!HLMoveClassCommand class methodsFor: 'accessing'!
+
+key
+	^ 80
+!
+
+label
+	^ 'to package'
+!
+
+menuLabel	
+	^ 'Move to package...'
+! !
+
+!HLMoveClassCommand class methodsFor: 'testing'!
+
+isValidFor: anObject
+	^ anObject isBehavior
+! !
+
 HLMoveToCommand subclass: #HLMoveMethodToCommand
 	instanceVariableNames: ''
 	package: 'Helios-Commands-Browser'!
@@ -370,6 +440,42 @@ label
 	^ 'Remove'
 ! !
 
+HLRemoveCommand subclass: #HLRemoveClassCommand
+	instanceVariableNames: ''
+	package: 'Helios-Commands-Browser'!
+
+!HLRemoveClassCommand methodsFor: 'executing'!
+
+execute
+	self model removeClass
+! !
+
+!HLRemoveClassCommand methodsFor: 'testing'!
+
+isActive
+	^ self model selectedClass notNil
+! !
+
+!HLRemoveClassCommand class methodsFor: 'accessing'!
+
+key
+	^ 67
+!
+
+label
+	^ 'Class'
+!
+
+menuLabel
+	^ 'Remove class'
+! !
+
+!HLRemoveClassCommand class methodsFor: 'testing'!
+
+isValidFor: anObject
+	^ anObject isBehavior
+! !
+
 HLRemoveCommand subclass: #HLRemoveMethodCommand
 	instanceVariableNames: ''
 	package: 'Helios-Commands-Browser'!
@@ -388,8 +494,8 @@ isActive
 
 !HLRemoveMethodCommand class methodsFor: 'accessing'!
 
-isValidFor: anObject
-	^ anObject isCompiledMethod
+key
+	^ 77
 !
 
 label
@@ -402,8 +508,8 @@ menuLabel
 
 !HLRemoveMethodCommand class methodsFor: 'testing'!
 
-key
-	^ 77
+isValidFor: anObject
+	^ anObject isCompiledMethod
 ! !
 
 HLBrowserCommand subclass: #HLToggleCommand
@@ -420,6 +526,28 @@ label
 	^ 'Toggle'
 ! !
 
+HLToggleCommand subclass: #HLToggleClassCommentCommand
+	instanceVariableNames: ''
+	package: 'Helios-Commands-Browser'!
+
+!HLToggleClassCommentCommand methodsFor: 'executing'!
+
+execute
+	self model showComment: true
+! !
+
+!HLToggleClassCommentCommand class methodsFor: 'accessing'!
+
+key
+	"d"
+    
+	^ 68
+!
+
+label
+	^ 'Documentation'
+! !
+
 HLToggleCommand subclass: #HLToggleClassSideCommand
 	instanceVariableNames: ''
 	package: 'Helios-Commands-Browser'!

+ 19 - 23
st/Helios-Core.st

@@ -47,8 +47,7 @@ widget: aWidget
 !HLTab methodsFor: 'actions'!
 
 hide
-	root ifNotNil: [
-		root asJQuery hide ]
+	root ifNotNil: [ root asJQuery css: 'visibility' put: 'hidden' ]
 !
 
 registerBindings
@@ -62,7 +61,7 @@ remove
 show
 	root
 		ifNil: [ self appendToJQuery: 'body' asJQuery ]
-		ifNotNil: [ root asJQuery show ]
+		ifNotNil: [ root asJQuery css: 'visibility' put: 'visible' ]
 ! !
 
 !HLTab methodsFor: 'rendering'!
@@ -186,7 +185,7 @@ HLWidget subclass: #HLDebugger
 	package: 'Helios-Core'!
 
 HLWidget subclass: #HLFocusableWidget
-	instanceVariableNames: 'hiddenInput'
+	instanceVariableNames: ''
 	package: 'Helios-Core'!
 
 !HLFocusableWidget methodsFor: 'accessing'!
@@ -198,15 +197,15 @@ focusClass
 !HLFocusableWidget methodsFor: 'events'!
 
 blur
-	hiddenInput asJQuery blur
+	self wrapper asJQuery blur
 !
 
 focus
-	hiddenInput asJQuery focus
+	self wrapper asJQuery focus
 !
 
 hasFocus
-	^ self wrapper notNil and: [ self wrapper asJQuery hasClass: self focusClass ]
+	^ self wrapper notNil and: [ self wrapper asJQuery is: ':focus' ]
 ! !
 
 !HLFocusableWidget methodsFor: 'rendering'!
@@ -214,22 +213,19 @@ hasFocus
 renderContentOn: html
 !
 
-renderHiddenInputOn: html
-	hiddenInput := html input
-    	style: 'position: absolute; left: -100000px;';
-    	onBlur: [ self wrapper asJQuery removeClass: self focusClass ];
-        onFocus: [ self wrapper asJQuery addClass: self focusClass ]
-!
-
 renderOn: html
 	self registerBindings.
-	self renderHiddenInputOn: html.
     
     wrapper := html div 
-    	class: 'hl_widget'; 
-        onClick: [ hiddenInput asJQuery focus ];
-        with: [
-			self renderContentOn: html ]
+    	class: 'hl_widget';
+		yourself.
+		
+       wrapper with: [ self renderContentOn: html ].
+	
+	wrapper
+		at: 'tabindex' put: '0';
+		onBlur: [ self wrapper asJQuery removeClass: self focusClass ];
+        onFocus: [ self wrapper asJQuery addClass: self focusClass ]
 ! !
 
 !HLFocusableWidget methodsFor: 'testing'!
@@ -344,9 +340,9 @@ setupKeyBindings
 	
 	active := false.
 	repeatInterval := 70.
-	hiddenInput asJQuery unbind: 'keydown'.
+	self wrapper asJQuery unbind: 'keydown'.
 
-	hiddenInput asJQuery keydown: [ :e |
+	self wrapper asJQuery keydown: [ :e |
 		
         (e which = 38 and: [ active = false ]) ifTrue: [ 
 			active := true.
@@ -364,7 +360,7 @@ setupKeyBindings
 					valueWithInterval: repeatInterval ]
 						valueWithTimeout: 300 ] ].
 	
-	hiddenInput asJQuery keyup: [ :e |
+	self wrapper asJQuery keyup: [ :e |
 		active ifTrue: [
 			active := false.
 			interval ifNotNil: [ interval clearInterval ].
@@ -468,7 +464,7 @@ previousFocus
 setupKeyBindings
 	super setupKeyBindings.
 
-	hiddenInput asJQuery keydown: [ :e |
+	self wrapper asJQuery keydown: [ :e |
         e which = 39 ifTrue: [ 
         	self nextFocus ].
 		e which = 37 ifTrue: [ 

+ 31 - 0
st/Helios-Environments.st

@@ -11,6 +11,10 @@ availableClassNames
 	self subclassResponsibility
 !
 
+availablePackageNames
+	self subclassResponsibility
+!
+
 availableProtocolsFor: aClass
 	self subclassResponsibility
 !
@@ -42,6 +46,10 @@ eval: someCode on: aReceiver
 	^ self subclassResponsibility
 !
 
+moveClass: aClass toPackage: aPackageName
+	self subclassResponsibility
+!
+
 moveMethod: aMethod toClass: aClassName
 	self subclassResponsibility
 !
@@ -50,6 +58,10 @@ moveMethod: aMethod toProtocol: aProtocol
 	self subclassResponsibility
 !
 
+removeClass: aClass
+	self sublcassResponsibility
+!
+
 removeMethod: aMethod
 	self sublcassResponsibility
 ! !
@@ -89,6 +101,11 @@ availableClassNames
 		collect: [ :each | each name ]
 !
 
+availablePackageNames
+	^ Smalltalk current packages 
+		collect: [ :each | each name ]
+!
+
 availableProtocolsFor: aClass
 	| protocols |
 	
@@ -128,6 +145,16 @@ eval: aString on: aReceiver
 	^ compiler evaluateExpression: aString on: aReceiver
 !
 
+moveClass: aClass toPackage: aPackageName
+	| package |
+	
+	package := Package named: aPackageName.
+	package ifNil: [ self error: 'Invalid package name' ].
+	package == aClass package ifTrue: [ ^ self ].
+	
+	package addClass: aClass
+!
+
 moveMethod: aMethod toClass: aClassName
 	| destinationClass |
 	
@@ -143,6 +170,10 @@ moveMethod: aMethod toProtocol: aProtocol
 	aMethod category: aProtocol
 !
 
+removeClass: aClass
+	Smalltalk current removeClass: aClass
+!
+
 removeMethod: aMethod
 	aMethod methodClass forsakeMethod: aMethod
 ! !

+ 5 - 1
st/Helios-Inspector.st

@@ -312,6 +312,10 @@ announcer
 	^ announcer ifNil:[ announcer := Announcer new ]
 !
 
+label
+	^ self model inspectee class name
+!
+
 model
     ^ model
 !
@@ -374,6 +378,6 @@ renderContentOn: html
 renderHeadOn: html
 	html div 
 		class: 'list-label';
-		with: self model inspectee asString
+		with: self label
 ! !
 

+ 28 - 26
st/Helios-Layout.st

@@ -1,5 +1,5 @@
 Smalltalk current createPackage: 'Helios-Layout'!
-Widget subclass: #HLContainer
+HLWidget subclass: #HLContainer
 	instanceVariableNames: 'splitter'
 	package: 'Helios-Layout'!
 
@@ -18,9 +18,7 @@ splitter: aSplitter
 renderOn: html
 	html div 
     	class: 'tool_container'; 
-        with: self splitter.
-        
-   (window jQuery: window) bind: 'resize' do: [ self splitter resize ]
+        with: self splitter
 ! !
 
 !HLContainer class methodsFor: 'instance creation'!
@@ -69,14 +67,10 @@ renderOn: html
     	splitter := html div class: self cssClass.
     	secondPane := html div class: 'pane'; with: self secondWidget ].
         
-	self 
-    	setupSplitter;
-        resize
+	self setupSplitter
 !
 
 resize
-	self firstWidget isHeliosSplitter ifTrue: [ self firstWidget resize ].
-    self secondWidget isHeliosSplitter ifTrue: [ self secondWidget resize ]
 !
 
 setupSplitter
@@ -114,19 +108,23 @@ panesCssClass
 !HLHorizontalSplitter methodsFor: 'actions'!
 
 resize
-	self resize: splitter asJQuery offset top
+	self resize: (splitter asJQuery css: 'top')
 !
 
 resize: anInteger
-	| container position |
+	| container size offset percentage |
     
     container := firstPane asJQuery parent.
-    position := anInteger - container offset top.
-    
-	firstPane asJQuery height: ((position min: container height - 100) max: 100).
-    secondPane asJQuery height: (((container height - position) min: container height - 100) max: 100) - 1.
-    
-    super resize
+	offset := firstPane asJQuery offset top.
+    size := container height.
+	
+	percentage := (size - (anInteger - offset)) / size * 100.
+	percentage := 80 min: (percentage max: 20).
+	
+    firstPane asJQuery css: 'bottom' put: percentage asString, '%'.
+	
+	splitter asJQuery css: 'top' put: (100 - percentage) asString, '%'.
+	secondPane asJQuery css: 'top' put: (100 - percentage) asString, '%'
 !
 
 startResizing: aSplitter
@@ -161,19 +159,23 @@ panesCssClass
 !HLVerticalSplitter methodsFor: 'actions'!
 
 resize
-	self resize: splitter asJQuery offset left
+	self resize: (splitter asJQuery css: 'left')
 !
 
 resize: anInteger
-	| container position |
+	| container size offset percentage |
     
     container := firstPane asJQuery parent.
-    position := anInteger - container offset left.
-    
-	firstPane asJQuery width: ((position min: container width - 100) max: 100).
-    secondPane asJQuery width: (((container width - position) min: container width - 100) max: 100) - 1.
-    
-    super resize
+	offset := firstPane asJQuery offset left.
+    size := container width.
+	
+	percentage := (size - (anInteger - offset)) / size * 100.
+	percentage := 80 min: (percentage max: 20).
+	
+    firstPane asJQuery css: 'right' put: percentage asString, '%'.
+	
+	splitter asJQuery css: 'left' put: (100 - percentage) asString, '%'.
+	secondPane asJQuery css: 'left' put: (100 - percentage) asString, '%'
 !
 
 startResizing: aSplitter
@@ -188,7 +190,7 @@ setupSplitter
         'containment' -> splitter asJQuery parent.
         'helper' -> 'clone'.
         'start' -> [ :e :ui | self startResizing: ui helper ].
-        'drag' -> [ :e :ui | self resize: ui offset left ] }
+        'drag' -> [ :e :ui | self resize: (ui offset left) ] }
 ! !
 
 !Object methodsFor: '*Helios-Layout'!

+ 87 - 4
st/Helios-Workspace.st

@@ -417,7 +417,7 @@ canBeOpenAsTab
 ! !
 
 HLCodeWidget subclass: #HLSourceCodeWidget
-	instanceVariableNames: 'browserModel'
+	instanceVariableNames: 'browserModel methodContents'
 	package: 'Helios-Workspace'!
 
 !HLSourceCodeWidget methodsFor: 'accessing'!
@@ -428,7 +428,25 @@ browserModel
 
 browserModel: aBrowserModel
 	browserModel := aBrowserModel.
-	self observeBrowserModel
+	self 
+		observeSystem;
+		observeBrowserModel
+!
+
+methodContents
+	^ methodContents
+!
+
+methodContents: aString
+	methodContents := aString
+!
+
+previous
+	"for browser lists widget"
+!
+
+previous: aWidget
+	"for browser lists widget"
 ! !
 
 !HLSourceCodeWidget methodsFor: 'actions'!
@@ -444,7 +462,36 @@ observeBrowserModel
 		on: HLUnknownVariableErrorRaised
 		do: [ :ann | self onUnknownVariableError: ann error ];
 		on: HLInstVarAdded 
-		do: [ :ann | self onInstVarAdded ]
+		do: [ :ann | self onInstVarAdded ];
+		on: HLMethodSelected 
+		do: [ :ann | self onMethodSelected: ann item ];
+    	on: HLClassSelected 
+		do: [ :ann | self onClassSelected: ann item ];
+    	on: HLProtocolSelected 
+		do: [ :ann | self onProtocolSelected: ann item ];
+		on: HLSourceCodeFocusRequested 
+		do: [ :ann | self onSourceCodeFocusRequested ]
+!
+
+observeSystem
+	self browserModel systemAnnouncer
+    	on: MethodModified
+        do: [ :ann | self onMethodModified: ann method ];
+		on: HLMethodSelected 
+		do: [ :ann | self onMethodSelected: ann item ];
+    	on: HLClassSelected 
+		do: [ :ann | self onClassSelected: ann item ];
+    	on: HLProtocolSelected 
+		do: [ :ann | self onProtocolSelected: ann item ];
+		on: HLSourceCodeFocusRequested 
+		do: [ :ann | self onSourceCodeFocusRequested ]
+!
+
+refresh
+	self hasModification ifTrue: [ ^ self ].
+    self hasFocus ifTrue: [ ^ self ].
+
+	self contents: self model selectedMethod source
 !
 
 saveIt
@@ -453,6 +500,12 @@ saveIt
 
 !HLSourceCodeWidget methodsFor: 'reactions'!
 
+onClassSelected: aClass
+	aClass ifNil: [ ^ self contents: '' ].
+    
+    self contents: aClass definition
+!
+
 onCompileError: anError
 	self alert: anError messageText
 !
@@ -461,6 +514,20 @@ onInstVarAdded
 	self  browserModel save: self contents
 !
 
+onMethodModified: aMethod
+	self browserModel selectedClass = aMethod methodClass ifFalse: [ ^ self ].
+	self browserModel selectedMethod ifNil: [ ^ self ].
+    self browserModel selectedMethod selector = aMethod selector ifFalse: [ ^ self ].
+
+    self refresh
+!
+
+onMethodSelected: aCompiledMethod
+	aCompiledMethod ifNil: [ ^ self contents: '' ].
+    
+    self contents: aCompiledMethod source
+!
+
 onParseError: anAnnouncement
 	| lineIndex newContents |
 	
@@ -481,8 +548,18 @@ onParseError: anAnnouncement
 			lineIndex := lineIndex + 1 ] ])
 !
 
+onProtocolSelected: aString
+	self browserModel selectedClass ifNil: [ ^ self contents: '' ].
+    
+    self contents: self browserModel selectedClass definition
+!
+
 onSaveIt
-	self  browserModel save: self contents
+	self browserModel save: self contents
+!
+
+onSourceCodeFocusRequested
+	self focus
 !
 
 onUnknownVariableError: anError
@@ -499,6 +576,12 @@ onUnknownVariableError: anError
 	self browserModel addInstVarNamed: anError variableName
 ! !
 
+!HLSourceCodeWidget methodsFor: 'testing'!
+
+hasModification
+	^ (self methodContents = self contents) not
+! !
+
 !HLSourceCodeWidget class methodsFor: 'instance creation'!
 
 on: aBrowserModel

+ 4 - 0
st/Kernel-Classes.st

@@ -277,6 +277,10 @@ includesSelector: aString
 
 inheritsFrom: aClass
 	^aClass allSubclasses includes: self
+!
+
+isBehavior
+	^ true
 ! !
 
 Behavior subclass: #Class

+ 4 - 0
st/Kernel-Objects.st

@@ -278,6 +278,10 @@ ifNotNil: aBlock ifNil: anotherBlock
 	^aBlock value: self
 !
 
+isBehavior
+	^ false
+!
+
 isBoolean
 	^ false
 !